主函数:
ret = device_init(DEVICE_SN, device_evt_cb, device_data_send_cb);
while (1)
{
ret = device_step();
}
参数:
#define DEVICE_SN "123456"
设备事件回调函数 int32 device_evt_cb(struct device_event_t *evt){}
通信串口数据发送接口 int32 device_data_send_cb(uint8 *data, uint16 data_len){}
struct device_event_t
{
enum device_evt_id_t evt_id;
uint8 *evt_data;
uint16 evt_data_len;
uint16 reserved;
};
参数:
typedef int32 (*device_event_cb)(struct device_event_t *evt);//类似于TLV的一个结构 叫做event!!
typedef int32 (*data_send_cb)(uint8 *data, uint16 data_len);
函数:
也就是给一个sn
给一个 event处理的函数
给一个发送到平台的接口
int32 device_init(const int8 *sn, device_event_cb event_cb, data_send_cb send_cb)
{
int32 ret = ERR_OK;
osl_memset(&device, 0, sizeof(struct device_t));
device.evt_cb = event_cb;
osl_memcpy(sn_buf, sn, strlen(sn));//static int8 sn_buf[DEV_SN_LEN + 1];
device.sn = sn_buf;
ret = protocol_init(send_cb);//???
return ret;
}
typedef int32 (*protocol_frame_send_cb)(uint8 *frame, uint16 frame_len);
也就是 protocol_frame_send_cb == data_send_cb
static struct prot_frame_parser_t parser;
struct prot_frame_parser_t
{
uint8 *recv_ptr;
uint8 *send_ptr;
uint16 r_oft;
uint16 w_oft;
uint16 frame_len;
uint16 found_frame_head;
protocol_frame_send_cb send_cb;
};
static uint8 recv_buf[PROT_FRAME_LEN_RECV];
static uint8 send_buf[PROT_FRAME_LEN_SEND];
int32 protocol_init(protocol_frame_send_cb callback)
{
osl_memset(&parser, 0, sizeof(struct prot_frame_parser_t));
/* 初始化分配数据接收与解析缓冲区*/
parser.recv_ptr = recv_buf;
/* 初始化分配数据发送缓冲区*/
parser.send_ptr = send_buf;
parser.send_cb = callback; //传入发送回调函数接口
return ERR_OK;
}
好了 代码看完 看循环
while (1)
{
ret = device_step(); //是一个状态机
}
会一直device_set_module_param(device.sn);
static int32 device_set_module_param(const int8 *sn)
{
int32 ret = ERR_OK;
uint16 payload_len = 0;
uint16 offset = 0;
uint16 sn_len = strlen(sn);//sn
uint16 product_id_len = strlen(PRODUCT_ID);//#define PRODUCT_ID "281509"
uint16 device_ver_len = strlen(DEV_VERSION);//#define DEV_VERSION "1.0.0"
uint8 *payload = protocol_send_buf_malloc(PROT_FRAME_LEN_SEND);//看一下
payload_len = 6 + sn_len + product_id_len + device_ver_len;
offset += set_lv_str(payload + offset, PRODUCT_ID);
offset += set_lv_str(payload + offset, sn);
offset += set_lv_str(payload + offset, DEV_VERSION);
ret = send_request_frame(FRAME_TYPE_CONFIG_MODULE, payload, payload_len);
return ret;
}
//看一下 开始
uint8 *protocol_send_buf_malloc(uint16 data_len)
{
uint8 *send = NULL;
if (data_len > PROT_FRAME_LEN_SEND) return NULL;
send = parser.send_ptr;
return (send + sizeof(struct prot_frame_header_t)); //返回数据段首地址 有意思!
}
#pragma pack(1)
struct prot_frame_header_t
{
uint16 sync;//#define PROT_FRAME_SYNC 0x5A5A
uint16 len;
uint8 type: 5;
uint8 ver: 2;
uint8 response: 1;
};
#pragma pack()
//看一下 结束
//一个str进去 复制到data里面 同时在前面多2个字节 描述它的LEN 也就是TLV其实没有T
//所以全部长度+6 明白了吧 有3个LV进来
//这句是TLV嵌套吧
static uint16 set_lv_str(uint8 *data, const int8 *str)
{
uint16 str_len = 0;
if (!str)
str_len = 0;
else
str_len = strlen(str);
*data++ = str_len & 0xFF;
*data++ = (str_len >> 8) & 0xFF;
osl_memcpy(data, str, str_len);
return (2 + str_len);
}
继续看 现在是已经准备好了body
ret = send_request_frame(FRAME_TYPE_CONFIG_MODULE, payload, payload_len);
static int32 send_request_frame(enum protocol_frame_type_t type, uint8 *data, uint16 data_len)
{
int32 ret = ERR_OK;
device.last_frame_time = osl_time_ms();
ret = protocol_frame_pack_and_send(type, PROT_REQUEST, data, data_len);//参数和过来的一样 多了一个0 1标识主动还是反馈
if (ERR_OK != ret)
return ret;
return process_frame(type, PROTOCOL_FRAME_TIMEOUT_SEC);
}
int32 protocol_frame_pack_and_send(enum protocol_frame_type_t type, uint8 is_resp, uint8 *data, uint16 data_len)
{
uint8 *send_frame = NULL;
uint8 *checksum = NULL;
struct prot_frame_header_t *header;
if (!data_len)//也就是没有body 只有头的包
{
data = protocol_send_buf_malloc(PROT_FRAME_LEN_SEND);
}
send_frame = data - sizeof(struct prot_frame_header_t); //send_frame指针指向帧头 其实可以直接指向数组头即可
/** 协议封包*/
header = (struct prot_frame_header_t *)send_frame;//赋值技巧!!!!!
header->sync = PROT_FRAME_SYNC;//#define PROT_FRAME_SYNC 0x5A5A
header->len = sizeof(struct prot_frame_header_t) + data_len + PROT_FRAME_LEN_CHECKSUM;//头+数据bosy+CRC1 它的好处是啥?我以前TLV总是V长度不定 现在这样头体分离 完美
header->response = is_resp;
header->ver = 0x01;
header->type = type;
checksum = (uint8 *)(send_frame + sizeof(struct prot_frame_header_t) + data_len);
*checksum = cal_checksum((uint8 *)send_frame, header->len - PROT_FRAME_LEN_CHECKSUM);
parser.send_cb(send_frame, header->len); //调用串口发送回调函数,发送数据
return ERR_OK;
}
最后就是打包好了 发送出去!
所以它是MCU把数据整理好发送联网模块 即可 联网的流程都是在模块完成的 模块的代码是移动自己写的
return的是 解析RX数据
case FRAME_TYPE_CONFIG_MODULE:
{
resp_code = (enum protocol_resp_code_t)(*payload);
if (RESPONSE_CODE_OK == resp_code)
{
ret = ERR_OK;
device.state = DEVICE_STATE_RUNNING;
}
else
ret = ERR_INITIALIZING;
break;
}