2288 lines
86 KiB
C
2288 lines
86 KiB
C
/*
|
||
* @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
|