esp8266-std/driver/ne_sweeper.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;
}