#include #include #include "common.h" #include "param_config.h" #include "ble_pub.h" #include "drv_oled.h" #include #include #include "app_temperature.h" #ifdef PKG_USING_EASYFLASH #include "easyflash.h" #endif static app_temperature_info_t temperature_info; static app_dev_info_t dev_info; static app_temperature_mode_t app_mode = APP_MODE_NORMAL; static beken_timer_t timer_detect; static beken_timer_t timer_hall_detect; static beken_timer_t timer_poweroff; static beken_timer_t timer_bind; static beken_timer_t timer_idle; //extern uint8_t ble_active; //static uint8_t actv_idx; int Temp,Temp2,lastTemp; int temp0,temp1,temp2; uint8_t tempstr[5]; uint8_t tempstr1[5]; uint8_t tempstr11[5]; uint8_t tempstr2[5]; uint8_t batstr1[5]; uint8_t batstr2[5]="%"; uint8_t batstr3[5]=" "; char *endPtr; int start_bind_detect = 0; int hall_key_down_count = 0; int hall_io_state = 0; uint8_t ble_device_mac[6] = {0xe5, 0xe6, 0xb6, 0x09, 0x28, 0x37}; int ble_device_rssi = -100; int ble_found_bind_dev = 0; /** * 在BLE 广播里边查找设备名称 */ int temperature_adv_get_name(recv_adv_t *r_ind,char *name){ int name_len = 0; const uint8_t *p = r_ind->data; const uint8_t *end = r_ind->data + r_ind->data_len; while (p < end) { uint8_t current_length = *p++; // current_length是类型+数据的总字节数。当前指针已经移动到类型字段。 if (current_length == 0) { break; } if (p + current_length > end) { // 类型1字节 + 数据长度current_length -1字节? // 数据不够,退出 break; } uint8_t type = *p++; uint8_t data_len = current_length - 1; // 扣除类型字节后的数据长度 const uint8_t *data_ptr = p; switch (type) { case 0x09: // Complete Local Name if(data_len){ name_len = data_len; rt_strncpy(name,(char*)data_ptr,data_len); //rt_snprintf(name,data_len,"%s",data_ptr); } break; default: break; } p += data_len; // p之前已经移动到数据部分开始处,此时加上数据长度让指针移动到下一个AD结构 } return name_len; } void temperature_adv_callback(recv_adv_t *r_ind) { char str_name[12] ={0}; int ret = temperature_adv_get_name(r_ind,str_name); signed char rssi = (signed char)r_ind->rssi; if(ret){ #if 0 bk_printf("ble dev (%s): %02x:%02x:%02x:%02x:%02x:%02x,rssi:%d\r\n",str_name,r_ind->adv_addr[0], r_ind->adv_addr[1], r_ind->adv_addr[2], r_ind->adv_addr[3], r_ind->adv_addr[4], r_ind->adv_addr[5],rssi); #endif }else{ //没有名称的 跳过! return; } if(strstr(str_name,BLE_TEMPERATURE_DEVICE_IT12) == NULL){ //不等于 IT12的 跳过! return; } #if 1 bk_printf("\r\n"); bk_printf("ble dev (%s): %02x:%02x:%02x:%02x:%02x:%02x,rssi:%d\r\n",str_name,r_ind->adv_addr[0], r_ind->adv_addr[1], r_ind->adv_addr[2], r_ind->adv_addr[3], r_ind->adv_addr[4], r_ind->adv_addr[5],rssi); #endif //如果当前是绑定模式 则收集BLE 测温设备 判断信号值,然后绑定 if(app_mode == APP_MODE_BIND){ //简单匹配 选择信号值最大的 if(rssi > ble_device_rssi){ ble_found_bind_dev = 1; ble_device_rssi = rssi; rt_memcpy(ble_device_mac,r_ind->adv_addr,6); bk_printf("found better !bind - > ble_device : %s \r\n",str_name); } return; } // 绑定的设备 if (r_ind->adv_addr[0] != dev_info.bind_mac[0] &&r_ind->adv_addr[1] != dev_info.bind_mac[1] &&r_ind->adv_addr[2] != dev_info.bind_mac[2] &&r_ind->adv_addr[3] != dev_info.bind_mac[3] &&r_ind->adv_addr[4] != dev_info.bind_mac[4] &&r_ind->adv_addr[5] != dev_info.bind_mac[5]) { return; } rtos_reload_timer(&timer_idle); //int i; //for (i = 0; i < r_ind->data_len; i++) //{ // bk_printf("0x%02x,", r_ind->data[i]); //} //bk_printf("\r\n"); const uint8_t *p = r_ind->data; const uint8_t *end = r_ind->data + r_ind->data_len; int j = 0; while (p < end) { uint8_t current_length = *p++; // current_length是类型+数据的总字节数。当前指针已经移动到类型字段。 if (current_length == 0) { break; } if (p + current_length > end) { // 类型1字节 + 数据长度current_length -1字节? // 数据不够,退出 break; } uint8_t type = *p++; uint8_t data_len = current_length - 1; // 扣除类型字节后的数据长度 const uint8_t *data_ptr = p; switch (type) { case 0x01: // Flags break; case 0xFF: // Manufacturer Specific Data bk_printf("FF: "); for (j = 0; j < data_len; j++) { bk_printf("0x%02x ", data_ptr[j]); } bk_printf("\r\n"); uint16_t body = (data_ptr[1] & 0xff) | (((data_ptr[0] & 0xff) << 8)); uint16_t obj = (data_ptr[3] & 0xff) | (((data_ptr[2] & 0xff) << 8)); uint16_t env = (data_ptr[5] & 0xff) | (((data_ptr[4] & 0xff) << 8)); uint16_t batt = data_ptr[6] & 0xff; temperature_info.temperature_body = body; temperature_info.temperature_obj = obj; temperature_info.temperature_env = env; temperature_info.batt_val = batt; bk_printf("temp-> body : %d obj : %d env : %d batt : %d\r\n", body, obj, env, batt); break; // 其他需要的类型可以继续添加 default: break; } p += data_len; // p之前已经移动到数据部分开始处,此时加上数据长度让指针移动到下一个AD结构 } } uint16_t last_body_temp = 0; void timer_temp_run_callback(void *arg){ //如果当前进入了绑定模式 则不刷新温度 if(app_mode == APP_MODE_BIND){ return; } //如果当前温度和之前相同 不刷新温度 uint16_t temp_body = temperature_info.temperature_body; if(last_body_temp == temp_body){ return; } last_body_temp = temp_body; char str_temp[8]={0}; rt_sprintf(str_temp,"%d.%d \n",temp_body/100,temp_body/10%10); rt_kprintf("%s\r\n",str_temp); //rt_kprintf("Temp:%d,Temp2:%d\r\n",Temp,Temp2); //rt_kprintf("Temp:%d,Temp2:%d\r\n",Temp,Temp2); if(temp_body > BLE_TEMPERATURE_LIMIT_MIN && temp_body < BLE_TEMPERATURE_LIMIT_MAX){ OLED_Clear(); rt_memset(str_temp,0,sizeof(str_temp)); rt_sprintf(str_temp,"%d",temp_body/100);//整数 OLED_ShowString(0,0+10,(u8*)str_temp,32,1); OLED_ShowChar(32,0+10,'.',32,1);//小数点 rt_memset(str_temp,0,sizeof(str_temp)); rt_sprintf(str_temp,"%d",temp_body/10%10);//小数点后一位 OLED_ShowString(40,0+10,(u8*)str_temp,32,1); OLED_DrawCircle(58,5+6,4); OLED_ShowChar(56,8+10,'C',24,1); } if(temp_body < BLE_TEMPERATURE_LIMIT_MIN){ OLED_Clear(); OLED_ShowString(0+10,0+5,(u8 *)"LOW",32,1); } if(temp_body > BLE_TEMPERATURE_LIMIT_MAX){ OLED_Clear(); OLED_ShowString(0+5,0+5,(u8 *)"HIGH",32,1); } lastTemp=Temp; OLED_Refresh(); } void app_enter_bind_mode(bool enter){ if(enter){ app_mode = APP_MODE_BIND; rt_memset(ble_device_mac,0,sizeof(ble_device_mac)); //收到的信号值 区域0 为越好 ble_device_rssi = -100; //清除找到绑定设备标志 ble_found_bind_dev = 0; OLED_Clear(); OLED_ShowString(0+5,0+5,(u8 *)"BIND",32,1); }else{ app_mode = APP_MODE_NORMAL; OLED_Clear(); OLED_ShowString(0+20,0,(u8 *)"...",32,1); } OLED_Refresh(); } void box_poweroff_timeout_callback(void *arg){ rtos_stop_timer(&timer_poweroff); bk_gpio_config_output(BLE_TEMPERATURE_BOX_POWER_CTR); bk_gpio_output(BLE_TEMPERATURE_BOX_POWER_CTR,0); rt_kprintf("box poweroff !!!\r\n"); } /** * 绑定扫描设备时间到 判断有无找到设备 有则写入FLASH */ void box_bind_timeout_callback(void *arg){ rtos_stop_timer(&timer_bind); if(ble_found_bind_dev){ bk_printf("BIND: %02x:%02x:%02x:%02x:%02x:%02x \r\n",ble_device_mac[0],ble_device_mac[1], ble_device_mac[2], ble_device_mac[3], ble_device_mac[4],ble_device_mac[5]); rt_memcpy(dev_info.bind_mac,ble_device_mac,sizeof(ble_device_mac)); EfErrCode result = EF_NO_ERR; //将要写入的数据存放到 easy flash 环境变量 result = ef_set_env(BLE_TEMPERATURE_FLASH_CONFIG_KEY, (char*)&dev_info); //保存数据 result = ef_save_env(); if(result == EF_NO_ERR) { OLED_Clear(); OLED_ShowString(0+15,0+5,(u8 *)"OK",32,1); OLED_Refresh(); rt_thread_mdelay(1000); } } app_enter_bind_mode(false); rt_kprintf("exit bind mode !!!\r\n"); } /* 长时间没有接收到温度广播 则回到等待页面 */ void timer_app_idle_callback(void *arg){ if(app_mode == APP_MODE_BIND){ return; } app_enter_bind_mode(false); rt_kprintf("back idle mode !!!\r\n"); } /** * 检测hall开关状态 判断是否进入绑定模式 * 进入绑定模式后检测接收到的最强一个测温信号设备绑定 */ void timer_hall_detect_callback(void *arg){ int hall = bk_gpio_input(38); //rt_kprintf("hall -> %d\r\n",hall); if(hall_io_state == hall){ return; } hall_io_state = hall; if(hall == 0){ if(!start_bind_detect){ start_bind_detect = 1; } hall_key_down_count ++; rt_kprintf("detect hall down ,count :%d\r\n",hall_key_down_count); //延迟关机 //启动定时8秒关机 rtos_start_timer(&timer_poweroff); }else{ //如果启动定时开机后 检测到开盖,则取消开机 if(rtos_is_timer_running(&timer_poweroff)){ //rt_kprintf("stop poweroff timeout !!!\r\n"); rtos_stop_timer(&timer_poweroff); } if(start_bind_detect && hall_key_down_count == 5){ rt_kprintf("enter bind !!!\r\n"); start_bind_detect = 0; hall_key_down_count = 0; app_enter_bind_mode(true); //进入绑定模式 并启动超时退出 rtos_start_timer(&timer_bind); } } } // 中断触发的回调函数 void box_switch_irq_callback(unsigned char ucChannel) { rt_kprintf("Interrupt triggered!\n"); // 这里可以添加更多的处理逻辑 int hall = bk_gpio_input(38); rt_kprintf("hall -> %d\r\n",hall); } int box_switch_init(void) { //关闭box 保持电源不关机 bk_gpio_config_output(39); bk_gpio_output(39,1); bk_gpio_config_input(38); //启动中断失败 //gpio_int_enable(38,GMODE_INPUT_PULLDOWN,box_switch_irq_callback); /* 按键引脚为输入模式*/ //rt_pin_mode(GPIO38 , PIN_MODE_INPUT); /* 绑定中断, 下降沿模式, 回调函数名为box_switch_irq_callback */ //rt_pin_attach_irq(GPIO38 , PIN_IRQ_MODE_FALLING , box_switch_irq_callback, RT_NULL); /* 使能中断*/ //rt_pin_irq_enable(GPIO38 , PIN_IRQ_ENABLE); return 0; } void temperature_dev_config_init(){ easyflash_init(); rt_memset(&dev_info,0,sizeof(app_dev_info_t)); /*获取easy flash存入的数据*/ char *t = ef_get_env(BLE_TEMPERATURE_FLASH_CONFIG_KEY); if(t != NULL){ rt_memcpy(&dev_info,t,sizeof(app_dev_info_t)); rt_kprintf("\r\n"); rt_kprintf("BIND TDEVICE:%02X %02X %02X %02X %02X %02X\r\n",dev_info.bind_mac[0],dev_info.bind_mac[1],dev_info.bind_mac[2],dev_info.bind_mac[3],dev_info.bind_mac[4],dev_info.bind_mac[5]); //rt_kprintf("DETECT %d\r\n",dev_info.detect_interval); rt_kprintf("\r\n"); }else{ rt_kprintf("easy_flash read error\r\n"); } } void temperature_init(void){ // 查询绑定设备 uint8_t test_device_mac[6] = {0xe5, 0xe6, 0xb6, 0x09, 0x28, 0x37}; rt_memcmp(dev_info.bind_mac, test_device_mac, sizeof(test_device_mac)); //初始化GPIO gpio_init(); //初始化OLED显示屏 OLED_Init(); //OLED_Clear(); // OLED_ShowChar(32,0+10,'.',32,1); // OLED_Refresh(); // rt_thread_mdelay(100); // OLED_Clear(); // OLED_ShowChar(56,8+10,'C',24,1); // OLED_Refresh(); // bk_gpio_output(20,0); // bk_gpio_output(21,0); // oled_show_temp(370,4); // user_app_start(); temperature_dev_config_init(); app_enter_bind_mode(false); box_switch_init(); //初始化BLE belon_ble_active(); //启动BLE MASTER 扫描BLE测温设备 belon_ble_init_scan(); rt_thread_mdelay(100); //启动BLE SLAVE 发广播提供APP 连接进行设置 belon_ble_init_adv(); //启动定时器 定时更新温度显示 rtos_init_timer(&timer_detect, 1000, timer_temp_run_callback, NULL); rtos_start_timer(&timer_detect); //霍尔检测 100ms一次 中断不好使 先这样处理 rtos_init_timer(&timer_hall_detect, 100, timer_hall_detect_callback, NULL); rtos_start_timer(&timer_hall_detect); rtos_init_timer(&timer_poweroff, BLE_TEMPERATURE_POWEROFF_TIMEOUT, box_poweroff_timeout_callback, NULL); rtos_init_timer(&timer_bind, BLE_TEMPERATURE_BIND_MODE_TIMEOUT, box_bind_timeout_callback, NULL); rtos_init_timer(&timer_idle, BLE_TEMPERATURE_IDLE_MODE_TIMEOUT, timer_app_idle_callback, NULL); }