【环境专家之智能手表】Part7:动态添加人员,实时显示数据
[复制链接]
1.介绍
前面下井人员的设备已经可以广播温度、湿度和气压了,现在需要矿井人员接收到广播数据,同时显示出下井人员的信息,由于目前只实现了温度、湿度和气压的实时数据,所以暂时只刷新这三个数据和信号强度数据,本来想通过NFC扫码添加人员的,但是这个NFC扫描准备使用手机实现,所以这里接收到新的广播数据就和NFC扫描到设备一样,动态添加下井人员设备。
2.下井设备修改
上一篇的广播设备代码稍微有点问题,导致矿井外设备无法扫描到其广播,只有手机能够正常扫描,这里准备修改一下下井设备的广播内容和方式。
我所在的范围气压值一般在100000左右,两个字节无法存储,所以将气压值扩大为3个字节,同时添加上了安森美的厂商ID。
图1
矿井外设备无法扫描到广播是因为设备类型设置为不支持经典蓝牙的【BR/EDR】,当然,这应该是扫描设备的配置问题,目前暂时先修改广播设备解决问题,修改内容如下。
图2
3.矿井外设备
首先找到扫描广播刷新的回调函数【SCAN_ScreenUpdateTimeout】,准备从这里修改OLED屏幕的内容,首先设备下井设备名称需要以【#R】开头,这样证明该设备为下井设备,然后扫描该设备的广播信息,对于的位与上面图1的协议匹配,传入OLED刷新,具体代码如下:
void SCAN_ScreenUpdateTimeout(void)
{
/* VT100 codes for clearing the screen. Works on VT100 terminals only */
/* Clear ("\033[2J") and move cursor ("\033[0;0H") */
go_well_info_t people = {0};
for (int i = 0; i < adv_report_list_size; i++)
{
const uint8_t target_name[] = {'#', 'R'};
const uint8_t* addr = adv_report_list[i].adv_addr.addr;
/* Create a UART string entry with device index, rssi, address, device name */
/* Indicate which device was selected for a connection */
memcpy(uart_tx_buffer, adv_report_list[i].data, adv_report_list[i].data_len);
if(memcmp(target_name, &adv_report_list[i].data[5], 2) == 0)
{
SCAN_UART_SendString(uart_tx_buffer, adv_report_list[i].data_len);
//刷新OLED
people.rssi_value = 150 + adv_report_list[i].rssi; //信号强度
people.activity = adv_report_list[i].data[21]; //活动状态
people.temp_value = adv_report_list[i].data[22]; //温度
people.humidity = adv_report_list[i].data[23]; //湿度
people.light_value = adv_report_list[i].data[24]; //光照强度
people.pressure = (adv_report_list[i].data[25] << 16) + (adv_report_list[i].data[26] << 8) + adv_report_list[i].data[27]; //气压值
memcpy(people.name, &adv_report_list[i].data[7], 10);
oled_config_refresh(people); //刷新数据
}
}
}
其中刷新数据就是将数据传入OLED,【oled_config_refresh】函数会判断,当前显示设备中是否有该设备,如果有则将刷新数据正常显示,如果没有则添加设备,同时为了节省资源,刷新数据时会判断与当前屏幕显示的值是否相同,如果相同则不进行刷新,具体代码如下。
//扫描到相关的设备,刷新信息
void oled_config_refresh(go_well_info_t people_temp)
{
int i = 0;
for(i = 0;i < go_well_cnt;i++) //遍历已存储的人员信息
{
if(memcmp(people_temp.name, go_well_poeple[i].name, 10) == 0) //已经存有名字相同的设备
{
memcpy(&go_well_poeple[i], &people_temp, sizeof(go_well_info_t)); //拷贝信息
if(go_well_poeple[i].activity != global_activity) //刷新活动状态
{
uint8_t act_display[3] = {0}; //显示活动状态
global_activity = go_well_poeple[i].activity;
switch(go_well_poeple[i].activity)
{
case NO_ACTIVITY:
act_display[0] = 'N';
act_display[1] = 'o';
break;
case WALK:
act_display[0] = 'W';
act_display[1] = 'l';
break;
case WORK:
act_display[0] = 'W';
act_display[1] = 'k';
break;
}
OLED_ShowString(32, 2, act_display, 16);
}
if(go_well_poeple[i].rssi_value != global_rssi_value) //刷新信号强度
{
uint8_t rssi_display[4] = {0}; //显示信号强度状态
global_rssi_value = go_well_poeple[i].rssi_value;
oled_config_num2str(rssi_display, go_well_poeple[i].rssi_value, 3);
OLED_ShowString(64+40, 2, rssi_display, 16);
}
if(go_well_poeple[i].temp_value != global_temp_value) //刷新温度
{
uint8_t temp_display[3] = {0}; //显示温度
global_temp_value = go_well_poeple[i].temp_value;
oled_config_num2str(temp_display, go_well_poeple[i].temp_value, 2);
OLED_ShowString(32, 4, temp_display, 16);
}
if(go_well_poeple[i].humidity != global_humidity) //刷新湿度
{
uint8_t humidity_display[4] = {0}; //显示湿度
global_humidity = go_well_poeple[i].humidity;
oled_config_num2str(humidity_display, go_well_poeple[i].humidity, 3);
OLED_ShowString(64+32, 4, humidity_display, 16);
}
if(go_well_poeple[i].pressure != global_pressure) //刷新气压值
{
uint8_t pressure_display[7] = {0}; //显示气压值
global_pressure = go_well_poeple[i].pressure;
oled_config_num2str(pressure_display, go_well_poeple[i].pressure, 6);
OLED_ShowString(16, 6, pressure_display, 16);
}
if(go_well_poeple[i].light_value != global_light_value) //刷新亮度
{
uint8_t light_display[4] = {0}; //显示亮度
global_light_value = go_well_poeple[i].light_value;
oled_config_num2str(light_display, go_well_poeple[i].light_value, 3);
OLED_ShowString(64+40, 6, light_display, 16);
}
return;
}
}
oled_config_add(people_temp); //则添加
}
添加下井人员函数,双重判断,是否列表中有该人员,如果没有则将名字和信息拷贝至列表中,具体代码如下。
//进入矿井时添加人员信息
void oled_config_add(go_well_info_t people_temp)
{
for(int i = 0;i < go_well_cnt;i++) //遍历已存储的人员信息
{
if(memcmp(people_temp.name, go_well_poeple[i].name, 10) == 0) //已经存有名字相同的设备
{
return; //不进行后续的添加
}
}
memcpy(&go_well_poeple[go_well_cnt], &people_temp, sizeof(go_well_info_t)); //拷贝信息和名字
go_well_cnt++;
//刷新显示屏
oled_config_display(go_well_cnt - 1); //显示刚添加的人员信息
}
这样添加人员功能基本就做完了,由于例程中的扫描广播是将广播中的名字扫描出来,并从串口打印出来,所以在扫描到广播的时候有一个提取名字的功能,过滤掉了其他信息,所以这一块需要修改,再一个是只有第一次扫描会提取名字信息,这一块需要修改为每一次扫描到都提取信息,【SCAN_AdvReportInd_Handler】函数功能为扫描到广播时调用,【SCAN_ScreenUpdateTimeout】函数为到时间调用,修改【SCAN_AdvReportInd_Handler】函数如下图所示。
图3
这样广播扫描并显示的功能就做好了,由于气压值修改了,所以界面也做了稍许的修改,其中rssi是信号强度,这里是数值越大,信号强度越强,效果图如下。
图4
实际演示的效果如下所示。
图5
4.总结
这一篇主要对广播方面做了一些修改,把自己的功能添加进去,整体来说不是很难,但是也有一些坑,不过坑踩过之后就知道了,下一篇是下井人员设备关于加速度计的活动状态采集。
|