/* * @Author: mbw * @Date: 2024-10-09 08:42:14 * @LastEditors: mbw && 1600520629@qq.com * @LastEditTime: 2025-01-18 15:39:10 * @FilePath: \JT-DT-YD4N02A_RTT_MRS-NT26K\bsp\src\bsp_nt26k.c * @Description: * * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. */ /* * Copyright (c) 2006-2023, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2019-12-13 qiyongzhong first version */ #include #include "drv_gpio.h" #include "bsp_nt26k.h" #include "user_sys.h" #include "bsp_flash.h" #include "bsp_h308.h" #include "stddef.h" #include "bsp_emv.h" #include "bsp_rtc.h" #include "bsp_relay.h" #include "bsp_rng.h" #define LOG_TAG "nt26k" #include #if IOT_MODULE_SWITCH == 1 #define NT26K_THREAD_STACK_SIZE (4096) #define NT26K_RECV_THREAD_STACK_SIZE (4096) #define NT26K_LIFE_THREAD_STACK_SIZE (2048) #define NT26K_THREAD_PRIORITY 25 #define NT26K_THREAD_TICKS 50 #define NT26K_RECV_THREAD_PRIORITY 24 #define NT26K_RECV_THREAD_TICKS 10 #define NT26K_LIFE_THREAD_PRIORITY 26 #define NT26K_LIFE_THREAD_TICKS 10 // static rt_uint32_t nt26k_status = 0; ALIGN(RT_ALIGN_SIZE) static char nt26k_thread_stack[NT26K_THREAD_STACK_SIZE]; static struct rt_thread nt26k_thread; ALIGN(RT_ALIGN_SIZE) static char nt26k_recv_thread_stack[NT26K_RECV_THREAD_STACK_SIZE]; static struct rt_thread nt26k_recv_thread; ALIGN(RT_ALIGN_SIZE) static char nt26k_life_thread_stack[NT26K_LIFE_THREAD_STACK_SIZE]; static struct rt_thread nt26k_life_thread; struct rt_event at_device_event; rt_sem_t nt26k_recv_sem; rt_sem_t nt26k_recv_heart_sem; // 用于接收心跳信号 rt_sem_t nt26k_disconnect_sem; static rt_timer_t nt26k_timer; // 上报心跳 static rt_timer_t nt26k_upload_timer; // 更新本地时间定时器 static rt_timer_t nt26k_power_error_timer; // 上电失败情况下启动定时器 rt_uint8_t device_power_down_flag; rt_uint8_t nt26k_power_down_flag; rt_uint8_t nt26k_connect_sever_flag; rt_uint8_t nt26k_conncet_tcp_flag; rt_uint8_t nt26k_disconnect_pdp_flag; // PDP断开连接标志 rt_uint8_t nt26k_disconnect_retry_flag = 0; // 用于判断是否已经启动了重连,如果启动,不需要每次都进入 Nt26kEventIndex nt26k_event_index; rt_uint8_t power_on_send_flag = 0; rt_mutex_t nt26k_mutex; int BSP_Nt26k_Init(struct Nt26k_Ops *ops, rt_uint8_t version); int BSP_Nt26k_Update(struct Nt26k_Ops *ops, rt_uint8_t device_type, rt_uint8_t event_type); int Nt26k_Send_Data(struct Nt26k_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type); int Data_Resp(struct Nt26k_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type, char *data, rt_uint8_t res); int Nt26k_Recv_Data(struct Nt26k_Ops *ops, char *data); static struct DataBody body; static struct Nt26kDataFrame frame; static struct Nt26kRecvData nt26k_recv; struct Nt26k_Ops nt26k_ops = { .body = &body, .frame = &frame, .recv = &nt26k_recv, .init = BSP_Nt26k_Init, .update_data = BSP_Nt26k_Update, .send = Nt26k_Send_Data, .Resp = Data_Resp, // .Recv = Nt26k_Recv_Data,//,没用到 }; static struct at_device_nt26k _dev = { NT26K_SAMPLE_DEIVCE_NAME, NT26K_SAMPLE_CLIENT_NAME, NT26K_PWR_EN_PIN, NT26K_RST_PIN, NT26K_PWR_KEY_PIN, NT26K_SAMPLE_RECV_BUFF_LEN, }; static rt_uint32_t nt26k_event_flags[kNt26kMaxEventcnt] = {0}; static rt_bool_t nt26k_event_initialized = RT_FALSE; // 是否初始化完成 typedef enum { NT26K_PRIORITY_LOWEST, // 4、优先级最低(定时心跳、浓度异常、报警触发、报警解除、传感器故障触发 传感器故障解除) NT26K_PRIORITY_MEDIUM, // 2、优先级第三高 自检触发 NT26K_PRIORITY_HIGH, // 1、优先级第二高 掉电 NT26K_PRIORITY_HIGHEST, // 0 优先级最高(设备上电时的定时心跳) } Nt26kPriority; typedef struct { Nt26kEvent event_flag; Nt26kPriority priority; const char *event_name; int (*send_func)(struct at_device *device, void *param); } Nt26kEventInfo; static void Nt26k_Set_Event(Nt26kEvent event_type) { if (event_type < kNt26kMaxEventcnt) { nt26k_event_flags[event_type] = (1 << event_type); } } void Nt26k_Event_Init(void) { rt_err_t ret = rt_event_init(&at_device_event, "nt26k_event", RT_IPC_FLAG_PRIO); if (ret == RT_EOK) { nt26k_event_initialized = RT_TRUE; for (Nt26kEvent event = kNt26kHeartbeatEvent; event < kNt26kMaxEventcnt; event++) { Nt26k_Set_Event(event); } } else { LOG_E("nt26k_event init failed!"); } } rt_uint32_t Nt26k_Get_Event_Flag(Nt26kEvent event_type) { if (event_type < kNt26kMaxEventcnt) { return nt26k_event_flags[event_type]; } return 0; } void Nt26k_Send_Event(Nt26kEvent event_type) { LOG_D("Send_Nt26k_Event = %d", event_type); nt26k_event_index.last_event = nt26k_event_index.current_event; nt26k_event_index.current_event = event_type; if (nt26k_event_initialized == RT_TRUE) { rt_event_send(&at_device_event, Nt26k_Get_Event_Flag(event_type)); } else { LOG_E("nt26k_event_initialized is false"); } } // 定义定时器回调函数 static void Nt26k_Ht_Timer_Cb(void *parameter) { Nt26k_Send_Event(kNt26kHeartbeatEvent); } // 定时器回调函数,当1分钟内没有数据交互时,关闭tcp连接 static void Nt26k_Error_Timer_Cb(void *parameter) { if (power_on_send_flag) // 上电成功时,停止定时器 { rt_timer_stop(nt26k_power_error_timer); } else { Nt26k_Send_Event(kNt26kPowerOnEvent); } } int _Pack_Send(struct Nt26k_Ops *ops, char *buf) { char nt26k_send_buf[512] = {0}; // 发送缓冲区,用于存储最终发送的数据 // char byteArr1[512]; // 转换成字节值 unsigned short crc16 = 0; // 存储CRC16校验和 struct at_device *device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, NT26K_SAMPLE_DEIVCE_NAME); ASSERT(device); crc16 = crc1021(buf, rt_strlen(buf)); LOG_D("buf: %s", buf); LOG_D("crc16: %X", crc16); // 将数据、校验和及尾部标识添加到发送缓冲区中 if (rt_snprintf(nt26k_send_buf, sizeof(nt26k_send_buf), "%s%04X%02X%02X%02X", buf, crc16, ops->frame->tail[0], ops->frame->tail[1], ops->frame->tail[2]) >= sizeof(nt26k_send_buf)) { // 发生缓冲区溢出 LOG_E("Buffer overflow in nt26k_send_buf"); return -RT_ERROR; } // 打印调试信息 // LOG_D("nt26k_send_buf: %s", nt26k_send_buf); rt_uint16_t data_len = rt_strlen(nt26k_send_buf); // 通过AT指令发送数据给NT26K模块 if (at_send_data(device, nt26k_send_buf, data_len / 2) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } /** * @brief 发送数据到nt26k模块 * * 本函数根据提供的数据和参数构建一个格式化字符串,计算其CRC16校验和, * 然后将该字符串发送给NT26K模块 *@param version 协议版本 * @param data 要发送的十六进制数据字符串 * @param len 数据字符串的十六进制数据格式长度 * @param data_num 数据编号 * @param cmd_num 命令编号 * @return int 返回0表示成功,非零表示失败 */ static int _Send_Handle(struct Nt26k_Ops *ops, rt_size_t data_num, rt_size_t cmd_num, const char *data) { // 临时缓冲区,用于格式化数据 char data_buf[512] = {0}; rt_size_t data_len = rt_strlen(data); // 格式化数据,构建发送给NT26K模块的数据包 rt_int32_t len = rt_snprintf(data_buf, sizeof(data_buf), "%02X%02X%02X%02X%04X%04X%02X%04X%s", ops->frame->header[0], ops->frame->header[1], ops->frame->header[2], ops->frame->version, // 协议版本 ops->frame->manufacture, // 制造商ID data_num, cmd_num, data_len / 2, data); if (len < 0 || len >= sizeof(data_buf)) { LOG_E("Send Data buffer overflow"); return -RT_ERROR; } // LOG_D("data_buf: %s", data_buf); return _Pack_Send(ops, data_buf); } // 初始化函数 int BSP_Nt26k_Init(struct Nt26k_Ops *ops, rt_uint8_t version) { if (ops->frame == RT_NULL) { LOG_E("Memory allocation failed"); return -RT_ENOMEM; } rt_memset(ops->frame, 0, sizeof(struct Nt26kDataFrame)); ops->frame->header[0] = 0x4A; ops->frame->header[1] = 0x54; ops->frame->header[2] = 0x34; ops->frame->version = version; ops->frame->manufacture = DEVICE_MANUFACTURE; ops->frame->tail[0] = 0x42; ops->frame->tail[1] = 0x4A; ops->frame->tail[2] = 0x51; return RT_EOK; } // 更新函数 int BSP_Nt26k_Update(struct Nt26k_Ops *ops, rt_uint8_t device_type, rt_uint8_t event_type) { ops->body->device_type = device_type; ops->body->event_type = event_type; ops->body->hw = (rt_uint8_t)Flash_Get_SysCfg(kHwVerId); ops->body->sw = (rt_uint8_t)Flash_Get_SysCfg(kSwVerId); rt_memcpy(ops->body->imei, &nt26k, sizeof(nt26k_sys_info)); // 直接赋值结构体数据 rt_memcpy(&(ops->body->lel), &H308.Data, (rt_ubase_t)offsetof(TsH308Data, checksum)); // 复制除了校验码以外的数据 ops->body->product_work_temperature = ops->body->temp; // 暂时定为激光器测量的环境温度 ops->body->work_duration = work_duration; ops->body->device_status = device_state_flag; ops->body->emv_status = emv_state_flag; ops->body->relay_status = relay_state_flag; return RT_EOK; } int Nt26k_Send_Data(struct Nt26k_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type) { int ret = 0; char data_buf[512] = {0}; char temp[3]; // 临时缓冲区,用于存储每个字节的十六进制表示 if (ops == NULL || ops->body == NULL) { // 处理 ops 或 ops->body 为 NULL 的情况 return RT_ERROR; // 或者抛出异常,返回错误码等 } if (sizeof(struct DataBody) == 0) { data_buf[0] = '\0'; // 确保 data_buf 被正确初始化 return RT_ERROR; } rt_memset(ops->body, 0, sizeof(struct DataBody)); rt_mutex_take(nt26k_mutex, RT_WAITING_FOREVER); ret = nt26k_ops.update_data(ops, device_type, event_type); if (ret == RT_EOK) { for (int i = 0; i < sizeof(struct DataBody); i++) { rt_snprintf(temp, sizeof(temp), "%02X", ((rt_uint8_t *)ops->body)[i]); rt_memcpy(data_buf + i * 2, temp, 2); } ret = _Send_Handle(ops, data_num, cmd, data_buf); if (ret != RT_EOK) { ret = -ret; } } rt_mutex_release(nt26k_mutex); return ret; } int Data_Resp(struct Nt26k_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type, char *data, rt_uint8_t res) { if (nt26k_conncet_tcp_flag != 1) { LOG_E("nt26k_conncet_tcp_flag error"); return -RT_ERROR; } char data_buf[512] = {0}; rt_int32_t len = rt_snprintf(data_buf, sizeof(data_buf), "%02X%02X%30s%02X", device_type, event_type, data, res); if (len < 0 || len >= sizeof(data_buf)) { LOG_E("Resp Data buffer overflow"); return -RT_ERROR; } // LOG_D("data_buf: %s", data_buf); return _Send_Handle(ops, data_num, cmd, data_buf); } int Nt26k_Recv_Data(struct Nt26k_Ops *ops, char *data) { // ops->body = (struct DataBody *)rt_malloc(sizeof(struct DataBody)); // rt_memset(ops->body, 0, sizeof(struct DataBody)); // rt_free(ops->body); return RT_EOK; } /***************************************发送处理函数************************************************ */ /** * 处理定时心跳事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Heartbeat(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; int ret = 0; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } ret = device->class->device_ops->control(device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL); if (ret != RT_EOK) { LOG_E("nt26k get signal failed\n"); return -RT_ERROR; } ret = nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_DATA_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_HEARTBEAT); if (ret != RT_EOK) { LOG_E("nt26k send data failed\n"); return ret; } return RT_EOK; } /** * 处理时间校准事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Time_Calibration(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_TIME_CALIBRATION, DEVICE_TYPE_NT26K, EVENT_TYPE_TIME_CALIBRATION)) { LOG_E("nt26k send cmd[%X] failed\n", CMD_TYPE_TIME_CALIBRATION); return -RT_ERROR; } return RT_EOK; } /** * 处理报警事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Alarm(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_ALARM)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_ALARM); return -RT_ERROR; } return RT_EOK; } /** * 处理报警恢复事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Alarm_Recover(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_ALARM_RECOVER)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_ALARM_RECOVER); return -RT_ERROR; } return RT_EOK; } /** * 处理故障事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Fault(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_FAULT)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_FAULT); return -RT_ERROR; } return RT_EOK; } /** * 处理故障恢复事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Fault_Recover(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_FAULT_RECOVER)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_FAULT_RECOVER); return -RT_ERROR; } return RT_EOK; } /** * 处理自检事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Self_Check(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_SELF_CHECK)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_SELF_CHECK); return -RT_ERROR; } return RT_EOK; } /** * 处理消音事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Silence(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_SILENCE)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_SILENCE); return -RT_ERROR; } return RT_EOK; } /** * 处理异常事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Exception(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_EXCEPTION)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_EXCEPTION); return -RT_ERROR; } return RT_EOK; } /** * 处理电磁阀状态改变事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Valve_Status(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_VALVE_STATUS)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_VALVE_STATUS); return -RT_ERROR; } return RT_EOK; } /** * 处理风扇状态改变事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Fan_Status(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_FAN_STATUS)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_FAN_STATUS); return -RT_ERROR; } return RT_EOK; } /** * 处理温度异常事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Temp_Anomaly(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_TEMP_ANOMALY)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_TEMP_ANOMALY); return -RT_ERROR; } return RT_EOK; } /** * 处理断电事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Power_Off(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_POWER_OFF)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_POWER_OFF); return -RT_ERROR; } return RT_EOK; } /** * 处理断电事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Power_On(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_POWER_ON)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_POWER_ON); return -RT_ERROR; } return RT_EOK; } /** * 处理设备故障事件 * @param device 设备结构体指针 * @param param 操作结构体指针 * @return 操作结果 */ int Nt26k_Send_Device_Failure(struct at_device *device, void *param) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; if ((device == RT_NULL) || (nt26k_ops == RT_NULL)) { LOG_E("nt26k param error\n"); return RT_ERROR; } if (nt26k_ops->send(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_NT26K, EVENT_TYPE_DEVICE_FAILURE)) { LOG_E("nt26k send cmd[%X] failed\n", EVENT_TYPE_DEVICE_FAILURE); return -RT_ERROR; } return RT_EOK; } /*这个【4、优先级最低当同时触发后,相同服务直接合并】暂时还没想好怎么做, 思路感觉就是得重新开一个线程,然后再开一个任务队列,将所有的事件,发送到任务队列 在线程中,对任务队列进行查看并处理,看目前都有哪些事件,是处于那个优先级得,如果是最低优先级,就只发送一帧数据就行了, 如果是不同优先级,按照优先级顺序发送事件,但感觉这样会使得程序更复杂,本来发送就很快,感觉没必要这样搞*/ const Nt26kEventInfo nt26k_event_info[] = { {kNt26kPowerOnEvent, NT26K_PRIORITY_HIGHEST, "上电心跳事件", Nt26k_Send_Power_On}, {kNt26kPowerDownEvent, NT26K_PRIORITY_HIGH, "掉电事件", Nt26k_Send_Power_Off}, {kNt26kSelfCheckEvent, NT26K_PRIORITY_MEDIUM, "自检事件", Nt26k_Send_Self_Check}, {kNt26kHeartbeatEvent, NT26K_PRIORITY_LOWEST, "定时心跳事件", Nt26k_Send_Heartbeat}, {kNt26kTempAnomalyEvent, NT26K_PRIORITY_LOWEST, "温度异常事件", Nt26k_Send_Temp_Anomaly}, {kNt26kAlarmEvent, NT26K_PRIORITY_LOWEST, "报警触发事件", Nt26k_Send_Alarm}, {kNt26kAlarmRcyEvent, NT26K_PRIORITY_LOWEST, "报警解除事件", Nt26k_Send_Alarm_Recover}, {kNt26kFaultEvent, NT26K_PRIORITY_LOWEST, "传感器故障事件", Nt26k_Send_Fault}, {kNt26kFaultRcyEvent, NT26K_PRIORITY_LOWEST, "传感器故障解除事件", Nt26k_Send_Fault_Recover}, {kNt26kTimeCalibrationEvent, NT26K_PRIORITY_LOWEST, "时间校准事件", Nt26k_Send_Time_Calibration}, {kNt26kSilenceEvent, NT26K_PRIORITY_LOWEST, "消音事件", Nt26k_Send_Silence}, {kNt26kExceptionEvent, NT26K_PRIORITY_LOWEST, "异常事件", Nt26k_Send_Exception}, {kNt26kValveStatusEvent, NT26K_PRIORITY_LOWEST, "电磁阀状态改变事件", Nt26k_Send_Valve_Status}, {kNt26kFanStatusEvent, NT26K_PRIORITY_LOWEST, "风机状态改变事件", Nt26k_Send_Fan_Status}, {kNt26kDeviceFailureEvent, NT26K_PRIORITY_LOWEST, "设备失效事件", Nt26k_Send_Device_Failure}}; /** * 处理NT26K设备的事件 * @param nt26k_recv_event 接收到的NT26K事件标志 * @return */ int Nt26k_Process_Events(Nt26kEvent nt26k_recv_event, struct at_device *device, void *param) { rt_uint8_t max_retry_count = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId); struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)param; const Nt26kEventInfo *event = RT_NULL; for (size_t i = 0; i < sizeof(nt26k_event_info) / sizeof(Nt26kEventInfo); ++i) { // 检查当前事件是否在接收到的事件标志中 if (nt26k_recv_event == nt26k_event_info[i].event_flag) { event = &nt26k_event_info[i]; break; } } if (event) // 处理该事件 { // 打印事件的名称 LOG_D("%s上报\n", event->event_name); for (size_t i = 0; i < max_retry_count; i++) { if (nt26k_conncet_tcp_flag) { if (event->send_func) { #ifdef TEST_ENABLE RTC_ShowTime(); // 每次发送打印下时间,容易定位问题 #endif // 如果事件有关联的发送函数,则调用该发送函数 rt_thread_mdelay(IMEI_Delay()); int result = event->send_func(device, nt26k_ops); if (result != RT_EOK) { LOG_E("nt26k send cmd failed\n"); nt26k_conncet_tcp_flag = 0; if (!nt26k_disconnect_retry_flag) { LOG_D("断网,启动重连\n"); rt_sem_release(nt26k_disconnect_sem); } rt_thread_mdelay(5000); continue; } else { if ((rt_strcmp(event->event_name, "定时心跳事件") == RT_EOK) || (rt_strcmp(event->event_name, "上电心跳事件") == RT_EOK)) // 定时心跳是有回应的 { if (rt_sem_take(nt26k_recv_heart_sem, 5000) == RT_EOK) { LOG_D("收到心跳回复\n"); return RT_EOK; // 函数执行完毕,返回0 } else { LOG_E("nt26k send cmd failed\n"); // 收不到说明断网了,重连下10s后再发送 LOG_D("rt_sem_release (nt26k_disconnect_sem)"); nt26k_conncet_tcp_flag = 0; rt_thread_mdelay(1); rt_sem_release(nt26k_disconnect_sem); rt_thread_mdelay(5000); continue; } } else { return RT_EOK; // 函数执行完毕,返回0 } } if (rt_strcmp(event->event_name, "掉电事件") == RT_EOK) { rt_uint8_t cnt = 0; while ((device_power_down_flag == 0)&&(cnt < 10)) { rt_thread_mdelay(500); } if (device->class->device_ops->control(device, AT_DEVICE_CTRL_POWER_OFF, RT_NULL) == RT_EOK) { LOG_D("关闭模组"); nt26k_power_down_flag = 1; return RT_EOK; } } } } else { if (!nt26k_disconnect_retry_flag) { LOG_D("断网,启动重连\n"); rt_sem_release(nt26k_disconnect_sem); } LOG_D("断网,等待连接中......\n"); } rt_thread_mdelay(5000); } } // 函数执行完毕,返回0 return RT_EOK; } // 比较帧头和帧尾 int Compare_HeaderToTail(struct Nt26k_Ops *ops) { // 比较帧头 for (int i = 0; i < 3; i++) { if (ops->frame->header[i] != ops->recv->header[i]) { LOG_E("ops->frame->header[%x] != ops->recv->header[%x]\n", ops->frame->header[i], ops->recv->header[i]); return -1; } } // 比较帧尾 for (int i = 0; i < 3; i++) { if (ops->frame->tail[i] != ops->recv->tail[i]) { LOG_E("ops->frame->tail[%x] != ops->recv->tail[%x]\n", ops->frame->tail[i], ops->recv->tail[i]); return -2; } } if (ops->recv->recv_data.res_num != RESPONSE_CODE_SUCCESS) // 判断是否为成功响应 { LOG_E("ops->recv->recv_data.res_num[%x] != RESPONSE_CODE_SUCCESS\n", ops->recv->recv_data.res_num); return -3; } return RT_EOK; } void Handle_Server_Reply(struct Nt26k_Ops *ops) { if ((ops->recv->recv_data.event_type == INSTRUCTION_HEART_BEAT) || (ops->recv->recv_data.event_type == EVENT_TYPE_POWER_ON)) { LOG_D("nt26k send data success\n"); } else if (ops->recv->recv_data.event_type == EVENT_TYPE_POWER_OFF)//是掉电事件回应 { device_power_down_flag = 1; } } void Handle_Self_Check(struct Nt26k_Ops *ops) { LOG_D("服务器下发自检指令\n"); char imei[16] = {0}; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); LOG_D("imei:%s\n", imei); char temp[32] = "0"; String2Hex(temp, imei); // 将字符串转为十六进制字符串 LOG_D("temp: %s", temp); Send_Laser_Alarm_Event(kSelfCheckEvent); rt_thread_mdelay(100); ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_SELF_CHECK, temp, RESPONSE_CODE_SUCCESS); } void Handle_Mute(struct Nt26k_Ops *ops) { LOG_D("服务器下发消音指令\n"); char imei[16] = {0}; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); char temp[32] = "0"; String2Hex(temp, imei); // 将字符串转为十六进制字符串 Send_Laser_Alarm_Event(KMuteEvent); rt_thread_mdelay(100); ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_MUTE, temp, RESPONSE_CODE_SUCCESS); } void Handle_Close_Valve(struct Nt26k_Ops *ops) { LOG_D("服务器下发关闭阀门指令\n"); char imei[16] = {0}; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); char temp[32] = "0"; String2Hex(temp, imei); // 将字符串转为十六进制字符串 EMV_CLOSE_VALVE; ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_SUCCESS); } void Handle_Open_Valve(struct Nt26k_Ops *ops) { LOG_D("服务器下发打开阀门指令\n"); // char imei[16] = {0}; // Get_IotImei(imei, FLASH_IOT_IMEI_LEN); // char temp[32] = "0"; // String2Hex(temp, imei); // 将字符串转为十六进制字符串 // // rt_uint8_t ret = BSP_Set_Emv_Status(1); // emv_state_flag = 1; // 电磁阀动作 // rt_thread_mdelay(20); // emv_state_flag = 0; // ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_OPEN_VALVE, temp, RESPONSE_CODE_SUCCESS); } void Handle_Open_Relay(struct Nt26k_Ops *ops) { LOG_D("服务器下发打开继电器指令\n"); char imei[16] = {0}; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); char temp[32] = "0"; String2Hex(temp, imei); // 将字符串转为十六进制字符串 relay_state_flag = 1; rt_thread_mdelay(10); // rt_uint8_t ret = BSP_Set_Relay_Status(0); ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_OPEN_RELAY, temp, RESPONSE_CODE_SUCCESS); } void Handle_Close_Relay(struct Nt26k_Ops *ops) { LOG_D("服务器下发关闭继电器指令\n"); char imei[16] = {0}; char temp[32] = "0"; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); String2Hex(temp, imei); // 将字符串转为十六进制字符串 relay_state_flag = 0; rt_thread_mdelay(100); ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CLOSE_RELAY, temp, RESPONSE_CODE_SUCCESS); } void Handle_Query_Params(struct Nt26k_Ops *ops) { rt_uint8_t data[10] = {0}; char str[64] = {0}; LOG_D("服务器下发查询系统参数\n"); rt_memcpy(data, (rt_uint8_t *)FLASH_HW_VER_ADDR, sizeof(sys_config_info) - 50); LOG_D("hw_ver:%02x sw_ver:%02x alarm_low:%02x alarm_high:%02x temp_alarm:%02x iot_upload_cycle:%dmin retry:%02x emagnetic:%02X relay_switch:%02X\n", data[0], data[1], data[2], data[3], data[4], ((data[5]) | (data[6] << 8)), data[7], data[8], data[9]); rt_sprintf(str, "0000000000%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]); rt_thread_mdelay(100); // 释放下线程 ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_QUERY_PARAMS, str, RESPONSE_CODE_SUCCESS); } int Handle_Config_Params(struct Nt26k_Ops *ops) { char data_buf[32] = {0}; rt_uint8_t recv_data[16] = {0}; rt_uint8_t flash_info[16] = {0}; char imei[16] = {0}; char temp[32] = "0"; LOG_D("服务器下发配置参数\n"); Get_IotImei(imei, FLASH_IOT_IMEI_LEN); String2Hex(temp, imei); // 将字符串转为十六进制字符串 rt_memset(data_buf, '0', 32); rt_memcpy(recv_data, (ops->recv->recv_data.res_data + 5), sizeof(sys_config_info) - 50); rt_memcpy(flash_info, (rt_uint8_t *)FLASH_HW_VER_ADDR, sizeof(sys_config_info) - 50); LOG_D("hw_ver:%02x sw_ver:%02x alarm_low:%02x alarm_high:%02x temp_alarm:%02x iot_upload_cycle:%d min retry:%02x emagnetic:%02X relay_switch:%02X\n", flash_info[0], flash_info[1], flash_info[2], flash_info[3], flash_info[4], (flash_info[5] | (flash_info[6] << 8)), flash_info[7], flash_info[8], recv_data[9]); LOG_D("recv_data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n", recv_data[0], recv_data[1], recv_data[2], recv_data[3], recv_data[4], recv_data[5], recv_data[6], recv_data[7], recv_data[8], recv_data[9], recv_data[10], recv_data[11], recv_data[12], recv_data[13], recv_data[14], recv_data[15]); LOG_D("data:%s\n", data_buf); for (rt_uint8_t i = 0; i < (sizeof(sys_config_info) - 50); i++) { LOG_D("recv_data[%d] = %d", i, recv_data[i]); if (recv_data[i] != flash_info[i]) { if ((recv_data[2] > 25) || (recv_data[2] < 5)) /*家报的报警设定值应在5%~25%之间*/ { if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_ACTION_FAILURE) == RT_EOK) { LOG_W("recv_data[3] :%d", recv_data[3]); LOG_W("配置参数超出范围,请核实后重试\n"); } return RT_EOK; } else // 如果没有超出,再写入信息 { if (BSP_Flash_Write_Info(recv_data, sizeof(sys_config_info) - 50) != 0) { rt_uint32_t iot_upload_time = (uint16_t)Flash_Get_SysCfg(kIotUploadCycleId); rt_uint32_t timeout = iot_upload_time * 60 * RT_TICK_PER_SECOND; if (iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND) { timeout = 24 * 60 * 60 * RT_TICK_PER_SECOND; LOG_E("iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND"); } else { timeout = iot_upload_time * 60 * RT_TICK_PER_SECOND; } rt_timer_control(nt26k_timer, RT_TIMER_CTRL_SET_TIME, (void *)&timeout); // 更新上报周期 rt_timer_start(nt26k_timer); LOG_D("上报周期由%dmin更新为%dmin", ((flash_info[5] << 8) | flash_info[6]), iot_upload_time); if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_SUCCESS) == RT_EOK) { LOG_D("配置参数写入成功\n"); } return RT_EOK; } else { LOG_D("配置参数写入失败\n"); if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_ACTION_FAILURE) == RT_EOK) { LOG_D("写入失败响应成功\n"); } return RT_ERROR; } } } } if (ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_SUCCESS) == RT_EOK) { LOG_D("配置参数没有变化\n"); } return RT_EOK; } void Handle_Time_Calibration_Data(struct Nt26k_Ops *ops) { rt_uint8_t data[10] = {0}; TsRtcDateTime rtc_dt; char imei[16] = {0}; char temp[32] = "0"; LOG_D("时间校准数据\n"); Get_IotImei(imei, FLASH_IOT_IMEI_LEN); String2Hex(temp, imei); // 将字符串转为十六进制字符串 rt_memcpy(data, ops->recv->recv_data.res_data, sizeof(data)); // 提取后4个字节作为时间戳 time_t timestamp = (data[6] << 24) | (data[7] << 16) | (data[8] << 8) | data[9]; Timestamp_To_Rtc_DateTime(timestamp, &rtc_dt); // 打印结果 LOG_I("时间: %04d-%02d-%02d %02d:%02d:%02d (星期%d)\n", rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second, rtc_dt.week); RTC_SetTime(rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, 0); /* Setup Time */ rt_thread_mdelay(100); // 释放下线程 ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_TIME_CALIBRATION, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_TIME_CALIBRATION, temp, RESPONSE_CODE_SUCCESS); } // 下发修改服务器地址指令 void Handle_Sever_Addr_Set(struct Nt26k_Ops *ops) { rt_uint8_t data[6] = {0}; char imei[16] = {0}; char temp[32] = "0"; flash_sever_info sever_info= {0}; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); String2Hex(temp, imei); // 将字符串转为十六进制字符串 rt_memcpy(data, (ops->recv->recv_data.res_data + 9), FLASH_SERVER_LEN); LOG_D("data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x data[%d] = %x", 0, data[0], 1, data[1], 2, data[2], 3, data[3], 4, data[4], 5, data[5]); Flash_Set_Sever_Data(data); rt_thread_mdelay(10); if (Flash_Get_Sever_Data(&sever_info) != RT_EOK) { LOG_E("服务器地址修改失败\n"); } else { LOG_D("服务器地址修改成功\n"); if(ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_SEVER_ADDR, temp, RESPONSE_CODE_SUCCESS)==RT_EOK) { Flash_Set_WorkDuration(work_duration); rt_thread_mdelay(2000); reboot(); } } } void Handle_Error(struct Nt26k_Ops *ops, rt_err_t ret) { LOG_E("数据帧解析失败,错误码: %d", ret); char imei[16] = {0}; char temp[32] = "0"; Get_IotImei(imei, FLASH_IOT_IMEI_LEN); String2Hex(temp, imei); // 将字符串转为十六进制字符串 ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, ops->recv->cmd, temp, RESPONSE_CODE_PARSE_FAIL); } void Handle_Instruction_Down(struct Nt26k_Ops *ops) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)ops; switch (nt26k_ops->recv->recv_data.event_type) { case INSTRUCTION_DOWN_SELF_CHECK: Handle_Self_Check(nt26k_ops); break; case INSTRUCTION_DOWN_MUTE: Handle_Mute(nt26k_ops); break; case INSTRUCTION_DOWN_CLOSE_VALVE: Handle_Close_Valve(nt26k_ops); break; case INSTRUCTION_DOWN_OPEN_VALVE: Handle_Open_Valve(nt26k_ops); break; case INSTRUCTION_DOWN_OPEN_RELAY: Handle_Open_Relay(nt26k_ops); break; case INSTRUCTION_DOWN_CLOSE_RELAY: Handle_Close_Relay(nt26k_ops); break; case INSTRUCTION_DOWN_QUERY_PARAMS: Handle_Query_Params(nt26k_ops); break; case INSTRUCTION_DOWN_CONFIG_PARAMS: Handle_Config_Params(nt26k_ops); break; case INSTRUCTION_DOWN_TIME_CALIBRATION: Handle_Time_Calibration_Data(nt26k_ops); break; case INSTRUCTION_DOWN_SEVER_ADDR: Handle_Sever_Addr_Set(nt26k_ops); break; } } void Handle_Time_Calibration(struct Nt26k_Ops *ops) { rt_uint8_t data[10] = {0}; LOG_D("服务器下发时间校准数据\n"); rt_memcpy(data, ops->recv->recv_data.res_data, sizeof(data)); TsRtcDateTime rtc_dt; // 提取后4个字节作为时间戳 time_t timestamp = (data[6] << 24) | (data[7] << 16) | (data[8] << 8) | data[9]; Timestamp_To_Rtc_DateTime(timestamp, &rtc_dt); // 打印结果 LOG_I("时间: %04d-%02d-%02d %02d:%02d:%02d (星期%d)\n", rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second, rtc_dt.week); RTC_SetTime(rtc_dt.year, rtc_dt.month, rtc_dt.day, rtc_dt.hour, rtc_dt.minute, rtc_dt.second); /* Setup Time */ ops->Resp(ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, INSTRUCTION_DOWN_TIME_CALIBRATION, NT26K_DEFIENE_DATA, RESPONSE_CODE_SUCCESS); } void Handle_Cmd_Type(struct Nt26k_Ops *ops) { struct Nt26k_Ops *nt26k_ops = (struct Nt26k_Ops *)ops; switch (nt26k_ops->recv->cmd) { case CMD_TYPE_SERVER_REPLY: Handle_Server_Reply(nt26k_ops); break; case CMD_TYPE_INSTRUCTION_DOWN: Handle_Instruction_Down(nt26k_ops); break; case CMD_TYPE_TIME_CALIBRATION: Handle_Time_Calibration(nt26k_ops); break; default: nt26k_ops->Resp(nt26k_ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_NT26K, ops->recv->cmd, NT26K_DEFIENE_DATA, RESPONSE_CODE_PARSE_FAIL); break; } } void Analyze_Recv_Frame(struct at_device *device, struct Nt26k_Ops *ops) { rt_err_t ret = RT_EOK; ret = Compare_HeaderToTail(ops); if (ret == RT_EOK) { Handle_Cmd_Type(ops); } else { Handle_Error(ops, ret); } } /* 上电模式 发送一包数据后,转换到检测模式 120分钟发送一次数据 当有事件发生时,发送一包事件数据包 */ static void Nt26k_Send_Thread_Entry(void *param) { rt_err_t result = RT_EOK; rt_uint32_t nt26k_recv_event; LOG_D("nt26k thread entry\n"); struct Nt26k_Ops *ops = (struct Nt26k_Ops *)param; struct at_device_nt26k *nt26k = &_dev; struct at_device *device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, nt26k->device_name); RT_ASSERT(device); if (ops->init(ops, PROTOCOL_VERSION) != RT_EOK) { LOG_E("nt26k init failed\n"); } else { LOG_D("nt26k init success\n"); rt_completion_wait(&nt26k_init_complate, RT_WAITING_FOREVER); // wait for nt26k init finish Nt26k_Send_Event(kNt26kPowerOnEvent); } while (1) { result = rt_event_recv(&at_device_event, Nt26k_Get_Event_Flag(kNt26kPowerOnEvent) | Nt26k_Get_Event_Flag(kNt26kHeartbeatEvent) | Nt26k_Get_Event_Flag(kNt26kSelfCheckEvent) | Nt26k_Get_Event_Flag(kNt26kSilenceEvent) | Nt26k_Get_Event_Flag(kNt26kExceptionEvent) | Nt26k_Get_Event_Flag(kNt26kValveStatusEvent) | Nt26k_Get_Event_Flag(kNt26kFanStatusEvent) | Nt26k_Get_Event_Flag(kNt26kTempAnomalyEvent) | Nt26k_Get_Event_Flag(kNt26kPowerOnEvent) | Nt26k_Get_Event_Flag(kNt26kPowerDownEvent) | Nt26k_Get_Event_Flag(kNt26kAlarmEvent) | Nt26k_Get_Event_Flag(kNt26kAlarmRcyEvent) | Nt26k_Get_Event_Flag(kNt26kFaultEvent) | Nt26k_Get_Event_Flag(kNt26kFaultRcyEvent) | Nt26k_Get_Event_Flag(kNt26kDeviceFailureEvent) | Nt26k_Get_Event_Flag(kNt26kTimeCalibrationEvent), RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &nt26k_recv_event); // 这个事件一般是设备端发生了变化,发送到服务器时调用 if (result == RT_EOK) { if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kPowerOnEvent)) { result = Nt26k_Process_Events(kNt26kPowerOnEvent, device, ops); // 当上电心跳包发送不成功时,其他事件不启动 if (result) { power_on_send_flag = 0; rt_timer_start(nt26k_power_error_timer); // 启动重连定时器, 3min一次,直到发送成功 LOG_E("nt26k send data failed result = [%d]\n", result); } else { rt_timer_start(nt26k_timer); // 当上电心跳包发送成功时, 开始心跳包周期发送 rt_timer_start(nt26k_upload_timer); // 周期修改时间更新 power_on_send_flag = 1; } } if (power_on_send_flag) { if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kHeartbeatEvent)) { result = Nt26k_Process_Events(kNt26kHeartbeatEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kTimeCalibrationEvent)) { Time_Calibration(device); } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kAlarmEvent)) { result = Nt26k_Process_Events(kNt26kAlarmEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kAlarmRcyEvent)) { result = Nt26k_Process_Events(kNt26kAlarmRcyEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kFaultEvent)) { if (device_state_flag != 1) // 当设备失效时,只上报失效信息 { result = Nt26k_Process_Events(kNt26kFaultEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kFaultRcyEvent)) { result = Nt26k_Process_Events(kNt26kFaultRcyEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kSelfCheckEvent)) { result = Nt26k_Process_Events(kNt26kSelfCheckEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kSilenceEvent)) { result = Nt26k_Process_Events(kNt26kSilenceEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kExceptionEvent)) { result = Nt26k_Process_Events(kNt26kExceptionEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kValveStatusEvent)) { result = Nt26k_Process_Events(kNt26kValveStatusEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kFanStatusEvent)) { result = Nt26k_Process_Events(kNt26kFanStatusEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kTempAnomalyEvent)) { result = Nt26k_Process_Events(kNt26kTempAnomalyEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kPowerDownEvent)) { nt26k_event_initialized = RT_FALSE; // 当接收到掉电事件时,发送完成后删除事件,不再接收其他事件 result = Nt26k_Process_Events(kNt26kPowerDownEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kDeviceFailureEvent)) { result = Nt26k_Process_Events(kNt26kDeviceFailureEvent, device, ops); if (result) { LOG_E("nt26k send data failed result = [%d]\n", result); } } } } } } static void Nt26k_Recv_Thread_Entry(void *parameter) { struct Nt26k_Ops *ops = (struct Nt26k_Ops *)parameter; struct at_device_nt26k *nt26k = &_dev; struct at_device *device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, nt26k->device_name); RT_ASSERT(device); LOG_D("nt26k recv thread entry\n"); while (1) { rt_sem_take(nt26k_recv_sem, RT_WAITING_FOREVER); // 这个主要用来处理的数据 /*对数据帧进行分析,判断所处的是对服务器响应还是指令下发*/ Analyze_Recv_Frame(device, ops); } } static void Nt26k_Life_Thread_Entry(void *parameter) { struct at_device_nt26k *nt26k = &_dev; struct at_device *device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, nt26k->device_name); RT_ASSERT(device); rt_err_t result = RT_EOK; rt_uint32_t delay_n = 1; LOG_D("nt26k_life_thread entry\n"); while (1) { result = rt_sem_take(nt26k_disconnect_sem, RT_WAITING_FOREVER); if (result == RT_EOK) { if (!nt26k_conncet_tcp_flag) { LOG_D("重连网络中...\n"); nt26k_connect_sever_flag = 0; at_response_t resp = at_create_resp(64, 0, 5000); if (resp == RT_NULL) { LOG_E("No memory for response structure!"); at_delete_resp(resp); result = -RT_ETIMEOUT; } if (device->class->device_ops->control(device, AT_DEVICE_CTRL_POWER_ON, RT_NULL) == RT_EOK) { LOG_D("AT device power on success"); rt_thread_mdelay(1000); /* disable echo */ at_obj_exec_cmd(device->client, resp, "ATE0"); /*AT+QICFG="dataformat" 设置收发模式*/ if (at_obj_exec_cmd(device->client, resp, "AT+QICFG=\"dataformat\",%d,%d", AT_NSONMI_MODE_DEFAULT, AT_NSONMI_MODE_DEFAULT) != RT_EOK) { LOG_E("AT+QICFG=\"dataformat\" error\n"); result = -RT_ETIMEOUT; goto __exit; } /*设置显示模式*/ if (at_obj_exec_cmd(device->client, resp, "AT+QICFG=\"viewmode\",1") != RT_EOK) { LOG_E("AT+QICFG=\"viewmode\" error\n"); result = -RT_ETIMEOUT; goto __exit; } /*设置保活信息*/ if (at_obj_exec_cmd(device->client, resp, "AT+QICFG=\"tcp/keepalive\",1,1000,100,10") != RT_EOK) { LOG_E("AT+QICFG=\"tcp/keepalive\" error\n"); result = -RT_ETIMEOUT; goto __exit; } if (at_obj_exec_cmd(device->client, resp, "AT+QICFG=\"passiveclosed\",1") != RT_EOK) { LOG_E("AT+QICFG=\"passiveclosed\" error\n"); result = -RT_ETIMEOUT; goto __exit; } if (at_obj_exec_cmd(device->client, resp, "AT+CGACT=1,1") != RT_EOK) { LOG_E("AT+CGACT=1,1 error\n"); result = -RT_ETIMEOUT; goto __exit; } if (device->class->device_ops->control(device, AT_DEVICE_CTRL_NET_CONN, RT_NULL) == RT_EOK) { LOG_D("重连网络成功\n"); nt26k_conncet_tcp_flag = RT_TRUE; delay_n = 0; nt26k_disconnect_retry_flag = 0; } else { device->class->device_ops->control(device, AT_DEVICE_RF_CLOSE, RT_NULL); result = -RT_ETIMEOUT; goto __exit; } at_delete_resp(resp); } } } else { delay_n = 0; goto __exit; } __exit: if (result != RT_EOK) { LOG_D("重连网络失败,等待%d s后重连\n",delay_n * 5); rt_thread_mdelay(delay_n * 5000); delay_n++; if (delay_n >= 66)//大于3小时的重连都不行,则重启设备 { Flash_Set_WorkDuration(work_duration); delay_n = 0; reboot(); } rt_sem_release(nt26k_disconnect_sem); nt26k_disconnect_retry_flag = 1; } } } // 定时器回调函数,当1分钟内没有数据交互时,关闭tcp连接 static void Nt26k_Upload_Timer_Cb(void *parameter) { Nt26k_Send_Event(kNt26kTimeCalibrationEvent); // 更新下时间 } int BSP_Nt26k_Thread_Init(void) { rt_err_t ret; Nt26k_Event_Init(); rt_uint32_t iot_upload_time = (uint16_t)Flash_Get_SysCfg(kIotUploadCycleId); rt_uint32_t timeout = 0; if (iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND) { timeout = 24 * 60 * 60 * RT_TICK_PER_SECOND; LOG_E("iot_upload_time > 24 * 60 * 60 * RT_TICK_PER_SECOND"); } else { timeout = iot_upload_time * 60 * RT_TICK_PER_SECOND; } LOG_I("上报服务器周期:%d分钟", iot_upload_time); nt26k_mutex = rt_mutex_create("nt26k_mutex", RT_IPC_FLAG_PRIO); if (nt26k_mutex == RT_NULL) { LOG_E("nt26k_mutex create failed"); } nt26k_recv_sem = rt_sem_create("nt26k_recv", 0, RT_IPC_FLAG_PRIO); if (nt26k_recv_sem == RT_NULL) { LOG_E("nt26k_recv_sem create failed"); } nt26k_recv_heart_sem = rt_sem_create("nt26k_recv_heart", 0, RT_IPC_FLAG_PRIO); if (nt26k_recv_heart_sem == RT_NULL) { LOG_E("nt26k_recv_heart_sem create failed"); } nt26k_disconnect_sem = rt_sem_create("nt26k_life", 0, RT_IPC_FLAG_PRIO); if (nt26k_disconnect_sem == RT_NULL) { LOG_E("nt26k_disconnect_sem create failed"); } LOG_D("定时周期ticks = %d", timeout); // 创建定时器 nt26k_timer = rt_timer_create("heartbeat", Nt26k_Ht_Timer_Cb, // 回调函数 RT_NULL, // 参数 timeout, // 定时周期(120分钟) RT_TIMER_FLAG_PERIODIC); // 周期性定时器 if (nt26k_timer == RT_NULL) { rt_kprintf("创建定时器失败\n"); return -1; } nt26k_power_error_timer = rt_timer_create("nt26k_error_timer", Nt26k_Error_Timer_Cb, RT_NULL, 3 * 60 * RT_TICK_PER_SECOND, // (3分钟) RT_TIMER_FLAG_PERIODIC); nt26k_upload_timer = rt_timer_create("nt26k_upload_timer", Nt26k_Upload_Timer_Cb, RT_NULL, 24 * 60 * 60 * RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC); ret = rt_thread_init(&nt26k_thread, "nt26k_send_thread", Nt26k_Send_Thread_Entry, &nt26k_ops, &nt26k_thread_stack[0], sizeof(nt26k_thread_stack), NT26K_THREAD_PRIORITY, NT26K_THREAD_TICKS); rt_thread_startup(&nt26k_thread); ret = rt_thread_init(&nt26k_recv_thread, "nt26k_recv_thread", Nt26k_Recv_Thread_Entry, &nt26k_ops, &nt26k_recv_thread_stack[0], sizeof(nt26k_recv_thread_stack), NT26K_RECV_THREAD_PRIORITY, NT26K_RECV_THREAD_TICKS); rt_thread_startup(&nt26k_recv_thread); ret = rt_thread_init(&nt26k_life_thread, "nt26k_life_thread", Nt26k_Life_Thread_Entry, &nt26k_ops, &nt26k_life_thread_stack[0], sizeof(nt26k_life_thread_stack), NT26K_LIFE_THREAD_PRIORITY, NT26K_LIFE_THREAD_TICKS); rt_thread_startup(&nt26k_life_thread); return ret; } // INIT_APP_EXPORT(BSP_Nt26k_Thread_Init); static int nt26k_device_register(void) { struct at_device_nt26k *nt26k = &_dev; return at_device_register(&(nt26k->device), nt26k->device_name, nt26k->client_name, AT_DEVICE_CLASS_NT26K, (void *)nt26k); } INIT_COMPONENT_EXPORT(nt26k_device_register); #endif // IOT_MODULE_SWITCH