【环境专家之智能手表】Part12:手表名称和时间的配置
<p><strong><span style="font-size:20px;">1.介绍</span></strong></p><p><span style="font-size:16px;">手表出厂肯定会用同一个固件,那么名字肯定都是一样的,所以每个用户拿到手里会去修改手表的名字,同时手表需要存储数据的话需要自己跑时间戳,这样才能知道自己这条数据时采集至何时,那么说了就开始动手干吧!</span></p>
<p><strong><span style="font-size:20px;">2.下位机设计</span></strong></p>
<p><span style="font-size:16px;">首先还是需要定义协议,在之前的基础之上添加相关的协议,协议内容如下图1:</span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p style="text-align: center;"><span style="font-size:16px;">图1</span></p>
<p><span style="font-size:16px;">首先是修改名字,这里目前最多10字节,一个汉字占用两个字节,十个字节五个汉字基本够大家使用,如果是英文的话,十个字母也是完全足够的。</span></p>
<p><span style="font-size:16px;">设置名字的话,需要先修改一下设置名字的API,在名字的开头添加上【#R】这两个字符,代表着该广播设备为【环境专家之智能手表】,具体修改为如下:</span></p>
<pre>
<code class="language-cpp">void BDK_BLE_SetLocalName(const char* name)
{
uint32_t name_len;
if (ble_env.state == BLE_STATE_OFF)
{
BDK_BLE_Initialize();
}
if (name != NULL)
{
uint8_t name_temp = {'#', 'R'};
memcpy(&name_temp, name, 10);
name_len = 12;
if (name_len <= BDK_BLE_LOCAL_NAME_MAX_LENGTH)
{
memcpy(ble_env.local_name, name_temp, name_len);
ble_env.local_name_len = name_len;
}
}
}</code></pre>
<p><span style="font-size:16px;">当然这个广播名字需要存储在Flash中,这个还是比较简单的,如果Flash中没有名字,则使用默认名字【Downhole】,最终显示在广播中的就是【#RDownhole】,所以名字的初始化如下所示:</span></p>
<pre>
<code class="language-cpp">void phone_communication_init(void)
{
int32_t retval = 0;
//.....
retval = I2CEeprom_Read(BIND_NAME_ADDR, (uint8_t*)watch_name, sizeof(watch_name), &eeprom);
if(watch_name == 0x00)
{
memcpy(watch_name, (uint8_t *)"Downhole", 10); //默认名字
}
//.....
}
</code></pre>
<p>最后就是接收到设置名称的数据时的处理代码了,具体如下:</p>
<pre>
<code class="language-cpp"> case PHONE_SET_NAME:
{
uint8_t send_buff = {PHONE_SET_NAME_ACK, 0};
memcpy(watch_name, &data, 10); //设置广播名字
BDK_BLE_SetLocalName(watch_name);
I2CEeprom_Write(BIND_NAME_ADDR, (uint8_t*)watch_name, sizeof(watch_name), &eeprom);
phone_send_data(send_buff, sizeof(send_buff)); //回复名字设置
break;
}</code></pre>
<p><span style="font-size:16px;">为什么只判断第一位,因为只要设置名字,那么第一位数据肯定不是【0x00】,初始化完成之后,调用设置广播名字的函数即可【BDK_BLE_SetLocalName】。</span></p>
<p><span style="font-size:16px;">接下来是设置时间,设置时间之前肯定需要有一个时间戳能够在手表上跑,所以先定义一个全局变量,存储时间戳,然后定义一个接口用于获取时间戳和让时间戳加一,【add_time_utc】该函数放在一个1S的定时中即可,代码如下:</span></p>
<pre>
<code>my_time_t time_utc = 0;
uint32_t get_time_utc(void)
{
return time_utc;
}
void add_time_utc(void)
{
time_utc++;
}
</code></pre>
<p><span style="font-size:16px;">时间戳不需要掉电存储,为什么呢,因为掉电之后,就算再快上电,时间戳的时间也会比现实时间滞后,而时间错了之后存储的数据是无效的,那么只需要设定开机未设置时间,则不对数据进行存储就可以了。</span></p>
<p><span style="font-size:16px;">所以设置时间和查询时间的解析处理代码如下:</span></p>
<pre>
<code class="language-cpp"> case PHONE_SET_TIME:
{
uint8_t send_buff = {PHONE_SET_TIME_ACK, 0};
struct my_tm t;
t.tm_year = data + 2000;
t.tm_mon= data;
t.tm_mday = data;
t.tm_hour = data;
t.tm_min= data;
t.tm_sec= data;
time_utc = mktime(t);
printf("time_utc:%d\r\n", time_utc);
phone_send_data(send_buff, sizeof(send_buff)); //回复设置状态
break;
}
case PHONE_INQ_TIME:
{
uint8_t send_buff = {PHONE_INQ_TIME_ACK, 0};
struct my_tm t;
localtime(time_utc, &t);
send_buff = t.tm_year - 2000;
send_buff = t.tm_mon;
send_buff = t.tm_mday;
send_buff = t.tm_hour;
send_buff = t.tm_min;
send_buff = t.tm_sec;
phone_send_data(send_buff, sizeof(send_buff)); //发送手表当前时间
break;
}</code></pre>
<p><span style="font-size:16px;">为什么需要查询时间接口呢,主要其实是为了APP连接手表时,自动设置时间,当时间未初始化时,则对时间进行设置,以及手表时间出现误差时对时间的偏移进行校准,这时数据肯定也出现了偏差,知道偏差的时间也可以对数据存储的时间进行校准。</span></p>
<p><strong><span style="font-size:20px;">3.APP设计</span></strong></p>
<p><span style="font-size:16px;">APP主要是界面的设计,因为通信协议还是比较简单的,对于界面的设计流程我就不过多的说明了,直接来看一下设计的结果吧,如下图2所示:</span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p style="text-align: center;"><span style="font-size:16px;">图2</span></p>
<p><span style="font-size:16px;">设置时间时使用了数字滑动控件【NumberPicker】,我个人觉得这样设置时间比较方便,按下【获取手表时间】按钮可以获取手表的当前时间,【设置手表未上方时间】按钮主要是为了调试使用,可以设置手表为任意时间,【设置为手机当前时间】主要是为了方便直接设置手表时间,设置手机当前时间的代码如下:</span></p>
<pre>
<code class="language-java"> //设置当前时间
private void SetTime(){
int year1,year2,month,day,hour,minute,second;
SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
Date curDate =new Date(System.currentTimeMillis());
String thistime = formatter.format(curDate);
//year1 = Integer.valueOf(thistime.substring(0,2)).intValue();
year2 = Integer.valueOf(thistime.substring(2,4)).intValue();
month = Integer.valueOf(thistime.substring(5,7)).intValue();
day = Integer.valueOf(thistime.substring(8,10)).intValue();
hour = Integer.valueOf(thistime.substring(11,13)).intValue();
minute = Integer.valueOf(thistime.substring(14,16)).intValue();
second = Integer.valueOf(thistime.substring(17)).intValue();
byte[] bbb = new byte;
bbb=(byte) 0x05;
bbb=(byte) year2;
bbb=(byte) (month+1);
bbb=(byte) day;
bbb=(byte) hour;
bbb=(byte) minute;
bbb=(byte) second;
Send_Data_Ble(bbb, bbb.length);
//Toast.makeText(mContext, "设置当前时间", Toast.LENGTH_SHORT).show();
}</code></pre>
<p><span style="font-size:16px;">然后就是协议发送和接收部分,这里没有太难的,我就贴出一部分代码:</span></p>
<pre>
<code class="language-java">case 0x06:
if(ReceiveBuff == 0x00) {
ConfigurationStateTextView.setTextColor(0xff0000ff);
ConfigurationStateTextView.setText("设置时间成功!");
}
else {
ConfigurationStateTextView.setTextColor(0xffff0000);
ConfigurationStateTextView.setText("设置时间失败!");
}
break;
case 0x08:
String TimeString = "20" + ReceiveBuff + "-" + ReceiveBuff + "-" + ReceiveBuff + " " + ReceiveBuff + ":" + ReceiveBuff + ":" + ReceiveBuff;
WatchPowerPercentEditText.setText(TimeString);
break;
case 0x0A:
if(ReceiveBuff == 0x00) {
Toast.makeText(mContext, "设置名字成功!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(mContext, "设置名字失败!", Toast.LENGTH_SHORT).show();
}
break;</code></pre>
<p><span style="font-size:16px;">设置名字的效果如下GIF所示:</span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p style="text-align: center;"><span style="font-size:16px;">图3</span></p>
<p><span style="font-size: 16px;">关于时间的操作图下GIF所示:</span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p style="text-align: center;"><span style="font-size:16px;">图4</span></p>
<p><strong><span style="font-size:20px;">4.总结</span></strong></p>
<p><span style="font-size:16px;">时间其实是手表比较重要的一部分,但是难度不大,只要维护好时间戳就可以了,对于设置名字,其实只要熟悉广播包的数据协议其实也没有什么难度,下一篇就是数据采集和存储同时APP获取并显示。</span></p>
<p>等着下一篇数据采集和存储同时APP获取并显示</p>
Jacktang 发表于 2021-6-27 20:15
等着下一篇数据采集和存储同时APP获取并显示
<p>已经写出来了~</p>
页:
[1]