BLE_TYQ_BJQ_CH32V303/bsp/src/bsp_ml307.c

2288 lines
86 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-11-30 15:46:21
* @LastEditors: mbw && 1600520629@qq.com
* @LastEditTime: 2025-05-29 10:03:26
* @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_ml307.c
* @Description:
*
* Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
*/
#include <at_device_ml307.h>
#include "drv_gpio.h"
#include "bsp_ml307.h"
#include "user_sys.h"
#include "bsp_flash.h"
#include "stddef.h"
#include "bsp_rtc.h"
#include "bsp_bt.h"
#include "bsp_mq.h"
#include "user_sys.h"
#include "bsp_rtc.h"
#define LOG_TAG "ml307"
#include <at_log.h>
#if IOT_MODULE_SWITCH == 1
#define ML307_THREAD_STACK_SIZE (4096 + 2048)
#define ML307_RECV_THREAD_STACK_SIZE (4096 + 2048)
#define ML307_LIFE_THREAD_STACK_SIZE (4096)
#define ML307_THREAD_PRIORITY 25
#define ML307_THREAD_TICKS 50
#define ML307_RECV_THREAD_PRIORITY 24
#define ML307_RECV_THREAD_TICKS 10
#define ML307_LIFE_THREAD_PRIORITY 26
#define ML307_LIFE_THREAD_TICKS 10
// static rt_uint32_t ml307_status = 0;
ALIGN (RT_ALIGN_SIZE)
static char ml307_thread_stack[ML307_THREAD_STACK_SIZE];
static struct rt_thread ml307_thread;
ALIGN (RT_ALIGN_SIZE)
static char ml307_recv_thread_stack[ML307_RECV_THREAD_STACK_SIZE];
static struct rt_thread ml307_recv_thread;
ALIGN (RT_ALIGN_SIZE)
static char ml307_life_thread_stack[ML307_LIFE_THREAD_STACK_SIZE];
static struct rt_thread ml307_life_thread;
struct rt_event at_device_event;
rt_sem_t ml307_recv_sem;
rt_sem_t ml307_recv_msg_sem; // 用于接收信号
rt_sem_t ml307_disconnect_sem;
static rt_timer_t ml307_timer; // 上报心跳
static rt_timer_t ml307_upload_timer; // 更新本地时间定时器
static rt_timer_t ml307_error_timer; // 上电失败情况下启动定时器
rt_uint8_t ml307_power_down_flag;
rt_uint8_t ml307_connect_sever_flag;
rt_uint8_t ml307_send_error_flag;
rt_uint8_t ml307_conncet_tcp_flag;
rt_uint8_t ml307_disconnect_pdp_flag; // PDP断开连接标志
rt_uint8_t ml307_disconnect_retry_flag = 0; // 用于判断是否已经启动了重连,如果启动,不需要每次都进入
Ml307EventIndex ml307_event_index;
Ml307Event ml307_current_evnet = kMl307PowerOnEvent; // 默认上电事件
Ml307Event ml307_latest_evnet = kMl307PowerOnEvent; // 最新传入的事件
rt_uint8_t power_on_send_flag = 0;
rt_mutex_t ml307_mutex;
extern valve_data valve[MAX_VALVE_NUM];
int BSP_Ml307_Init (struct Ml307_Ops *ops, rt_uint8_t version);
int BSP_Ml307_Update (struct Ml307_Ops *ops, rt_uint8_t device_type, rt_uint8_t event_type);
int Ml307_Send_Data (struct Ml307_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 Ml307_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 Ml307_Recv_Data(struct Ml307_Ops *ops, char *data);
static struct DataBody body;
static struct Ml307DataFrame frame;
static struct Ml307RecvData ml307_recv;
struct Ml307_Ops ml307_ops = {
.body = &body,
.frame = &frame,
.recv = &ml307_recv,
.init = BSP_Ml307_Init,
.update_data = BSP_Ml307_Update,
.send = Ml307_Send_Data,
.Resp = Data_Resp,
// .Recv = Ml307_Recv_Data,//,没用到
};
static struct at_device_ml307 _dev = {
ML307_SAMPLE_DEIVCE_NAME,
ML307_SAMPLE_CLIENT_NAME,
ML307_ENABLE_3_8_V,
ML307_PWR_PIN,
ML307_RST_PIN,
ML307_USIM_DECT_PIN,
ML307_SAMPLE_RECV_BUFF_LEN,
};
static rt_uint32_t ml307_event_flags[kMl307MaxEventcnt] = {0};
static rt_bool_t ml307_event_initialized = RT_FALSE; // 是否初始化完成
typedef enum
{
kMl307PriorityLowest, // 4、优先级最低定时心跳、浓度异常、报警触发、报警解除、传感器故障触发 传感器故障解除)
kMl307PriorityMedium, // 2、优先级第三高 自检触发
kMl307PriorityHigh, // 1、优先级第二高 掉电
kMl307PriorityHighest, // 0 优先级最高(设备上电时的定时心跳)
} Ml307Priority;
typedef struct
{
Ml307Event event_flag;
Ml307Priority priority;
const char *event_name;
int (*send_func) (struct at_device *device, void *param);
} Ml307EventInfo;
static void Ml307_Set_Event (Ml307Event event_type)
{
if (event_type < kMl307MaxEventcnt)
{
ml307_event_flags[event_type] = (1 << event_type);
}
}
void Ml307_Event_Init (void)
{
rt_err_t ret = rt_event_init (&at_device_event, "ml307_event", RT_IPC_FLAG_PRIO);
if (ret == RT_EOK)
{
ml307_event_initialized = RT_TRUE;
for (Ml307Event event = kMl307HeartbeatEvent; event < kMl307MaxEventcnt; event++)
{
Ml307_Set_Event (event);
}
}
else
{
LOG_E ("ml307_event init failed!");
}
}
rt_uint32_t Ml307_Get_Event_Flag (Ml307Event event_type)
{
if (event_type < kMl307MaxEventcnt)
{
return ml307_event_flags[event_type];
}
return 0;
}
void Ml307_Send_Event (Ml307Event event_type)
{
ml307_event_index.last_event = ml307_event_index.current_event;
ml307_event_index.current_event = event_type;
ml307_latest_evnet = event_type;
if (ml307_event_initialized == RT_TRUE)
{
if ((ml307_event_index.current_event != kMl307PowerOnEvent) && (ml307_event_index.current_event != kMl307PowerDownEvent))
{
if (power_on_send_flag)
{
rt_event_send (&at_device_event, Ml307_Get_Event_Flag (event_type));
}
}
else
{
rt_event_send (&at_device_event, Ml307_Get_Event_Flag (event_type));
}
}
else
{
LOG_E ("ml307_event_initialized is false");
}
}
// 定义定时器回调函数
static void Ml307_Ht_Timer_Cb (void *parameter)
{
Ml307_Send_Event (kMl307HeartbeatEvent);
}
static void Ml307_Error_Timer_Cb (void *parameter)
{
if (power_on_send_flag) // 上电成功时,停止定时器
{
rt_timer_stop (ml307_error_timer);
}
else
{
Ml307_Send_Event (kMl307PowerOnEvent);
}
}
int _Pack_Send (struct Ml307_Ops *ops, char *buf)
{
char ml307_send_buf[1024] = {0}; // 发送缓冲区,用于存储最终发送的数据
// char byteArr1[512]; // 转换成字节值
unsigned short crc16 = 0; // 存储CRC16校验和
struct at_device *device = at_device_get_by_name (AT_DEVICE_NAMETYPE_NETDEV, ML307_SAMPLE_DEIVCE_NAME);
ASSERT (device);
crc16 = crc1021 (buf, rt_strlen (buf));
LOG_D ("buf: %s", buf);
LOG_D ("crc16: %X", crc16);
// 将数据、校验和及尾部标识添加到发送缓冲区中
if (rt_snprintf (ml307_send_buf, sizeof (ml307_send_buf),
"%s%04X%02X%02X%02X",
buf,
crc16,
ops->frame->tail[0],
ops->frame->tail[1],
ops->frame->tail[2]) >= sizeof (ml307_send_buf))
{
// 发生缓冲区溢出
LOG_E ("Buffer overflow in ml307_send_buf");
return -RT_ERROR;
}
// 打印调试信息
// LOG_D("ml307_send_buf: %s", ml307_send_buf);
rt_uint16_t data_len = rt_strlen (ml307_send_buf);
// 通过AT指令发送数据给ML307模块
if (at_send_data (device, ml307_send_buf, data_len / 2) != RT_EOK)
{
return -RT_ERROR;
}
return RT_EOK;
}
/**
* @brief 发送数据到ml307模块
*
* 本函数根据提供的数据和参数构建一个格式化字符串计算其CRC16校验和
* 然后将该字符串发送给ML307模块
*@param version 协议版本
* @param data 要发送的十六进制数据字符串
* @param len 数据字符串的十六进制数据格式长度
* @param data_num 数据编号
* @param cmd_num 命令编号
* @return int 返回0表示成功非零表示失败
*/
static int _Send_Handle (struct Ml307_Ops *ops, rt_size_t data_num, rt_size_t cmd_num, const char *data)
{
// 临时缓冲区,用于格式化数据
char data_buf[1024] = {0};
rt_size_t data_len = rt_strlen (data);
// 格式化数据构建发送给ML307模块的数据包
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_Ml307_Init (struct Ml307_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 Ml307DataFrame));
ops->frame->header[0] = 0x4A;
ops->frame->header[1] = 0x54;
ops->frame->header[2] = 0x30;
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 _Update_Valve_Data (struct Ml307_Ops *ops)
{
ops->body->valve_num = Flash_Get_Valve_Num();
if (ops->body->valve_num == 0) // 确保至少有一个阀门数据体
{
LOG_D ("No valve data");
rt_memset (&ops->body->valve_data, 0, sizeof (struct valve_t)); // 直接全部发送0
}
else
{
LOG_D ("valve_num: %d", ops->body->valve_num);
rt_memcpy (&ops->body->valve_data[0], &valve[0], sizeof (struct valve_t));
// rt_memset(&valve[0].valve_connct_status, 0, (sizeof(struct valve_t) - 7)); // 清空阀门包数据,等待下次更新,如果没更新说明断开了
}
return RT_EOK;
}
// 更新函数
int BSP_Ml307_Update (struct Ml307_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, &ml307, sizeof (ml307_sys_info)); // 直接赋值结构体数据
ops->body->gas_voltage = Get_Gas_VoltageAdcInt1000x();
ops->body->product_work_temperature = 0x32;
ops->body->work_duration = work_duration;
ops->body->device_status = device_state_flag;
ops->body->valve_num = Flash_Get_Valve_Num();
_Update_Valve_Data (ops);
return RT_EOK;
}
int Ml307_Send_Data (struct Ml307_Ops *ops, rt_uint8_t data_num, rt_uint8_t cmd, rt_uint8_t device_type, rt_uint8_t event_type)
{
rt_size_t lenght = 0;
int ret = 0;
char data_buf[1024] = {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 (ml307_mutex, RT_WAITING_FOREVER);
ret = ops->update_data (ops, device_type, event_type);
if (ret == RT_EOK)
{
if (ops->body->valve_num == 0)
{
lenght = (sizeof (struct DataBody) - (MAX_VALVE_NUM - 1) * sizeof (struct valve_t)); // 至少要发送一个阀门数据体
}
else
{
lenght = (sizeof (struct DataBody) - (MAX_VALVE_NUM - ops->body->valve_num) * sizeof (struct valve_t)); // 至少要发送一个阀门数据体
}
for (int i = 0; i < lenght; 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 (ml307_mutex);
return ret;
}
int Data_Resp (struct Ml307_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 (ml307_conncet_tcp_flag != 1)
{
LOG_E ("ml307_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);
}
#if 0
int Ml307_Recv_Data(struct Ml307_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;
}
#endif
/***************************************发送处理函数************************************************ */
/**
* 处理定时心跳事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Heartbeat (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
int ret = 0;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 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 ("ml307 get signal failed\n");
return -RT_ERROR;
}
ret = ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_DATA_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_HEARTBEAT);
if (ret != RT_EOK)
{
LOG_E ("ml307 send data failed\n");
return ret;
}
return RT_EOK;
}
/**
* 处理时间校准事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Time_Calibration (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_TIME_CALIBRATION, DEVICE_TYPE_ML307, EVENT_TYPE_TIME_CALIBRATION))
{
LOG_E ("ml307 send cmd[%X] failed\n", CMD_TYPE_TIME_CALIBRATION);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理报警事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Alarm (struct at_device *device, void *param)
{
rt_err_t ret = RT_EOK;
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_ALARM))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_ALARM);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理报警恢复事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Alarm_Recover (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_ALARM_RECOVER))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_ALARM_RECOVER);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理故障事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Fault (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAULT))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAULT);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理故障恢复事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Fault_Recover (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAULT_RECOVER))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAULT_RECOVER);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理自检事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Self_Check (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_SELF_CHECK))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_SELF_CHECK);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理消音事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Silence (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_SILENCE))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_SILENCE);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理异常事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Exception (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_EXCEPTION))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_EXCEPTION);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理电磁阀状态改变事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Valve_Status (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_STATUS))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_STATUS);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理风扇状态改变事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Fan_Status (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_FAN_STATUS))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_FAN_STATUS);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理温度异常事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Temp_Anomaly (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_TEMP_ANOMALY))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_TEMP_ANOMALY);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理上电事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Power_On (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_POWER_ON))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_POWER_ON);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理断电事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Power_Off (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
rt_memset (&valve[0].valve_connct_status, 0, (sizeof (struct valve_t) - 7)); // 当掉电事件时,直接清空阀门结构体,这样连接状态就为断开
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_POWER_OFF))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_POWER_OFF);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理阀门连接事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Valve_Connect (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_CONNECT))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_CONNECT);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理阀门断开事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Valve_Disconnect (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_VALVE_DISCONNECT))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_VALVE_DISCONNECT);
return -RT_ERROR;
}
return RT_EOK;
}
/**
* 处理设备故障事件
* @param device 设备结构体指针
* @param param 操作结构体指针
* @return 操作结果
*/
int Ml307_Send_Device_Failure (struct at_device *device, void *param)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
if ((device == RT_NULL) || (ml307_ops == RT_NULL))
{
LOG_E ("ml307 param error\n");
return RT_ERROR;
}
rt_err_t ret = RT_EOK;
ret = device->class->device_ops->control (device, AT_DEVICE_CTRL_GET_SIGNAL, RT_NULL);
if (ret != RT_EOK)
{
LOG_E ("ml307 get signal failed\n");
return -RT_ERROR;
}
if (ml307_ops->send (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_DEVICE_EVENT_REPORT, DEVICE_TYPE_ML307, EVENT_TYPE_DEVICE_FAILURE))
{
LOG_E ("ml307 send cmd[%X] failed\n", EVENT_TYPE_DEVICE_FAILURE);
return -RT_ERROR;
}
return RT_EOK;
}
/*这个【4、优先级最低当同时触发后相同服务直接合并】暂时还没想好怎么做
思路感觉就是得重新开一个线程,然后再开一个任务队列,将所有的事件,发送到任务队列
在线程中,对任务队列进行查看并处理,看目前都有哪些事件,是处于那个优先级得,如果是最低优先级,就只发送一帧数据就行了,
如果是不同优先级,按照优先级顺序发送事件,但感觉这样会使得程序更复杂,本来发送就很快,感觉没必要这样搞*/
const Ml307EventInfo ml307_event_info[] = {
{kMl307PowerOnEvent, kMl307PriorityHighest, "上电心跳事件", Ml307_Send_Power_On },
{kMl307PowerDownEvent, kMl307PriorityHigh, "掉电事件", Ml307_Send_Power_Off },
{kMl307ValveConnectEvent, kMl307PriorityMedium, "阀门连接事件", Ml307_Send_Valve_Connect },
{KMl307ValveDisconnectEvent, kMl307PriorityMedium, "阀门断开事件", Ml307_Send_Valve_Disconnect},
{kMl307SelfCheckEvent, kMl307PriorityMedium, "自检事件", Ml307_Send_Self_Check },
{kMl307HeartbeatEvent, kMl307PriorityLowest, "定时心跳事件", Ml307_Send_Heartbeat },
{kMl307TempAnomalyEvent, kMl307PriorityLowest, "温度异常事件", Ml307_Send_Temp_Anomaly },
{kMl307AlarmEvent, kMl307PriorityLowest, "报警触发事件", Ml307_Send_Alarm },
{kMl307AlarmRcyEvent, kMl307PriorityLowest, "报警解除事件", Ml307_Send_Alarm_Recover },
{kMl307FaultEvent, kMl307PriorityLowest, "传感器故障事件", Ml307_Send_Fault },
{kMl307FaultRcyEvent, kMl307PriorityLowest, "传感器故障解除事件", Ml307_Send_Fault_Recover },
{kMl307TimeCalibrationEvent, kMl307PriorityLowest, "时间校准事件", Ml307_Send_Time_Calibration},
{kMl307SilenceEvent, kMl307PriorityLowest, "消音事件", Ml307_Send_Silence },
// {kMl307ExceptionEvent, kMl307PriorityLowest, "异常事件", Ml307_Send_Exception},
{kMl307ValveStatusEvent, kMl307PriorityLowest, "电磁阀状态改变事件", Ml307_Send_Valve_Status },
{kMl307FanStatusEvent, kMl307PriorityLowest, "风机状态改变事件", Ml307_Send_Fan_Status },
{kMl307DeviceFailureEvent, kMl307PriorityLowest, "设备失效事件", Ml307_Send_Device_Failure }
};
Ml307Priority Get_Event_Priority (Ml307Event event_type)
{
for (size_t i = 0; i < sizeof (ml307_event_info) / sizeof (ml307_event_info[0]); i++)
{
if (ml307_event_info[i].event_flag == event_type)
{
return ml307_event_info[i].priority;
}
}
return kMl307PriorityLowest;
}
/**
* 处理ML307设备的事件
* @param ml307_recv_event 接收到的ML307事件标志
* @return
*/
int Ml307_Process_Events (Ml307Event ml307_recv_event, struct at_device *device, void *param)
{
rt_uint8_t cnt = 0;
rt_err_t ret = RT_EOK;
rt_uint8_t max_retry_count = (rt_uint8_t)Flash_Get_SysCfg (kIotRetryId);
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)param;
const Ml307EventInfo *event = RT_NULL;
for (size_t i = 0; i < sizeof (ml307_event_info) / sizeof (Ml307EventInfo); ++i)
{
// 检查当前事件是否在接收到的事件标志中
if (ml307_recv_event == ml307_event_info[i].event_flag)
{
event = &ml307_event_info[i];
break;
}
}
if (event) // 处理该事件
{
// 打印事件的名称
ml307_current_evnet = event->event_flag;
for (size_t i = 0; i < max_retry_count; i++)
{
if (ml307_conncet_tcp_flag)
{
if (event->send_func)
{
#ifdef TEST_ENABLE
RTC_ShowTime(); // 每次发送打印下时间,容易定位问题
#endif
LOG_D ("%s上报, cnt :%d", event->event_name, cnt);
int result = event->send_func (device, ml307_ops);
if (result != RT_EOK)
{
LOG_E ("ml307 send failed\n");
ret = RT_ERROR;
continue;
}
else
{
if (rt_sem_take (ml307_recv_msg_sem, 8000) == RT_EOK)
{
LOG_D ("收到回复\n");
ml307_connect_sever_flag = 1;
ret = RT_EOK; // 函数执行完毕返回0
break;
}
else
{
// 收不到说明在平台未注册或者信号不行,此时ml307_connect_sever_flag 为0但ml307_conncet_tcp_flag = 1此时不发起重连等待事件触发就行
ret = RT_ERROR;
rt_thread_mdelay (IMEI_Delay());
}
}
}
}
else
{
ret = RT_ERROR;
}
if (event->priority < Get_Event_Priority (ml307_latest_evnet)) // 查看当前事件和新传入的事件的优先级哪个高,如果有高的直接退出处理高优先级的
{
LOG_W ("有更高优先级的事件进入,退出当前处理\n");
ret = RT_EOK;
break;
}
}
}
if (rt_strcmp (event->event_name, "掉电事件") == RT_EOK)
{
LOG_D ("掉电处理TCP");
if (device->class->device_ops->control (device, AT_DEVICE_CTRL_NET_DISCONN, RT_NULL) == RT_EOK)
{
LOG_D ("关闭TCP");
}
rt_pin_write (_dev.pwr_en_pin, PIN_LOW); // 断开3_8v供电
LOG_D ("关闭模组");
ml307_power_down_flag = 1;
ret = RT_EOK;
}
else
{
if (ret != RT_EOK)
{
ml307_connect_sever_flag = 0;
if (!ml307_disconnect_retry_flag)
{
LOG_D("与服务器断开,重连网络中");
rt_sem_release (ml307_disconnect_sem);
}
else
{
LOG_D ("与服务区断开连接,等待连接中......\n");
}
}
}
return ret;
}
// 比较帧头和帧尾
int Compare_HeaderToTail (struct Ml307_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 Ml307_Ops *ops)
{
if ((ops->recv->recv_data.event_type >= EVENT_TYPE_HEARTBEAT) &&
(ops->recv->recv_data.event_type <= INSTRUCTION_DOWN_VALVE_REMOVE))
{
LOG_D ("服务器响应成功,响应码:[%02X]\n", ops->recv->recv_data.event_type);
rt_sem_release (ml307_recv_msg_sem);
}
else
{
LOG_E ("服务器响应失败,响应码:[%02X]\n", ops->recv->recv_data.event_type);
}
}
void Handle_Self_Check (struct Ml307_Ops *ops)
{
LOG_D ("服务器下发自检指令\n");
char imei[16] = {0};
Get_IotImei (imei, FLASH_IOT_IMEI_LEN);
LOG_D ("imei:%s\n", imei);
_Self_Check_Mode();
rt_thread_mdelay (100);
char temp[32] = "0";
String2Hex (temp, imei); // 将字符串转为十六进制字符串
LOG_D ("temp: %s", temp);
Send_Laser_Alarm_Event (kSelfCheckEvent);
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_SELF_CHECK, temp, RESPONSE_CODE_SUCCESS);
Send_Laser_Alarm_Event (kNormalDetectionEvents); // 先返回正常状态,然后跳转到所处的状态
}
void Handle_Mute (struct Ml307_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_ML307, INSTRUCTION_DOWN_MUTE, temp, RESPONSE_CODE_SUCCESS);
}
/*关阀 52-阀门编号1byte+ MAC地址6byte+ 补零字节 = 15byte 如果内容全部为0则默认为关闭有线阀门*/
rt_err_t Handle_Close_Valve (struct Ml307_Ops *ops)
{
LOG_D ("服务器下发关闭阀门指令\n");
int i = 0;
rt_uint8_t data[FLASH_VALVE_MAC_ADDR_LEN + 1] = {0};
rt_uint8_t mac_addr[6] = {0};
char imei[16] = {0};
Get_IotImei (imei, FLASH_IOT_IMEI_LEN);
char temp[32] = "0";
String2Hex (temp, imei); // 将字符串转为十六进制字符串
rt_memcpy (data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
LOG_D ("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
if ((data[0] > 0) && (data[0] < MAX_VALVE_NUM)) // 不为零则说明关闭无线阀门
{
rt_uint8_t cnt = Flash_Get_Valve_Num();
if (cnt == 0)
{
LOG_E ("没有设置无线阀门\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
LOG_D ("无线阀门编号:%d\n", data[0]);
if (Flash_Get_Mac_Addr (mac_addr, data[0]) != RT_EOK)
{
LOG_E ("获取无线阀门mac地址失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
LOG_D ("mac_addr[0] = %x mac_addr[1] = %x mac_addr[2] = %x mac_addr[3] = %x mac_addr[4] = %x, mac_addr[5] = %x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
/*对两个数组进行比较,如果值不同则退出*/
for (; i < FLASH_VALVE_MAC_ADDR_LEN; i++)
{
if (mac_addr[i] != data[i + 1])
{
LOG_E ("mac_addr[%d][%x]!= data[%d][%x]\n", i, mac_addr[i], i + 1, data[i + 1]);
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
}
if (i == FLASH_VALVE_MAC_ADDR_LEN)
{
LOG_D ("mac地址匹配成功,执行关阀动作\n");
if (Bt_Valve_Handler (kValveCmdCtr, data[0], &data[1]) != RT_EOK)
{
LOG_E ("关阀失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
if (rt_sem_take (&bt_ctr_sem, 10000) != RT_EOK) // 等待十秒获取信号量
{
LOG_E ("获取信号量失败\n");
rt_sem_control (&bt_ctr_sem, RT_IPC_CMD_RESET, 0);
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
LOG_D ("关阀成功\n");
rt_sem_control (&bt_ctr_sem, RT_IPC_CMD_RESET, 0);
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_SUCCESS);
return RT_EOK;
}
}
else
{
LOG_E ("mac地址匹配失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_ACTION_FAILURE);
}
}
}
else
{
LOG_D ("关闭有线阀门\n");
// TODO:此处需要增加关阀有线阀门的逻辑
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_CLOSE_VALVE, temp, RESPONSE_CODE_SUCCESS);
return RT_EOK;
}
}
void Handle_Open_Valve (struct Ml307_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_ML307, INSTRUCTION_DOWN_OPEN_VALVE, temp, RESPONSE_CODE_SUCCESS);
}
void Handle_Open_Relay (struct Ml307_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_ML307, INSTRUCTION_DOWN_OPEN_RELAY, temp, RESPONSE_CODE_SUCCESS);
}
void Handle_Close_Relay (struct Ml307_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_ML307, INSTRUCTION_DOWN_CLOSE_RELAY, temp, RESPONSE_CODE_SUCCESS);
}
void Handle_Query_Params (struct Ml307_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_ML307, INSTRUCTION_DOWN_QUERY_PARAMS, str, RESPONSE_CODE_SUCCESS);
}
int Handle_Config_Params (struct Ml307_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_ML307, 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_uint16_t iot_upload_time = (uint16_t)Flash_Get_SysCfg (kIotUploadCycleId);
unsigned long timeout = iot_upload_time * 60 * RT_TICK_PER_SECOND;
rt_timer_control (ml307_timer, RT_TIMER_CTRL_SET_TIME, (void *)&timeout); // 更新上报周期
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_ML307, 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_ML307, 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_ML307, INSTRUCTION_DOWN_CONFIG_PARAMS, temp, RESPONSE_CODE_SUCCESS) == RT_EOK)
{
LOG_D ("配置参数没有变化\n");
}
return RT_EOK;
}
void Handle_Time_Calibration_Data (struct Ml307_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_ML307, INSTRUCTION_DOWN_TIME_CALIBRATION, temp, RESPONSE_CODE_SUCCESS);
}
// 下发修改服务器地址指令
void Handle_Sever_Addr_Set (struct Ml307_Ops *ops)
{
flash_sever_info sever_info = {0};
rt_uint8_t data[6] = {0};
char imei[16] = {0};
char temp[32] = "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);
if (Flash_Get_Sever_Data (&sever_info) == RESET)
{
LOG_E ("服务器地址修改失败\n");
}
else
{
LOG_D ("服务器地址修改成功\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_SEVER_ADDR, temp, RESPONSE_CODE_SUCCESS);
}
}
/*新增阀门设备*/
rt_err_t Handle_Valve_Add (struct Ml307_Ops *ops)
{
LOG_D ("服务器下发注册阀门指令\n");
rt_uint8_t data[7] = {0};
char imei[16] = {0};
char temp[32] = "0";
rt_uint8_t cnt = Flash_Get_Valve_Num();
Get_IotImei (imei, FLASH_IOT_IMEI_LEN);
String2Hex (temp, imei); // 将字符串转为十六进制字符串
if (cnt >= 1)
{
LOG_E ("阀门设备数量超过最大值\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
// 无阀门数据时添加,有阀门数据时不添加
if (cnt >= 0 && cnt < MAX_VALVE_NUM)
{
rt_memcpy (data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
if (data[0] > 1)
{
LOG_E ("阀门设备数量超过最大值[1]\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_OTHER_ERROR);
return RT_ERROR;
}
LOG_D ("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
valve[data[0] - 1].valve_id = data[0]; // 更新阀门ID
rt_memcpy (valve[data[0] - 1].valve_mac, &data[1], FLASH_VALVE_MAC_ADDR_LEN); // 更新MAC地址
if (Bt_Valve_Handler (kValveCmdReg, data[0], &data[1]) != RT_EOK) // 更新蓝牙端mac地址
{
LOG_E ("新增阀门设备失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
if (rt_sem_take (&bt_reg_sem, 10000) != RT_EOK) // 等待十秒获取信号量
{
LOG_E ("获取信号量失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
if (Flash_Set_Mac_Addr (&data[1], data[0]) == RESET)
{
LOG_E ("阀门设备写入FLash失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
LOG_D ("新增阀门设备成功\n");
Flash_Set_Valve_Num (cnt + 1);
if (ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_SUCCESS) != RT_EOK)
{
LOG_D ("发送失败,清空本地mac地址");
rt_uint8_t mac_addr[6] = {0};
// 清空本地阀门信息
if (Flash_Set_Mac_Addr (mac_addr, 1) != RESET)
{
LOG_E ("本地阀门信息清空完成");
Flash_Set_Valve_Num (0);
}
Bt_Valve_Handler (kValveCmdRemAll, RT_NULL, RT_NULL);
if (rt_sem_take (&bt_rem_sem, 10000) == RT_EOK) // 如果没刷掉数据,则黄灯会亮一秒,如果刷成功了,则红灯闪一下黄灯不会亮
{
return RT_EOK;
}
}
}
return RT_EOK;
}
}
/*更换阀门设备*/
rt_err_t Handle_Valve_Replace (struct Ml307_Ops *ops)
{
size_t i = 0;
rt_uint8_t data[13] = {0};
rt_uint8_t mac_addr[FLASH_VALVE_MAC_ADDR_LEN] = {0};
char imei[16] = {0};
char temp[32] = "0";
LOG_I ("服务器下发更换阀门设备");
Get_IotImei (imei, FLASH_IOT_IMEI_LEN);
String2Hex (temp, imei); // 将字符串转为十六进制字符串
rt_memcpy (data, (ops->recv->recv_data.res_data + 2), (2 * FLASH_VALVE_MAC_ADDR_LEN + 1));
LOG_HEX ("data", 16, data, sizeof (data));
/*设备编号1byte+ 新MAC地址6+ 旧阀门MAC地址6 + 补零字节= 15byte*/
if (Flash_Get_Mac_Addr (mac_addr, data[0]) == RT_EOK)
{
for (; i < FLASH_VALVE_MAC_ADDR_LEN; i++)
{
if (mac_addr[i] != data[i + 7])
{
LOG_E ("旧阀门地址错误\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_OTHER_ERROR);
return RT_ERROR;
}
}
LOG_D ("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x data[6] = %x data[7] = %x data[8] = %x data[9] = %x data[10] = %x data[11] = %x data[12] = %x",
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12]);
if (i == FLASH_VALVE_MAC_ADDR_LEN)
{
if (Bt_Valve_Handler (kValveCmdRep, data[0], &data[1]) != RT_EOK)
{
LOG_E ("更换阀门设备失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
if (rt_sem_take (&bt_rep_sem, 10000) != RT_EOK) // 等待十秒获取信号量
{
LOG_E ("获取更换阀门信号量失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_ADD, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
if (Flash_Set_Mac_Addr (&data[1], data[0]) == RESET)
{
LOG_E ("更换阀门设备失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
LOG_D ("更换阀门设备成功\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_SUCCESS);
return RT_EOK;
}
}
else
{
LOG_E ("旧阀门MAC地址错误\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_OTHER_ERROR);
return RT_ERROR;
}
}
else
{
LOG_E ("该阀门设备错误\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REPLACE, temp, RESPONSE_CODE_PARSE_FAIL);
}
return RT_EOK;
}
/*移除阀门设备*/
rt_err_t Handle_Remove_Valve (struct Ml307_Ops *ops)
{
rt_uint8_t data[8] = {0};
char imei[16] = {0};
char temp[32] = "0";
rt_uint8_t cnt = Flash_Get_Valve_Num();
Get_IotImei (imei, FLASH_IOT_IMEI_LEN);
String2Hex (temp, imei); // 将字符串转为十六进制字符串
LOG_I ("接收到服务器下发移除阀门指令");
#if 1
if (cnt == 0)
{
LOG_W ("阀门设备数量为0\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_SUCCESS); // 如果本地无阀门信息,直接返回成功
return RT_EOK;
}
rt_memcpy (data, (ops->recv->recv_data.res_data + 8), FLASH_VALVE_MAC_ADDR_LEN + 1);
LOG_D ("data[0] = %x data[1] = %x data[2] = %x data[3] = %x data[4] = %x, data[5] = %x", data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
if (Bt_Valve_Handler (kValveCmdRem, data[0], &data[1]) != RT_EOK)
{
LOG_E ("移除阀门设备失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
if (rt_sem_take (&bt_rem_sem, 10000) != RT_EOK) // 等待十秒获取信号量
{
LOG_E ("获取移除阀门信号量失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
rt_memset (&data[1], 0, 6);
if (Flash_Set_Mac_Addr (&data[1], data[0]) == RESET)
{
LOG_E ("移除阀门设备失败\n");
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_ACTION_FAILURE);
return RT_ERROR;
}
else
{
LOG_D ("移除阀门设备成功\n");
Flash_Set_Valve_Num (cnt - 1);
ops->Resp (ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, INSTRUCTION_DOWN_VALVE_REMOVE, temp, RESPONSE_CODE_SUCCESS);
return RT_EOK;
}
}
#endif
}
void Handle_Error (struct Ml307_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_ML307, ops->recv->cmd, temp, RESPONSE_CODE_PARSE_FAIL);
}
void Handle_Instruction_Down (struct Ml307_Ops *ops)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)ops;
switch (ml307_ops->recv->recv_data.event_type)
{
case INSTRUCTION_DOWN_SELF_CHECK:
Handle_Self_Check (ml307_ops);
break;
case INSTRUCTION_DOWN_MUTE:
Handle_Mute (ml307_ops);
break;
case INSTRUCTION_DOWN_CLOSE_VALVE:
Handle_Close_Valve (ml307_ops);
break;
case INSTRUCTION_DOWN_OPEN_VALVE:
Handle_Open_Valve (ml307_ops);
break;
case INSTRUCTION_DOWN_OPEN_RELAY:
Handle_Open_Relay (ml307_ops);
break;
case INSTRUCTION_DOWN_CLOSE_RELAY:
Handle_Close_Relay (ml307_ops);
break;
case INSTRUCTION_DOWN_QUERY_PARAMS:
Handle_Query_Params (ml307_ops);
break;
case INSTRUCTION_DOWN_CONFIG_PARAMS:
Handle_Config_Params (ml307_ops);
break;
case INSTRUCTION_DOWN_TIME_CALIBRATION:
Handle_Time_Calibration_Data (ml307_ops);
break;
case INSTRUCTION_DOWN_SEVER_ADDR:
Handle_Sever_Addr_Set (ml307_ops);
break;
case INSTRUCTION_DOWN_VALVE_ADD:
Handle_Valve_Add (ml307_ops);
break;
case INSTRUCTION_DOWN_VALVE_REPLACE:
Handle_Valve_Replace (ml307_ops);
break;
case INSTRUCTION_DOWN_VALVE_REMOVE:
Handle_Remove_Valve (ml307_ops);
break;
}
}
void Handle_Time_Calibration (struct Ml307_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_ML307, INSTRUCTION_DOWN_TIME_CALIBRATION, ML307_DEFIENE_DATA, RESPONSE_CODE_SUCCESS);
}
void Handle_Cmd_Type (struct Ml307_Ops *ops)
{
struct Ml307_Ops *ml307_ops = (struct Ml307_Ops *)ops;
switch (ml307_ops->recv->cmd)
{
case CMD_TYPE_SERVER_REPLY:
Handle_Server_Reply (ml307_ops);
break;
case CMD_TYPE_INSTRUCTION_DOWN:
Handle_Instruction_Down (ml307_ops);
break;
case CMD_TYPE_TIME_CALIBRATION:
Handle_Time_Calibration (ml307_ops);
break;
default:
ml307_ops->Resp (ml307_ops, DATA_SERIAL_NUM, CMD_TYPE_INSTRUCTION_REPLY, DEVICE_TYPE_ML307, ops->recv->cmd, ML307_DEFIENE_DATA, RESPONSE_CODE_PARSE_FAIL);
break;
}
}
void Analyze_Recv_Frame (struct at_device *device, struct Ml307_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 Ml307_Send_Thread_Entry (void *param)
{
rt_err_t result = RT_EOK;
rt_uint32_t ml307_recv_event;
LOG_D ("ml307 thread entry\n");
struct Ml307_Ops *ops = (struct Ml307_Ops *)param;
struct at_device_ml307 *ml307 = &_dev;
struct at_device *device = at_device_get_by_name (AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
RT_ASSERT (device);
if (ops->init (ops, PROTOCOL_VERSION) != RT_EOK)
{
LOG_E ("ml307 init failed\n");
}
else
{
LOG_D ("ml307 init success\n");
rt_completion_wait (&ml307_init_complate, RT_WAITING_FOREVER); // wait for ml307 init finish
Ml307_Send_Event (kMl307PowerOnEvent);
}
while (1)
{
result = rt_event_recv (&at_device_event,
Ml307_Get_Event_Flag (kMl307PowerOnEvent) |
Ml307_Get_Event_Flag (kMl307HeartbeatEvent) |
Ml307_Get_Event_Flag (kMl307SelfCheckEvent) |
Ml307_Get_Event_Flag (kMl307SilenceEvent) |
Ml307_Get_Event_Flag (kMl307ExceptionEvent) |
Ml307_Get_Event_Flag (kMl307ValveStatusEvent) |
Ml307_Get_Event_Flag (kMl307FanStatusEvent) |
Ml307_Get_Event_Flag (kMl307TempAnomalyEvent) |
Ml307_Get_Event_Flag (kMl307PowerOnEvent) |
Ml307_Get_Event_Flag (kMl307PowerDownEvent) |
Ml307_Get_Event_Flag (kMl307AlarmEvent) |
Ml307_Get_Event_Flag (kMl307AlarmRcyEvent) |
Ml307_Get_Event_Flag (kMl307FaultEvent) |
Ml307_Get_Event_Flag (kMl307FaultRcyEvent) |
Ml307_Get_Event_Flag (kMl307DeviceFailureEvent) |
Ml307_Get_Event_Flag (kMl307TimeCalibrationEvent) |
Ml307_Get_Event_Flag (kMl307ValveConnectEvent) |
Ml307_Get_Event_Flag (KMl307ValveDisconnectEvent),
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
RT_WAITING_FOREVER, &ml307_recv_event); // 这个事件一般是设备端发生了变化,发送到服务器时调用
if (result == RT_EOK)
{
if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307PowerOnEvent))
{
result = Ml307_Process_Events (kMl307PowerOnEvent, device, ops); // 当上电心跳包发送不成功时,其他事件不启动
if (result)
{
power_on_send_flag = 0;
rt_timer_start (ml307_error_timer); // 启动重连定时器, 3min一次直到发送成功
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
else
{
power_on_send_flag = 1;
rt_timer_start (ml307_timer); // 当上电心跳包发送成功时, 开始心跳包周期发送
rt_timer_start (ml307_upload_timer); // 周期修改时间更新
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307PowerDownEvent))
{
result = Ml307_Process_Events (kMl307PowerDownEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
ml307_event_initialized = RT_FALSE; // 当接收到掉电事件时,不再接收其他事件
}
if (power_on_send_flag)
{
if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307HeartbeatEvent))
{
result = Ml307_Process_Events (kMl307HeartbeatEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307ValveConnectEvent))
{
result = Ml307_Process_Events (kMl307ValveConnectEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (KMl307ValveDisconnectEvent))
{
result = Ml307_Process_Events (KMl307ValveDisconnectEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307TimeCalibrationEvent))
{
Time_Calibration (device);
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307AlarmEvent))
{
result = Ml307_Process_Events (kMl307AlarmEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307AlarmRcyEvent))
{
result = Ml307_Process_Events (kMl307AlarmRcyEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307FaultEvent))
{
if (device_state_flag != 1) // 当设备失效时,只上报失效信息
{
result = Ml307_Process_Events (kMl307FaultEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307FaultRcyEvent))
{
result = Ml307_Process_Events (kMl307FaultRcyEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307SelfCheckEvent))
{
result = Ml307_Process_Events (kMl307SelfCheckEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307SilenceEvent))
{
result = Ml307_Process_Events (kMl307SilenceEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307ExceptionEvent))
{
result = Ml307_Process_Events (kMl307ExceptionEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307ValveStatusEvent))
{
result = Ml307_Process_Events (kMl307ValveStatusEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307FanStatusEvent))
{
result = Ml307_Process_Events (kMl307FanStatusEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307TempAnomalyEvent))
{
result = Ml307_Process_Events (kMl307TempAnomalyEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
else if (ml307_recv_event & Ml307_Get_Event_Flag (kMl307DeviceFailureEvent))
{
result = Ml307_Process_Events (kMl307DeviceFailureEvent, device, ops);
if (result)
{
LOG_E ("ml307 send data failed result = [%d]\n", result);
}
}
}
}
}
}
static void Ml307_Recv_Thread_Entry (void *parameter)
{
struct Ml307_Ops *ops = (struct Ml307_Ops *)parameter;
struct at_device_ml307 *ml307 = &_dev;
struct at_device *device = at_device_get_by_name (AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
RT_ASSERT (device);
LOG_D ("ml307 recv thread entry\n");
while (1)
{
if (rt_sem_take (ml307_recv_sem, RT_WAITING_FOREVER) == RT_EOK)
{
Analyze_Recv_Frame (device, ops);
}
}
}
static void Ml307_Life_Thread_Entry (void *parameter)
{
struct at_device_ml307 *ml307 = &_dev;
struct at_device *device = at_device_get_by_name (AT_DEVICE_NAMETYPE_NETDEV, ml307->device_name);
RT_ASSERT (device);
rt_err_t result = RT_ETIMEOUT;
rt_uint32_t delay_n = 0;
at_response_t resp = RT_NULL;
rt_uint32_t retry_delay = 8000;
LOG_D ("ml307_life_thread entry\n");
while (1)
{
result = rt_sem_take (ml307_disconnect_sem, RT_WAITING_FOREVER);
if (result == RT_EOK)
{
if (!ml307_conncet_tcp_flag)
{
LOG_D ("重连网络中...\n");
ml307_connect_sever_flag = 0;
resp = at_create_resp (256, 0, 5000);
if (resp == RT_NULL)
{
LOG_E ("No memory for response structure!");
at_delete_resp (resp);
result = -RT_ETIMEOUT;
goto __exit;
}
if (device->class->device_ops->control (device, AT_DEVICE_CTRL_NET_DISCONN, RT_NULL) == RT_EOK)
{
rt_thread_mdelay (RT_TICK_PER_SECOND); // 这里如果有TCP连接先关掉TCP,没有返回错误无所谓
}
if (device->class->device_ops->control (device, AT_DEVICE_CTRL_POWER_OFF, RT_NULL) == RT_EOK)
{
rt_thread_mdelay (RT_TICK_PER_SECOND);
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 (RT_TICK_PER_SECOND / 2);
/* disable echo */
LOG_D ("AT");
if (at_client_obj_wait_connect (device->client, 10000) != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/* disable echo */
LOG_D ("ATE0");
if (at_obj_exec_cmd (device->client, resp, "ATE0") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*disable sleep mode */
if (at_obj_exec_cmd (device->client, resp, "AT+MLPMCFG=\"sleepmode\",0,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*设置包模式*/
if (at_obj_exec_cmd (device->client, resp, "AT+MIPCFG=\"encoding\",0,1,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*设置包模式*/
if (at_obj_exec_cmd (device->client, resp, "AT+MIPCFG=\"autofree\",0,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
/*设置心跳包*/
if (at_obj_exec_cmd (device->client, resp, "AT+MIPTKA=0,1,120,60,3") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
rt_uint8_t i = 0;
/* check SIM card */
for (i = 0; i < 60; i++)
{
if (at_obj_exec_cmd (device->client, resp, "AT+CPIN?") == RT_EOK)
{
char code[8] = {0};
if (at_resp_parse_line_args_by_kw (resp, "+CPIN:", "+CPIN: %s", code) > 0)
{
if (rt_strcmp (code, "READY") == 0)
{
LOG_D ("%s device SIM card detection success.", device->name);
break;
}
else
{
LOG_E ("%s device SIM card detection failed.", device->name);
result = -RT_ERROR;
goto __exit;
}
}
}
rt_thread_mdelay (3000);
}
if (i == 60)
{
LOG_E ("%s device SIM card detection failed.", device->name);
result = -RT_ERROR;
goto __exit;
}
/* Define PDP Context */
for (i = 0; i < 5; i++)
{
if (at_obj_exec_cmd (device->client, resp, "AT+CGDCONT=1,\"IPV4V6\",\"cmnet\"") == RT_EOK)
{
LOG_D ("%s device Define PDP Context Success.", device->name);
break;
}
rt_thread_mdelay (1000);
}
if (i == 5)
{
LOG_E ("%s device Define PDP Context failed.", device->name);
result = -RT_ERROR;
goto __exit;
}
/* check the GPRS network is registered */
for (i = 0; i < 60; i++)
{
if (at_obj_exec_cmd (device->client, resp, "AT+CEREG?") == RT_EOK)
{
int link_stat = 0;
if (at_resp_parse_line_args_by_kw (resp, "+CEREG:", "+CEREG: %*d,%d", &link_stat) > 0)
{
if ((link_stat == 1) || (link_stat == 5))
{
LOG_D ("%s device GPRS is registered", device->name);
break;
}
}
}
rt_thread_mdelay (1000);
}
if (i == 60)
{
LOG_E ("%s device GPRS is register failed", device->name);
result = -RT_ERROR;
goto __exit;
}
if (at_obj_exec_cmd (device->client, resp, "AT+MIPCALL=1,1") != RT_EOK)
{
result = -RT_ERROR;
goto __exit;
}
#if defined(AT_DEBUG)
/* check the GPRS network IP address */
for (i = 0; i < 10; i++)
{
if (at_obj_exec_cmd (device->client, resp, "AT+MIPCALL?") == RT_EOK)
{
#define IP_ADDR_SIZE_MAX 16
char ipaddr_str[8 * IP_ADDR_SIZE_MAX] = {0};
char ipaddr_v4[IP_ADDR_SIZE_MAX] = {0};
char ipaddr_v6[4 * IP_ADDR_SIZE_MAX] = {0};
/* parse response data "+CGPADDR: 1,<IP_address>" */
if (at_resp_parse_line_args_by_kw (resp, "+MIPCALL:", "+MIPCALL: %*d,%*d,%s", ipaddr_str) > 0)
{
const char *ipaddr_v4_str = rt_strstr (ipaddr_str, "\"");
sscanf (ipaddr_v4_str, "\"%[^\"]", ipaddr_v4);
const char *ipaddr_v6_str = rt_strstr (ipaddr_str, "\",\"");
sscanf (ipaddr_v6_str, "\",\"%[^\"]", ipaddr_v6);
LOG_D ("%s device IP address: %s - %s", device->name, ipaddr_v4, ipaddr_v6);
break;
}
}
rt_thread_mdelay (2000);
}
if (i == 10)
{
LOG_E ("%s device GPRS is get IP address failed", device->name);
result = -RT_ERROR;
goto __exit;
}
#endif
if (device->class->device_ops->control (device, AT_DEVICE_CTRL_NET_CONN, RT_NULL) == RT_EOK)
{
LOG_D ("重连网络成功\n");
ml307_conncet_tcp_flag = 1;
delay_n = 0;
ml307_disconnect_retry_flag = 0;
at_delete_resp (resp);
retry_delay = 8000; // 重置重连延迟时间
rt_thread_mdelay (100);
Ml307_Send_Event (kMl307HeartbeatEvent);
}
else
{
result = -RT_ETIMEOUT;
goto __exit;
}
}
else
{
result = -RT_ETIMEOUT;
goto __exit;
}
}
else
{
result = -RT_ETIMEOUT;
goto __exit;
}
}
else
{
ml307_disconnect_retry_flag = 0;
Ml307_Send_Event (kMl307HeartbeatEvent);
}
}
else
{
delay_n = 0;
result = -RT_ETIMEOUT;
goto __exit;
}
__exit:
if (result != RT_EOK)
{
if (resp != RT_NULL)
{
at_delete_resp (resp);
}
ml307_disconnect_retry_flag = 1;
LOG_D ("联网错误,等待%dms后重连", retry_delay);
rt_thread_mdelay (retry_delay);
retry_delay = MIN (retry_delay * 2, 1800000); // 最大延迟30min
delay_n++;
if (delay_n >= 21) // 连续重连大于1小时都不行则重启设备
{
Flash_Set_WorkDuration (work_duration);
rt_thread_mdelay (100);
reboot();
}
ml307_conncet_tcp_flag = 0;
rt_sem_release (ml307_disconnect_sem);
}
}
}
static void Ml307_Upload_Timer_Cb (void *parameter)
{
Ml307_Send_Event (kMl307TimeCalibrationEvent); // 更新下时间
}
int BSP_Ml307_Thread_Init (void)
{
rt_err_t ret;
Ml307_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);
ml307_mutex = rt_mutex_create ("ml307_mutex", RT_IPC_FLAG_FIFO);
if (ml307_mutex == RT_NULL)
{
LOG_E ("ml307_mutex create failed");
}
ml307_recv_sem = rt_sem_create ("ml307_recv", 0, RT_IPC_FLAG_PRIO);
if (ml307_recv_sem == RT_NULL)
{
LOG_E ("ml307_recv_sem create failed");
}
ml307_recv_msg_sem = rt_sem_create ("ml307_recv_heart", 0, RT_IPC_FLAG_PRIO);
if (ml307_recv_msg_sem == RT_NULL)
{
LOG_E ("ml307_recv_msg_sem create failed");
}
ml307_disconnect_sem = rt_sem_create ("ml307_life", 0, RT_IPC_FLAG_PRIO);
if (ml307_disconnect_sem == RT_NULL)
{
LOG_E ("ml307_disconnect_sem create failed");
}
// 创建定时器
ml307_timer = rt_timer_create ("heartbeat",
Ml307_Ht_Timer_Cb, // 回调函数
RT_NULL, // 参数
timeout, // 定时周期120分钟
RT_TIMER_FLAG_PERIODIC); // 周期性定时器
if (ml307_timer == RT_NULL)
{
rt_kprintf ("创建定时器失败\n");
return -1;
}
ml307_error_timer = rt_timer_create ("ml307_error_timer",
Ml307_Error_Timer_Cb,
RT_NULL,
3 * 60 * RT_TICK_PER_SECOND, // 3分钟
RT_TIMER_FLAG_PERIODIC);
ml307_upload_timer = rt_timer_create ("ml307_upload_timer",
Ml307_Upload_Timer_Cb,
RT_NULL,
24 * 60 * 60 * RT_TICK_PER_SECOND, //
RT_TIMER_FLAG_PERIODIC);
ret = rt_thread_init (&ml307_thread,
"ml307_send_thread",
Ml307_Send_Thread_Entry,
&ml307_ops,
&ml307_thread_stack[0],
sizeof (ml307_thread_stack),
ML307_THREAD_PRIORITY,
ML307_THREAD_TICKS);
rt_thread_startup (&ml307_thread);
ret = rt_thread_init (&ml307_recv_thread,
"ml307_recv_thread",
Ml307_Recv_Thread_Entry,
&ml307_ops,
&ml307_recv_thread_stack[0],
sizeof (ml307_recv_thread_stack),
ML307_RECV_THREAD_PRIORITY,
ML307_RECV_THREAD_TICKS);
rt_thread_startup (&ml307_recv_thread);
ret = rt_thread_init (&ml307_life_thread,
"ml307_life_thread",
Ml307_Life_Thread_Entry,
&ml307_ops,
&ml307_life_thread_stack[0],
sizeof (ml307_life_thread_stack),
ML307_LIFE_THREAD_PRIORITY,
ML307_LIFE_THREAD_TICKS);
rt_thread_startup (&ml307_life_thread);
return ret;
}
// INIT_APP_EXPORT(BSP_Ml307_Thread_Init);
int ml307_device_register (void)
{
struct at_device_ml307 *ml307 = &_dev;
return at_device_register (&(ml307->device),
ml307->device_name,
ml307->client_name,
AT_DEVICE_CLASS_ML307,
(void *)ml307);
}
// INIT_DEVICE_EXPORT(ml307_device_register);
#endif // IOT_MODULE_SWITCH