443 lines
11 KiB
C
443 lines
11 KiB
C
/*
|
|
* ne_sweeper.c -- provide iot-system device layer of yanxuan sweeper operation interface.
|
|
*
|
|
*
|
|
* ORIGINAL AUTHOR:
|
|
*
|
|
* Copyright (c) 2018 Netease Corporation
|
|
*/
|
|
|
|
#include "c_types.h"
|
|
#include "user_main.h"
|
|
#include "ne_sweeper.h"
|
|
|
|
#include "esp_common.h"
|
|
#include "cfg.h"
|
|
#include "uart.h"
|
|
#include "log.h"
|
|
#include "ne_device.h"
|
|
#include "esp_MSG_ctrl.h"
|
|
#include "ota.h"
|
|
#include "freertos/semphr.h"
|
|
|
|
|
|
static void *yanxuan_sweeper_sema;
|
|
|
|
|
|
/*
|
|
* yanxuan sweeper uart init.
|
|
*/
|
|
int32 yanxuan_sweeper_init(void *arg)
|
|
{
|
|
UART_WaitTxFifoEmpty(UART0);
|
|
UART_WaitTxFifoEmpty(UART1);
|
|
|
|
UART_IntrConfTypeDef uart_intr;
|
|
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA;
|
|
uart_intr.UART_RX_FifoFullIntrThresh = 120;
|
|
uart_intr.UART_RX_TimeOutIntrThresh = 2;
|
|
uart_intr.UART_TX_FifoEmptyIntrThresh = 10;
|
|
UART_IntrConfig(UART0, &uart_intr);
|
|
|
|
UART_ConfigTypeDef uart_config;
|
|
uart_config.baud_rate = BIT_RATE_115200;
|
|
uart_config.data_bits = UART_WordLength_8b;
|
|
uart_config.parity = USART_Parity_None;
|
|
uart_config.stop_bits = USART_StopBits_1;
|
|
uart_config.flow_ctrl = USART_HardwareFlowControl_CTS_RTS;
|
|
uart_config.UART_RxFlowThresh = 120;
|
|
uart_config.UART_InverseMask = UART_None_Inverse;
|
|
UART_ParamConfig(UART0, &uart_config);
|
|
|
|
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
|
|
UART_ParamConfig(UART1, &uart_config);
|
|
|
|
UART_SetPrintPort(UART1); // uart1 for log.
|
|
ETS_UART_INTR_ENABLE();
|
|
yanxuan_sweeper_sema = xSemaphoreCreateMutex();
|
|
if (yanxuan_sweeper_sema == NULL) {
|
|
LOG_EX(LOG_Info, "init fail!\r\n");
|
|
|
|
return -ERR_FAIL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
int32 yanxuan_sweeper_deinit(void * arg)
|
|
{
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
int32 yanxuan_sweeper_write(void *arg, uint8 *input, uint32 len)
|
|
{
|
|
xSemaphoreTake(yanxuan_sweeper_sema, portMAX_DELAY);
|
|
uart_tx_buf(0, input, len);
|
|
xSemaphoreGive(yanxuan_sweeper_sema);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
/*
|
|
* yanxuan sweeper read datas.
|
|
*/
|
|
int32 yanxuan_sweeper_read(void *arg, uint8 **output, uint32 *len)
|
|
{
|
|
static int32 recv_temp_len=0;
|
|
ne_uart_recv_t * recv = ne_get_uart_recv_info();
|
|
|
|
if(recv->recv_len > recv_temp_len){
|
|
recv_temp_len = recv->recv_len;
|
|
}
|
|
else if(recv->recv_len == recv_temp_len && recv_temp_len != 0){
|
|
*len = recv_temp_len;
|
|
*output = recv->uart_buf;
|
|
recv_temp_len = 0;
|
|
return ERR_OK;
|
|
}
|
|
else{
|
|
recv_temp_len = 0;
|
|
}
|
|
|
|
return -ERR_FAIL;
|
|
}
|
|
|
|
/*
|
|
* yanxuan sweeper 8bit check.
|
|
*/
|
|
uint8 yanxuan_sweeper_check_8bit (uint8* in_data,uint8 in_len)
|
|
{
|
|
uint8 crc = 0;
|
|
uint8 loop = 0;
|
|
for (loop = 0;loop < in_len; loop++) {
|
|
crc += in_data[loop];
|
|
}
|
|
crc = ~crc;
|
|
crc += 1;
|
|
|
|
return crc;
|
|
}
|
|
|
|
/*
|
|
* yanxuan sweeper 16bit check.
|
|
*/
|
|
uint16 yanxuan_sweeper_check_16bit(uint8_t *input, uint16 input_len)
|
|
{
|
|
uint16 check_sum=0;
|
|
uint16 loop;
|
|
|
|
for(loop=0;loop<input_len;loop++){
|
|
check_sum += input[loop];
|
|
}
|
|
check_sum = ~check_sum;
|
|
check_sum += 1;
|
|
|
|
return check_sum;
|
|
}
|
|
|
|
/*
|
|
* yanxuan sweeper data split.
|
|
*/
|
|
int32 yanxuan_sweeper_split(void *arg, uint32 *offset, uint8 *input, uint32 len, uint8 *output, uint32 *out_len)
|
|
{
|
|
uint16 check_sum_c;
|
|
uint16 check_sum_d;
|
|
int pos;
|
|
uint16 frame_header, msg_len;
|
|
|
|
/* cycle check protocol */
|
|
for(pos=*offset; pos<len; pos++){
|
|
yanxuan_sweeper_protocol_header_t* header = (yanxuan_sweeper_protocol_header_t*)(input
|
|
+ pos);
|
|
yanxuan_sweeper_expand_protocol_header_t *header_b = (yanxuan_sweeper_expand_protocol_header_t *)(input + pos);
|
|
|
|
frame_header = (header_b->frame_header[0]<<0);
|
|
frame_header |= (header_b->frame_header[1]<<8);
|
|
|
|
/* header check */
|
|
if (header->frame_header != 0xAA && frame_header != 0xefcc)
|
|
continue;
|
|
|
|
/* sweeper protocol check */
|
|
if(header->frame_header == 0xAA){
|
|
if ((header == NULL) || (len - pos < sizeof(yanxuan_sweeper_protocol_header_t)) || (header->msg_len > len - pos - 1))
|
|
continue;
|
|
|
|
/* get checksum */
|
|
if (input[header->msg_len + pos] != yanxuan_sweeper_check_8bit(&(header->msg_len), header->msg_len - 1)) {
|
|
LOG_EX(LOG_Debug," yanxuan_sweeper_check_8bit error!\r\n");
|
|
|
|
continue;
|
|
}
|
|
*out_len = header->msg_len + 1;
|
|
memcpy(output, input + pos, *out_len);
|
|
*offset =pos + *out_len;
|
|
|
|
return MSG_DIRECTION_UART_UP;
|
|
}
|
|
|
|
/* sweeper expand protocol check */
|
|
else if(frame_header == 0xefcc){
|
|
|
|
if((header_b == NULL) || (len - pos < sizeof(yanxuan_sweeper_expand_protocol_header_t)))
|
|
continue;
|
|
|
|
msg_len = (header_b->msg_len[0]<<0);
|
|
msg_len |= (header_b->msg_len[1]<<8);
|
|
if(msg_len > NE_DEVICE_BUF_SIZE || (msg_len > len - pos - 2)){
|
|
LOG_EX(LOG_Debug," len overflow!\r\n");
|
|
|
|
continue;
|
|
}
|
|
|
|
check_sum_d = input[msg_len + pos];
|
|
check_sum_d |= input[msg_len+1 + pos]<<8;
|
|
|
|
/* get checksum */
|
|
check_sum_c = yanxuan_sweeper_check_16bit((uint8 *)&header_b->msg_len, msg_len - 2);
|
|
if(check_sum_d != check_sum_c){
|
|
LOG_EX(LOG_Debug,"check_sum_d=0x%x, check_sum_c=0x%x\r\n",check_sum_d, check_sum_c);
|
|
|
|
continue;
|
|
}
|
|
*out_len = msg_len + 2;
|
|
memcpy(output, input + pos, *out_len);
|
|
*offset =pos + *out_len;
|
|
|
|
return MSG_DIRECTION_BDATA_UP;
|
|
}
|
|
}
|
|
*offset = pos;
|
|
|
|
return -ERR_FAIL;
|
|
}
|
|
|
|
int yanxuan_sweeper_create_frame(uint8_t cmd, uint8_t *payload, int in_len, uint8 *output, int max_len)
|
|
{
|
|
yanxuan_sweeper_protocol_header_t *msg_header;
|
|
int count = 0;
|
|
int msg_len;
|
|
|
|
/* params check */
|
|
if(payload == NULL || output == NULL || in_len <= 0 || in_len + sizeof(yanxuan_sweeper_protocol_header_t) + 1 > max_len){
|
|
return -ERR_FAIL;
|
|
}
|
|
|
|
msg_header = (yanxuan_sweeper_protocol_header_t *)output;
|
|
memset(msg_header, 0 , sizeof(yanxuan_sweeper_protocol_header_t));
|
|
|
|
/* set msg header */
|
|
msg_header->frame_header = 0xaa;
|
|
msg_header->msg_len = in_len + sizeof(yanxuan_sweeper_protocol_header_t) - 1;
|
|
msg_header->device_type = 0xb8;
|
|
msg_header->msg_id = cmd;
|
|
|
|
/* get payload */
|
|
memcpy(output + sizeof(yanxuan_sweeper_protocol_header_t), payload, in_len);
|
|
|
|
/* calculate sum */
|
|
output[msg_header->msg_len] = yanxuan_sweeper_check_8bit(&msg_header->msg_len, msg_header->msg_len - 1);
|
|
|
|
/* message len */
|
|
msg_len = msg_header->msg_len + 1;
|
|
|
|
return msg_len;
|
|
}
|
|
|
|
void yanxuan_sweeper_connect_rsp(uint8 result)
|
|
{
|
|
uint8_t r_buf[] = {0xaa,0x0c,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x01,0x01,0xff};
|
|
|
|
LOG_EX(LOG_Info, "connect respond to mcu!\r\n");
|
|
r_buf[10] = result; // 1:success
|
|
r_buf[r_buf[1]] = yanxuan_sweeper_check_8bit(&r_buf[1], r_buf[1]-1);
|
|
yanxuan_sweeper_write(NULL, r_buf, sizeof(r_buf));
|
|
|
|
}
|
|
|
|
static void _yanxuan_sweeper_enter_softap(void)
|
|
{
|
|
ne_cfg_set_init_type(NE_DEVICE_APCONFIG);
|
|
// wifi_station_disconnect();
|
|
// vTaskDelay(500 / portTICK_RATE_MS);
|
|
system_restart();
|
|
}
|
|
|
|
static void _yanxuan_sweeper_exit_softap(void)
|
|
{
|
|
uint8_t r_buf[] = {0xaa,0x0c,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x01,0x01,0xff};
|
|
|
|
LOG_EX(LOG_Info, "exit softap!\r\n");
|
|
SoftAPExitCfgMode(0);
|
|
ne_cfg_set_init_type(NE_DEVICE_NORMAL);
|
|
|
|
/* respond */
|
|
r_buf[10] = 1; // 1:success
|
|
r_buf[r_buf[1]] = yanxuan_sweeper_check_8bit(&r_buf[1], r_buf[1]-1);
|
|
yanxuan_sweeper_write(NULL, r_buf, sizeof(r_buf));
|
|
vTaskDelay(500 / portTICK_RATE_MS);
|
|
|
|
/* restart */
|
|
system_restart();
|
|
}
|
|
|
|
static void _yanxuan_sweeper_cannel_bind(void)
|
|
{
|
|
uint8_t r_buf[] = {0xaa,0x0c,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x01,0x01,0xff};
|
|
|
|
wifi_station_disconnect();
|
|
ne_clear_ssid_psk();
|
|
// respond OK
|
|
LOG_EX(LOG_Info, "cannel bind!\r\n");
|
|
r_buf[10] = 1; // 1:success
|
|
r_buf[r_buf[1]] = yanxuan_sweeper_check_8bit(&r_buf[1], r_buf[1]-1);
|
|
yanxuan_sweeper_write(NULL, r_buf, sizeof(r_buf));
|
|
}
|
|
|
|
|
|
static void _yanxuan_sweeper_clear_ssid(void)
|
|
{
|
|
uint8_t r_buf[] = {0xaa,0x0b,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x86,0x01,0xff};
|
|
|
|
wifi_station_disconnect();
|
|
ne_clear_ssid_psk();
|
|
|
|
// respond OK
|
|
LOG_EX(LOG_Info, "clear ssid!\r\n");
|
|
r_buf[10] = 1; // 1:success
|
|
r_buf[r_buf[1]] = yanxuan_sweeper_check_8bit(&r_buf[1], r_buf[1]-1);
|
|
yanxuan_sweeper_write(NULL, r_buf, sizeof(r_buf));
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _yanxuan_sweeper_ota_process(uint8_t *input, uint8_t len)
|
|
{
|
|
uint8_t msg_type;
|
|
yanxuan_sweeper_protocol_header_t* header = (yanxuan_sweeper_protocol_header_t*)input;
|
|
|
|
if(len > 255){
|
|
LOG_EX(LOG_Error, "len error!\r\n");
|
|
}
|
|
|
|
input += sizeof(yanxuan_sweeper_protocol_header_t);
|
|
msg_type = input[0];
|
|
// LOG_EX(LOG_Info, "OTA Process %x!\r\n", msg_type);
|
|
switch(msg_type){
|
|
case 0x02:
|
|
{
|
|
struct OTA_Start_Cmd cmd;
|
|
|
|
cmd.type = OTA_DEVICE_MCU;
|
|
MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_START, &cmd);
|
|
}
|
|
break;
|
|
|
|
case 0x03:
|
|
{
|
|
struct OTA_SegDownload_Cmd cmd;
|
|
|
|
cmd.seg_num = input[1];
|
|
cmd.seg_size = 256*1000;
|
|
MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_SEGDOWNLOAD, &cmd);
|
|
}
|
|
break;
|
|
case 0x04:
|
|
{
|
|
struct OTA_SegRead_Cmd cmd;
|
|
|
|
|
|
cmd.length = (input[1]<<0);
|
|
cmd.length |= (input[2]<<8);
|
|
|
|
cmd.offset = (input[3]<<0);
|
|
cmd.offset |= (input[4]<<8);
|
|
cmd.offset |= (input[5]<<16);
|
|
cmd.offset |= (input[6]<<24);
|
|
|
|
MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_SEGREAD, &cmd);
|
|
}
|
|
break;
|
|
case 0x05:
|
|
{
|
|
struct OTA_Quit_Cmd cmd;
|
|
|
|
MSG_ctrl_cmd_put(MSG_CONTROL_CMD_OTA_QUIT, &cmd);
|
|
}
|
|
break;
|
|
case 0x11:
|
|
// ProCacheMCUMsg(input, len, MSG_TYPE_BYPASS);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* yanxuan sweeper protocol process.
|
|
*/
|
|
int32 yanxuan_sweeper_process(void *arg, uint8 msgdir, uint8 *input, uint32 ilen, uint8 *output, uint32 max_len)
|
|
{
|
|
|
|
uint8 msg_id;
|
|
yanxuan_sweeper_protocol_header_t* header = (yanxuan_sweeper_protocol_header_t*)input;
|
|
|
|
LOG_EX(LOG_Info, "[msgdir]=%d [msg_id]=0x%x\r\n", msgdir, header->msg_id);
|
|
|
|
/* protocol process */
|
|
if(msgdir == MSG_DIRECTION_BDATA_UP){
|
|
ProCacheMCUMsg(input, ilen, MSG_TYPE_BIGDATA);
|
|
}
|
|
else if (msgdir == MSG_DIRECTION_CLOUD_DOWN || msgdir == MSG_DIRECTION_OTA_DOWN || msgdir == MSG_DIRECTION_BDATA_DOWN){
|
|
if(ilen > max_len)
|
|
return -ERR_FAIL;
|
|
|
|
memcpy(output, input, ilen);
|
|
|
|
return ilen;
|
|
}
|
|
else {
|
|
switch (header->msg_id) {
|
|
case 0x04:
|
|
case 0x05:
|
|
ProCacheMCUMsg(input, ilen, MSG_TYPE_SHADOW);
|
|
break;
|
|
case 0x02:
|
|
case 0x03:
|
|
case 0x20:
|
|
case 0x06:
|
|
ProCacheMCUMsg(input, ilen, MSG_TYPE_BYPASS);
|
|
break;
|
|
case 0x08:
|
|
_yanxuan_sweeper_ota_process(input, ilen);
|
|
break;
|
|
case 0x63:
|
|
set_platform_product_id(input + 12, 4);
|
|
_yanxuan_sweeper_enter_softap();
|
|
break;
|
|
case 0x82:
|
|
_yanxuan_sweeper_exit_softap();
|
|
break;
|
|
case 0x84:
|
|
_yanxuan_sweeper_cannel_bind();
|
|
break;
|
|
case 0x86:
|
|
_yanxuan_sweeper_clear_ssid();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|