JT-DT-YD4N02B_4G_RTT_MRS/bsp/src/bsp_nt26k.c

1683 lines
60 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: mbw
* @Date: 2024-10-09 08:42:14
* @LastEditors: mbw && 1600520629@qq.com
* @LastEditTime: 2025-02-06 09:27:48
* @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 <at_device_nt26k.h>
#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 <at_log.h>
#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_msg_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_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_send_error_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_FIFO);
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)
{
if (nt26k_event_index.current_event != kNt26kPowerOnEvent)
{
if (power_on_send_flag)
{
rt_event_send(&at_device_event, Nt26k_Get_Event_Flag(event_type));
}
}
else
{
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_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_err_t ret = RT_EOK;
rt_uint8_t max_retry_count = (rt_uint8_t)Flash_Get_SysCfg(kIotRetryId);
LOG_D("max_retry_count:%d\n", max_retry_count);
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 failed\n");
ret = RT_ERROR;
continue;
}
else
{
if (rt_sem_take(nt26k_recv_msg_sem, 5000) == RT_EOK)
{
LOG_D("收到回复\n");
nt26k_connect_sever_flag = 1;
ret = RT_EOK; // 函数执行完毕返回0
break;
}
else
{
// 收不到说明在平台未注册,此时nt26k_connect_sever_flag 为0但nt26k_conncet_tcp_flag = 1此时不发起重连等待事件触发就行
nt26k_connect_sever_flag = 0;
ret = RT_ERROR;
}
}
}
}
else
{
if (!nt26k_disconnect_retry_flag)
{
LOG_D("断网,启动重连\n");
rt_sem_release(nt26k_disconnect_sem);
}
LOG_D("断网,等待连接中......\n");
ret = RT_ERROR;
}
rt_thread_mdelay(3000);
}
}
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;
ret = RT_EOK;
}
}
return ret;
}
// 比较帧头和帧尾
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");
}
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(100);
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 != RT_EOK)
{
power_on_send_flag = 0;
rt_timer_start(nt26k_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 != RT_EOK)
{
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 != RT_EOK)
{
if (SysControl.status == kAlarmEvent)
{
Nt26k_Send_Event(kNt26kAlarmEvent);
}
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 != RT_EOK)
{
LOG_E("nt26k send data failed result = [%d]\n", result);
if (SysControl.status == kAlarmRcyEvent)
{
Nt26k_Send_Event(kNt26kAlarmRcyEvent);
}
}
}
else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kFaultEvent))
{
result = Nt26k_Process_Events(kNt26kFaultEvent, device, ops);
if (result != RT_EOK)
{
LOG_E("nt26k send data failed result = [%d]\n", result);
if (SysControl.status == kFaultEvent)
{
Nt26k_Send_Event(kNt26kFaultEvent);
}
}
}
else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kFaultRcyEvent))
{
result = Nt26k_Process_Events(kNt26kFaultRcyEvent, device, ops);
if (result != RT_EOK)
{
LOG_E("nt26k send data failed result = [%d]\n", result);
if (SysControl.status == kFaultRcyEvent)
{
Nt26k_Send_Event(kNt26kFaultRcyEvent);
}
}
}
else if (nt26k_recv_event & Nt26k_Get_Event_Flag(kNt26kSelfCheckEvent))
{
result = Nt26k_Process_Events(kNt26kSelfCheckEvent, device, ops);
if (result != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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 != RT_EOK)
{
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");
/* disable echo */
at_client_obj_wait_connect(device->client, 5000);
/*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)
{
nt26k_disconnect_retry_flag = 1;
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);
}
}
}
// 定时器回调函数,当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 = (uint32_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;
if (timeout >= RT_TICK_MAX / 2)//超了就直接默认值
{
timeout = 60 * 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_msg_sem = rt_sem_create("nt26k_recv_heart", 0, RT_IPC_FLAG_PRIO);
if (nt26k_recv_msg_sem == RT_NULL)
{
LOG_E("nt26k_recv_msg_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, // 参数
(rt_uint32_t)timeout, // 定时周期(单位:分钟)
RT_TIMER_FLAG_PERIODIC); // 周期性定时器
if (nt26k_timer == RT_NULL)
{
rt_kprintf("创建定时器失败\n");
return -1;
}
nt26k_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