/*Includes ----------------------------------------------*/ #include "tool.h" #include "nrf_delay.h" #include "system.h" #include "ble_comm.h" #include "bsp_time.h" #include "hal_led.h" #include "app_flash.h" #include "app_wireless_pair.h" /*Private macro ------------------------------------------------------------------------------------------------------------------------------------*/ #define APP_WIRELESS_PAIR_FSMTABLE_LEN 8 //状态表长度 #define APP_WIRELESS_PAIR_RSSI_THRESHOLD -18 //rssi阈值 /*Struction ------------------------------------------------------------------------------------------------------------------------------------*/ //定义状态数据的枚举类型 typedef enum _app_wireless_pair_state { APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY, //配对待机状态 APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION, //配对准备中状态 APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS, //配对进行中状态 APP_WIRELESS_PAIR_STATE_END_OF_PAIRING, //配对结束状态 }App_Wireless_Pair_State_e; //定义状态表的数据类型 typedef struct _app_wireless_pair_fsmtable_s { App_Wireless_Pair_Event_e event; //事件 App_Wireless_Pair_State_e CurState; //当前状态 int (*eventActFun)(); //函数指针 App_Wireless_Pair_State_e NextState; //下一个状态 }App_Wireless_Pair_fsmtable_s; //定义状态机类型 typedef struct _app_wireless_pair_fsm_s { App_Wireless_Pair_State_e curState; //当前状态 App_Wireless_Pair_fsmtable_s FsmTable[APP_WIRELESS_PAIR_FSMTABLE_LEN]; //状态表 App_Wireless_Pair_Set_Scan_Cb set_scan_cb; //设置扫描回调 App_Wireless_Pair_Set_Adv_Cb set_adv_cb; //设置广播回调 uint8_t peer_addr[6]; //对端MAC地址 bool is_busy; //是否忙碌 uint8_t led_display_count; //亮灯次数 uint8_t led_switch; //灯的开关 char already_scan_or_adv_mac_buf[16]; //已经在扫描或广播的mac地址 }App_Wireless_Pair_Fsm_s; /*Local Variable ------------------------------------------------------------------------------------------------------------------------------------*/ static App_Wireless_Pair_Fsm_s ob_app_wireless_pair_fsm; /*Local Functions ------------------------------------------------------------------------------------------------------------------------------------*/ static int app_wireless_pair_set_scan_adv_on(void) { int ret = 0; //若是右鞋则进入主动扫描状态 //若是左鞋则设置扫描回应为MAC地址状态 if(mFlash.isHost) { advertising_stop(); nrf_ble_scan_stop(); host_disconnect(); if(host_isconnect() == 0) { if(ob_app_wireless_pair_fsm.set_adv_cb != NULL)ret = ob_app_wireless_pair_fsm.set_adv_cb(0x01); else ret = -1; if(ob_app_wireless_pair_fsm.set_scan_cb != NULL)ret = ob_app_wireless_pair_fsm.set_scan_cb(0x00); else ret = -1; } else { ret = -1; } } else { advertising_stop(); nrf_ble_scan_stop(); slave_disconnect(); if(slave_isconnect() == 0) { if(ob_app_wireless_pair_fsm.set_adv_cb != NULL)ret = ob_app_wireless_pair_fsm.set_adv_cb(0x00); else ret = -1; if(ob_app_wireless_pair_fsm.set_scan_cb != NULL)ret = ob_app_wireless_pair_fsm.set_scan_cb(0x01); else ret = -1; } else { ret = -1; } } return ret; } static int app_wireless_pair_set_scan_adv_off(void) { int ret = 0; char buf[16]; //若是右鞋则进入被动扫描状态 //若是左鞋则设置扫描回应为空数据状态 if(mFlash.isHost) { advertising_stop(); nrf_ble_scan_stop(); host_disconnect(); if(host_isconnect() == 0) { if(ob_app_wireless_pair_fsm.set_adv_cb != NULL)ret = ob_app_wireless_pair_fsm.set_adv_cb(0x00); else ret = -1; if(ob_app_wireless_pair_fsm.set_scan_cb != NULL) { sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.macHost[0],mFlash.macHost[1],mFlash.macHost[2],mFlash.mClient.macAddr[3],mFlash.mClient.macAddr[4],mFlash.mClient.macAddr[5]); host_set_scan_name(buf,strlen(buf)); ret = ob_app_wireless_pair_fsm.set_scan_cb(0x00); } else ret = -1; } else { ret = -1; } } else { advertising_stop(); nrf_ble_scan_stop(); slave_disconnect(); if(slave_isconnect() == 0) { if(ob_app_wireless_pair_fsm.set_adv_cb != NULL) { sprintf(buf,"%02X%02X%02X%02X%02X%02X",mFlash.mClient.macAddr[0],mFlash.mClient.macAddr[1],mFlash.mClient.macAddr[2],mFlash.macHost[3],mFlash.macHost[4],mFlash.macHost[5]); slave_set_adv_name(buf,strlen(buf)); slave_adv_init(); ret = ob_app_wireless_pair_fsm.set_adv_cb(0x00); } else ret = -1; } else { ret = -1; } } return ret; } static int app_wireless_pair_unconditional_entry(void) { return 0; //不用做任何操作,直接进入下一个状态 } static void Bubble_sort(int arr[], int size) { int j,i,tem; for (i = 0; i < size-1;i ++)//size-1是因为不用与自己比较,所以比的数就少一个 { int count = 0; for (j = 0; j < size-1 - i; j++) //size-1-i是因为每一趟就会少一个数比较 { if (arr[j] > arr[j+1])//这是升序排法,前一个数和后一个数比较,如果前数大则与后一个数换位置 { tem = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tem; count = 1; } } if (count == 0) //如果某一趟没有交换位置,则说明已经排好序,直接退出循环 break; //值得注意的是函数中的定义的count是为了检验是否进行了元素的交换,是对代码的一种优化 } } static int app_wireless_pair_enter_in_process(int rssi, uint8_t *addr) { #define N 15 static int rssi_buf[N], rssi_filter_buf[N]; static uint8_t index = 0; int ret = 0; uint8_t null_addr[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; if(ob_app_wireless_pair_fsm.is_busy == false) { rssi_buf[index++] = rssi; if(index == N)index = 0; memcpy(rssi_filter_buf,rssi_buf,sizeof(rssi_buf)); Bubble_sort(rssi_filter_buf, N); // SEGGER_RTT_printf(0,"rssi:%d,st:%d,curState:%d,active:%d\r\n",rssi_filter_buf[N-1],NRF_RTC0->COUNTER, \ // ob_app_wireless_pair_fsm.curState,wireless_pair_scan_get_active()); if(rssi_filter_buf[N-1] >= APP_WIRELESS_PAIR_RSSI_THRESHOLD) { if(memcmp(addr,null_addr,6) != 0) { ret = app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_RSSI_MEETS_REQUIREMENTS); for(int i=0; i<6; i++)ob_app_wireless_pair_fsm.peer_addr[i] = addr[5-i]; } else { ret = app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_RSSI_DOES_NOT_MEETS_REQUIREMENTS); } } else { ret = app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_RSSI_DOES_NOT_MEETS_REQUIREMENTS); } } return ret; } static void display_led_process(void) { ob_app_wireless_pair_fsm.led_display_count++; if (ob_app_wireless_pair_fsm.led_display_count % 2 == 0) { LED_Start(LED_PAIR, COLOR_BLACK); } else { LED_Start(LED_PAIR, COLOR_BLUE); } if (ob_app_wireless_pair_fsm.led_display_count > 20) { ob_app_wireless_pair_fsm.led_display_count = 0; LED_Stop(LED_PAIR); Process_SetHoldOn(display_led_process, 0); Process_Stop(display_led_process); } } static void app_wireless_pair_start_display_led(void) { ob_app_wireless_pair_fsm.led_display_count = 0; Process_Start(500, "display_led_process", display_led_process); Process_SetHoldOn(display_led_process, 1); } static void app_wireless_pair_stop_display_led(void) { ob_app_wireless_pair_fsm.led_display_count = 0; LED_Stop(LED_PAIR); Process_SetHoldOn(display_led_process, 0); Process_Stop(display_led_process); } static void app_wireless_pair_in_process(void) { int ret = 0; uint8_t *connect_addr; uint8_t peer_addr[6]; //对端mac地址 ble_gap_addr_t m_addr; //自身mac地址 char buf[16]; uint32_t err_code; if(ob_app_wireless_pair_fsm.curState == APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS) { ob_app_wireless_pair_fsm.is_busy = true; //获取已连接的对端mac地址 connect_addr = wireless_pair_get_connect_macaddr(); //获取自身mac地址 err_code = sd_ble_gap_addr_get(&m_addr); APP_ERROR_CHECK(err_code); //获取对端的mac地址 for(int i=0;i<6;i++)peer_addr[i]=ob_app_wireless_pair_fsm.peer_addr[i]; if(mFlash.isHost) //左鞋处理逻辑 { //判断是否处于连接且连接的mac地址为配对地址 if(host_isconnect() == 1 && memcmp(peer_addr,connect_addr,6) == 0) { //判断是否配对过,若已配对过,直接进入配对结束阶段。若无配对过,则记录MAC地址,清除步数,进入配对结束。 if(memcmp(peer_addr,mFlash.mClient.macAddr,6) != 0) { for(int i = 0; i < 6; i++) { mFlash.mClient.macAddr[i] = peer_addr[i]; mFlash.macHost[i] = m_addr.addr[5-i]; mBackup.macAddr_L[i] = mFlash.macHost[i]; //主机地址 mBackup.macAddr_R[i] = mFlash.mClient.macAddr[i]; //从机地址 } mFlash.mClient.isConfig ='C'; mBackup.hardVersion = mFlash.mClient.hardVersion; mBackup.sotfVersion = mFlash.mClient.sotfVersion; mBackup.isConfig = mFlash.mClient.isConfig; if(Flash_SaveBackup() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "pair save backup fail");} if(Flash_DeleteAllStep() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "pair clear step fail");} memset(&mFlash.mStep, 0, sizeof(FlashStep_t)); if(Flash_SaveInfomation() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "Flash_SaveInfomation fail");} } app_wireless_pair_start_led(); app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_PAIR_DONE); } else { //若不是,断开连接,设置扫描为新的配对地址 sprintf(buf,"%02X%02X%02X%02X%02X%02X",m_addr.addr[5],m_addr.addr[4],m_addr.addr[3],peer_addr[3],peer_addr[4],peer_addr[5]); if(memcmp(ob_app_wireless_pair_fsm.already_scan_or_adv_mac_buf,buf,strlen(buf)) != 0) { advertising_stop(); nrf_ble_scan_stop(); host_disconnect(); if(host_isconnect() == 0) { ret += ob_app_wireless_pair_fsm.set_adv_cb(0x01); host_set_scan_name(buf,strlen(buf)); ret += ob_app_wireless_pair_fsm.set_scan_cb(0x02); if(ret == 0)memcpy(ob_app_wireless_pair_fsm.already_scan_or_adv_mac_buf,buf,strlen(buf)); } } } } else //右鞋处理逻辑 { //判断是否处于连接且连接的mac地址为配对地址 if(slave_isconnect() == 1 && memcmp(peer_addr,connect_addr,6) == 0) { //判断是否配对过,若已配对过,直接进入配对结束阶段。若无配对过,则记录MAC地址,清除步数,进入配对结束。 if(memcmp(peer_addr,mFlash.mClient.macAddr,6) != 0) { for(int i = 0; i < 6; i++) { mFlash.mClient.macAddr[i] = peer_addr[i]; mFlash.macHost[i] = m_addr.addr[5-i]; mBackup.macAddr_L[i] = mFlash.macHost[i]; //主机地址 mBackup.macAddr_R[i] = mFlash.mClient.macAddr[i]; //从机地址 } mFlash.mClient.isConfig ='C'; mBackup.hardVersion = mFlash.mClient.hardVersion; mBackup.sotfVersion = mFlash.mClient.sotfVersion; mBackup.isConfig = mFlash.mClient.isConfig; if(Flash_SaveBackup() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "pair save backup fail");} if(Flash_DeleteAllStep() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "pair clear step fail");} memset(&mFlash.mStep, 0, sizeof(FlashStep_t)); if(Flash_SaveInfomation() != ZONE_OP_SUCCESS){Except_TxError(EXCEPT_Pair, "Flash_SaveInfomation fail");} } app_wireless_pair_start_led(); app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_PAIR_DONE); } else { //若不是,断开连接,设置广播为新的配对地址 sprintf(buf,"%02X%02X%02X%02X%02X%02X",peer_addr[0],peer_addr[1],peer_addr[2],m_addr.addr[2],m_addr.addr[1],m_addr.addr[0]); if(memcmp(ob_app_wireless_pair_fsm.already_scan_or_adv_mac_buf,buf,strlen(buf)) != 0) { advertising_stop(); nrf_ble_scan_stop(); slave_disconnect(); if(slave_isconnect() == 0) { ret += ob_app_wireless_pair_fsm.set_scan_cb(0x01); slave_set_adv_name(buf,strlen(buf)); slave_adv_init(); ret += ob_app_wireless_pair_fsm.set_adv_cb(0x02); if(ret == 0)memcpy(ob_app_wireless_pair_fsm.already_scan_or_adv_mac_buf,buf,strlen(buf)); } } } } ob_app_wireless_pair_fsm.is_busy = false; } } /*API ------------------------------------------------------------------------------------------------------------------------------------*/ /** @brief 初始化无线配对应用 @param 无 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_Init(void) { //初始化结构体 // memset(&ob_app_wireless_pair_fsm,0,sizeof(App_Wireless_Pair_Fsm_s)); //不能meset初始化,因为回调函数会被清除。 ob_app_wireless_pair_fsm.curState = APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY; ob_app_wireless_pair_fsm.is_busy = false; ob_app_wireless_pair_fsm.led_switch = 0x01; //{到来的事件,当前的状态,将要要执行的函数,下一个状态} ob_app_wireless_pair_fsm.FsmTable[0].event = APP_WIRELESS_PAIR_EVENT_CHARGING_INSERTING; //充电插入 ob_app_wireless_pair_fsm.FsmTable[0].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY; //配对待机状态 ob_app_wireless_pair_fsm.FsmTable[0].eventActFun = app_wireless_pair_set_scan_adv_on; //设置扫描和广播开 ob_app_wireless_pair_fsm.FsmTable[0].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION; //配对准备中状态 ob_app_wireless_pair_fsm.FsmTable[1].event = APP_WIRELESS_PAIR_EVENT_CHARGING_UNPLUG; //充电拔出 ob_app_wireless_pair_fsm.FsmTable[1].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION; //配对准备中状态 ob_app_wireless_pair_fsm.FsmTable[1].eventActFun = app_wireless_pair_set_scan_adv_off; //设置扫描和广播关 ob_app_wireless_pair_fsm.FsmTable[1].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY; //配对待机状态 ob_app_wireless_pair_fsm.FsmTable[2].event = APP_WIRELESS_PAIR_EVENT_RSSI_MEETS_REQUIREMENTS; //rssi符合要求 ob_app_wireless_pair_fsm.FsmTable[2].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION; //配对准备中状态 ob_app_wireless_pair_fsm.FsmTable[2].eventActFun = app_wireless_pair_unconditional_entry; //不操作,直接进入下一个状态 ob_app_wireless_pair_fsm.FsmTable[2].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS; //配对进行中状态 ob_app_wireless_pair_fsm.FsmTable[3].event = APP_WIRELESS_PAIR_EVENT_CHARGING_UNPLUG; //充电拔出 ob_app_wireless_pair_fsm.FsmTable[3].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS; //配对进行中状态 ob_app_wireless_pair_fsm.FsmTable[3].eventActFun = app_wireless_pair_set_scan_adv_off; //设置扫描和广播关 ob_app_wireless_pair_fsm.FsmTable[3].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY; //配对待机状态 ob_app_wireless_pair_fsm.FsmTable[4].event = APP_WIRELESS_PAIR_EVENT_RSSI_DOES_NOT_MEETS_REQUIREMENTS; //rssi不符合要求 ob_app_wireless_pair_fsm.FsmTable[4].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS; //配对进行中状态 ob_app_wireless_pair_fsm.FsmTable[4].eventActFun = app_wireless_pair_unconditional_entry; //不操作,直接进入下一个状态 ob_app_wireless_pair_fsm.FsmTable[4].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION; //配对准备中状态 ob_app_wireless_pair_fsm.FsmTable[5].event = APP_WIRELESS_PAIR_EVENT_PAIR_DONE; //配对完成 ob_app_wireless_pair_fsm.FsmTable[5].CurState = APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS; //配对进行中状态 ob_app_wireless_pair_fsm.FsmTable[5].eventActFun = app_wireless_pair_unconditional_entry; //不操作,直接进入下一个状态 ob_app_wireless_pair_fsm.FsmTable[5].NextState = APP_WIRELESS_PAIR_STATE_END_OF_PAIRING; //配对结束状态 ob_app_wireless_pair_fsm.FsmTable[6].event = APP_WIRELESS_PAIR_EVENT_CHARGING_UNPLUG; //充电拔出 ob_app_wireless_pair_fsm.FsmTable[6].CurState = APP_WIRELESS_PAIR_STATE_END_OF_PAIRING; //配对结束状态 ob_app_wireless_pair_fsm.FsmTable[6].eventActFun = app_wireless_pair_set_scan_adv_off; //设置扫描和广播关 ob_app_wireless_pair_fsm.FsmTable[6].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_STANDBY; //配对待机状态 ob_app_wireless_pair_fsm.FsmTable[7].event = APP_WIRELESS_PAIR_EVENT_RSSI_DOES_NOT_MEETS_REQUIREMENTS; //rssi不符合要求 ob_app_wireless_pair_fsm.FsmTable[7].CurState = APP_WIRELESS_PAIR_STATE_END_OF_PAIRING; //配对结束状态 ob_app_wireless_pair_fsm.FsmTable[7].eventActFun = app_wireless_pair_unconditional_entry; //不操作,直接进入下一个状态 ob_app_wireless_pair_fsm.FsmTable[7].NextState = APP_WIRELESS_PAIR_STATE_PAIRING_PREPARATION; //配对准备中状态 Process_Start(0,"app_wireless_pair_in_process",app_wireless_pair_in_process); return 0; } /** @brief 无线配对注册扫描设置 @param cb - [in] 注册的回调 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_Regist_SetScan(App_Wireless_Pair_Set_Scan_Cb cb) { if(cb != NULL) { ob_app_wireless_pair_fsm.set_scan_cb = cb; return 0; } return -1; } /** @brief 无线配对注册广播设置 @param cb - [in] 注册的回调 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_Regist_SetAdv(App_Wireless_Pair_Set_Adv_Cb cb) { if(cb != NULL) { ob_app_wireless_pair_fsm.set_adv_cb = cb; return 0; } return -1; } /** @brief 无线配对扫描请求 @param rssi - [in] 天线信号强度 @param addr - [in] MAC地址缓冲区指针 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_Scan_Req(int rssi, uint8_t *addr) { int ret = 0; if(mFlash.isHost) { app_wireless_pair_enter_in_process(rssi,addr); } else { ret = -1; //只有左鞋收到右鞋的扫描请求才对 } return ret; } /** @brief 无线配对扫描回复 @param rssi - [in] 天线信号强度 @param addr - [in] MAC地址缓冲区指针 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_Scan_Rsp(int rssi, uint8_t *addr) { int ret = 0; if(!mFlash.isHost) { app_wireless_pair_enter_in_process(rssi,addr); } else { ret = -1; //只有右鞋收到左鞋的扫描回应才对 } return ret; } /** @brief 无线配对亮灯 @param 无 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_start_led(void) { // SEGGER_RTT_printf(0,"start: curState:%d\r\n",ob_app_wireless_pair_fsm.curState); if(ob_app_wireless_pair_fsm.led_switch != 0 && (ob_app_wireless_pair_fsm.curState == APP_WIRELESS_PAIR_STATE_PAIRING_IN_PROGRESS)) { ob_app_wireless_pair_fsm.led_switch--; app_wireless_pair_start_display_led(); // SEGGER_RTT_printf(0,"app_wireless_pair_start_display_led\r\n"); } return 0; } /** @brief 无线配对灭灯 @param 无 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_stop_led(void) { // SEGGER_RTT_printf(0,"stop: curState:%d\r\n",ob_app_wireless_pair_fsm.curState); app_wireless_pair_stop_display_led(); ob_app_wireless_pair_fsm.led_switch = 1; app_wireless_pair_EventHandle(APP_WIRELESS_PAIR_EVENT_RSSI_DOES_NOT_MEETS_REQUIREMENTS); // SEGGER_RTT_printf(0,"app_wireless_pair_stop_display_led\r\n"); return 0; } /** @brief 无线配对事件处理 @param event - [in] 事件 @return 错误代码 - [out] -1失败,0成功 */ int app_wireless_pair_EventHandle(App_Wireless_Pair_Event_e event) { int (*eventActFun)() = NULL; //函数指针初始化为空 App_Wireless_Pair_State_e NextState; int flag = 0; //标识是否满足条件 int i; int ret = 0; /*获取当前动作函数*/ for (i = 0; i