/****************************************************************************** * file Core/Src/wireless.c * author YuLiang * version 1.0.0 * date 14-Jun-2022 * brief This file provides all the wireless related operation functions. ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2022 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of WTOE nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stdio.h" #include "string.h" #include "time.h" #include "usart.h" #include "adc.h" #include "tim.h" #include "rtc.h" #include "common.h" #include "wireless.h" #include "dev_config.h" #include "ADC_collect.h" #include "flash_if.h" #include "RS485_debug.h" #include "flash_log.h" /* Private define ------------------------------------------------------------*/ #define WL_RX_TIMEOUT 500 // 每 500ms 检查一次收包数据. #define WL_USART_ERR_TIMEOUT 1000 // 串口发送错误延迟时间. #define WL_SOFT_INIT_ERR 5 // 软件初始化错误最大次数. #define WL_DATA_ERR 3 // 数据发送错误最大次数. #define WL_PWR_FRE_CH_NUM 4 // 工频录波通道数. #define WL_FLASH_BUF_SIZE 1024 #define WIR_RX_TIMEOUT 10000 // 有线模式每 10s 检查一次收包数据. /* Private typedef -----------------------------------------------------------*/ /* 状态机状态. */ typedef enum { WL_STATE_SOFT = 0, WL_STATE_AT_ATE, WL_STATE_AT_QICSGP, WL_STATE_AT_QIACT, WL_STATE_AT_CSQ, WL_STATE_AT_QICFGTS, WL_STATE_AT_QICFGWT, WL_STATE_AT_QIOPEN, WL_STATE_ADC_WAIT, WL_STATE_WAKEUP = 128, WL_STATE_REALDATA, WL_STATE_PWR_FRE, WL_STATE_UPDATE, WL_STATE_UPDATE_RT, WL_STATE_WAVE, WL_STATE_WAVE_MAX, WL_STATE_POSITION, WL_STATE_POSITION_WAVE, WL_STATE_KEEPALIVE, CSG_STATE_CONNECT, CSG_STATE_TIME, CSG_STATE_BEAT, CSG_STATE_IDLE, CSG_STATE_DATA, CSG_STATE_DATA_HIS, WL_STATE_END = 255 } WL_STATE_E; typedef struct { uint32_t start; uint16_t len; uint16_t type; uint32_t id; uint32_t life_cnt; uint16_t num; uint16_t num_index; } wl_proto_head_t; typedef struct { uint32_t checksum; uint32_t end; } wl_proto_tail_t; /* RS485调试通讯协议器件信息. */ typedef struct { /* 设备信息. 36byte */ uint8_t type_m; uint8_t type_s; uint8_t mac[6]; uint32_t id; uint8_t ip[4]; uint8_t ip_mask[4]; uint8_t ip_gw[4]; uint8_t server_ip[4]; uint8_t wireless_server_ip[4]; uint16_t server_port; uint16_t wireless_server_port; /* 版本信息. 224byte */ uint8_t boot_version[DEV_VERSION_STR_LEN]; uint8_t boot_compile_time[DEV_COMPILE_TIME_LEN]; uint8_t img_version[DEV_VERSION_STR_LEN]; uint8_t img_compile_time[DEV_COMPILE_TIME_LEN]; uint8_t hardware_version[DEV_VERSION_STR_LEN]; uint8_t FPGA_version[DEV_VERSION_STR_LEN]; uint8_t factory_time[DEV_COMPILE_TIME_LEN]; /* 设备其他信息. 128byte */ uint8_t name[DEV_NAME_LEN]; } wl_proto_wakeup_t; /* 实时数据传输结构体. */ typedef struct { int16_t temperature; // 设备温度, 单位: 0.1℃. uint16_t vbat; // 电池电压, 单位: mv. int16_t CSQ; // 4G 信号质量 > -51dBm 统一显示 -51dBm, < -113 dBm 为无信号. uint16_t vin; // 工作电压, 单位: mv. uint32_t elec[CFG_ADC_CH_CNT]; // 通道电流有效值 mA. uint16_t vsc; // 超级电容电压, 单位: mv. uint16_t sen_temp[SENSOR_SUM]; // 传感器温度: 单位: 0.1℃. uint16_t sen_x[SENSOR_SUM]; // 传感器震动 x 轴. uint16_t sen_y[SENSOR_SUM]; // 传感器震动 y 轴. uint16_t sen_z[SENSOR_SUM]; // 传感器震动 z 轴. uint8_t energy_mode; // 当前设备工作模式. uint8_t sen_short; // 传感器是否短路, 0 – 没有短路, 1 – 短路. uint8_t sen_valid[SENSOR_SUM]; // 传感器数据是否有效, 0 - 无效, 1 - 有效. uint32_t run_time; // 设备运行时长, 单位 s. uint8_t fre_valid; // 工频数据有效, 有线协议使用. uint8_t wave_valid; // 高频数据有效, 有线协议使用. uint8_t reserve[2]; } wl_proto_realdata_t; /* 实时数据传输结构体. */ typedef struct { int16_t wave[WAVE_SUM]; // 高频录波最大值, 0 - 无效, 1 - 有效值. } wl_proto_wave_max_t; typedef struct { uint32_t utc; uint16_t interval; uint8_t wave_force; uint8_t wave_interval; uint16_t threshold; uint16_t wave_threshold; uint8_t is_updata; uint8_t main_cable; uint8_t normal_sleep; uint8_t is_voltage_col; uint8_t is_temp_col; uint8_t is_wave_col; uint8_t reserve[2]; //字节对齐 uint32_t position_file_s; uint32_t position_file_ns; } wl_proto_config_t; /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ osThreadId_t WLHandle; const osThreadAttr_t WL_attributes = { .name = "WIRELESS", .stack_size = 160 * 2 * 4, .priority = (osPriority_t) osPriorityNormal, }; wl_buf_list_t wl_buf_list_rx; static UART_HandleTypeDef *wl_uart = &huart3; wl_ctrl_t wl_ctrl; static fd_date_t csg_adc_data; static uint64_t csg_data_idx[CSG_PKT_DATA_SUM]; /* Private function prototypes -----------------------------------------------*/ static void _wl_4G_wakeup_send(void); static void _wl_4G_realdata_send(void); static void _wl_4G_update_send(void); static void _wl_4G_update_rt_send(void); static void _wl_4G_power_fre_send(void); static void _wl_4G_wave_max_send(void); static void _wir_data_process(uint8_t *cmd, uint32_t len); static void _csg_pkt_recv(void); /* Internal functions --------------------------------------------------------*/ /* 初始化 4G 模块硬件 */ static void _wl_4G_hw_init(void) { /* 4G 模块供电打开.*/ osDelay(1000); HAL_GPIO_WritePin(POWER_4G_GPIO_Port, POWER_4G_Pin, GPIO_PIN_SET); /* 4G 模块复位. */ osDelay(500); HAL_GPIO_WritePin(G4G_RST_GPIO_Port, G4G_RST_Pin, GPIO_PIN_SET); osDelay(100); HAL_GPIO_WritePin(G4G_RST_GPIO_Port, G4G_RST_Pin, GPIO_PIN_RESET); } /* 关闭 4G 模块硬件. */ static void _wl_4G_hw_close(uint32_t sleep_time) { HAL_GPIO_WritePin(POWER_4G_GPIO_Port, POWER_4G_Pin, GPIO_PIN_RESET); if (sleep_time < 1800) { sleep_time = 1800; } common_sys_set(COM_SYS_SHUTDOWN, (void*)&sleep_time); while(1) { osDelay(portMAX_DELAY); } } /* 关闭 4G 模块硬件. */ static void _wl_4G_hw_restart(void) { DBG(DBG_M_4G, "4G restart(%d),\r\n", wl_ctrl.err_cnt); /* 开启串口空闲中断收包. */ if (wl_ctrl.err_cnt) { if (DEV_TYPE_CT_P != dev_info.type_s) { flash_log_write(FLASH_LOG_TYPE_WARNING, "Server is disconnect system sleep %ds!\r\n", dev_config.collect_interval * 60 - 30); _wl_4G_hw_close(dev_config.collect_interval * 60 - 30); return; } /* 故障定位版本设备出现问题时重启不休眠 */ else { flash_log_write(FLASH_LOG_TYPE_WARNING, "Server is disconnect system reset!\r\n"); _wl_4G_hw_close(0); return; } } HAL_UART_Abort(wl_uart); memset(&wl_buf_list_rx, 0, sizeof(wl_buf_list_t)); osDelay(200); HAL_UARTEx_ReceiveToIdle_DMA(wl_uart, wl_ctrl.dma_rx_buf, WL_DMA_RX_BUF_LEN); /* 初始化 4G 模块硬件. */ HAL_GPIO_WritePin(POWER_4G_GPIO_Port, POWER_4G_Pin, GPIO_PIN_RESET); _wl_4G_hw_init(); /* 20s 内要收到 4G 模块发出的 RDY. */ wl_ctrl.state = 0; wl_ctrl.send_cnt = 0; wl_ctrl.mul_idx = 0; wl_ctrl.cmd_buf_index = 0; wl_ctrl.time_send = HAL_GetTick() + 20000; //wl_ctrl.wave_index = dev_record.wave_index; wl_ctrl.err_cnt++; } /* AT 命令 CSQ 返回数据处理. */ static void _wl_4G_AT_CSQ_process(uint8_t *cmd) { int32_t rssi = 99; int32_t ber = 99; sscanf((char*)cmd, "+CSQ: %d,%d\r\n", &rssi, &ber); if (rssi != 99) { wl_ctrl.CSQ = -113 + (2 * rssi); } else { wl_ctrl.CSQ = -115; } } /* AT 命令回复处理. */ static void _wl_4G_AT_process(uint8_t *cmd) { if (0 == strncmp((char*)cmd, "RDY", 3)) { /* 芯片启动后会发送. */ wl_ctrl.state++; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else if (0 == strncmp((char*)cmd, "OK", 2)) { /* 命令执行成功. */ if (wl_ctrl.state < WL_STATE_AT_QIOPEN) { wl_ctrl.state++; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } } else if (0 == strncmp((char*)cmd, "CONNECT", 7)) { /* 软件初始化完成. */ wl_ctrl.state++; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else if (0 == strncmp((char*)cmd, "+CSQ", 4)) { /* 获取信号质量. */ _wl_4G_AT_CSQ_process(cmd); } else if (0 == strncmp((char*)cmd, "ERROR", 5)) { /* 命令执行失败. */ wl_ctrl.time_send = HAL_GetTick() + 1000; } } /* 处理接收到的 AT 指令. */ void _wl_4G_AT_recv(void) { wl_buf_list_t *buf_l = &wl_buf_list_rx; uint8_t *buf = NULL; uint8_t i = 0; /* 遍历所有有效的 buf. */ while(buf_l->current != buf_l->valid) { buf = buf_l->buf[buf_l->current]; /* 将 buf 中的数据解析成命令. */ for(i = 0; i < buf_l->buf_cnt[buf_l->current]; i++) { wl_ctrl.cmd_buf[wl_ctrl.cmd_buf_index] = buf[i]; wl_ctrl.cmd_buf_index++; if (buf[i] != 0x0a) { /* 不是回车继续读取数据. */ continue; } /* 命令长度小于 2 为无效命令. */ if (wl_ctrl.cmd_buf_index <= 2) { wl_ctrl.cmd_buf_index = 0; continue; } /* 添加结束位, 更新 cmd buf index, 执行命令解析. */ wl_ctrl.cmd_buf[wl_ctrl.cmd_buf_index] = 0; wl_ctrl.cmd_buf_index = 0; DBG(DBG_M_4G, "Recv: %s\r\n", wl_ctrl.cmd_buf); _wl_4G_AT_process(wl_ctrl.cmd_buf); } /* 更新 buf index. */ buf_l->current++; if (WL_BUF_LIST_LEN == buf_l->current) { buf_l->current = 0; } } } static void _wl_4G_pkt_id_update(void) { wl_ctrl.pkt_id++; } static int32_t _wl_4G_pkt_check(uint8_t *cmd, uint32_t len) { proto_head_t *head = (proto_head_t*)cmd; /* 设备进入复位状态后不再处理报文. */ if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_RESET)) { vty_print("@0\r\n"); /* 这里挂住线程是因为重启时如果有收包, 会导致收包出错, 从而让设备进入休眠状态. */ osDelay(portMAX_DELAY); return HAL_ERROR; } /* 对主次设备号进行识别, 次设备号可以是广播. */ if ((head->dev_type_m != dev_info.type_m) || (head->dev_type_s != dev_info.type_s && head->dev_type_s != 0xFF)) { vty_print("@1\r\n"); return HAL_ERROR; } /* 对设备 id 进行识别, 可以是广播. */ if (head->dev_id != (*(uint32_t*)dev_info.id) && head->dev_id != 0xFFFFFFFF) { vty_print("@2\r\n"); return HAL_ERROR; } /* 验证 CRC32. */ if (crc32(cmd, head->len) != (*(uint32_t*)(cmd + head->len))) { vty_print("@3: %x %x\r\n", crc32(cmd, head->len), *(uint32_t*)(cmd + head->len)); return HAL_ERROR; } /* pkt_id 验证. */ if (head->pkt_id != wl_ctrl.pkt_id && dev_info.type_s != DEV_TYPE_ACDC) { vty_print("@4: %d %d\r\n", head->pkt_id, wl_ctrl.pkt_id); return HAL_ERROR; } return HAL_OK; } /* 设备信息获取报文处理. */ static void _wl_4G_pkt_reply(void) { wl_ctrl.state = WL_STATE_PWR_FRE; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } else { _wl_4G_realdata_send(); } return; } /* 设备信息回复. */ static void _wl_4G_dev_info_reply(uint8_t *cmd, uint32_t len) { wl_proto_config_t *cfg = (wl_proto_config_t*)(cmd + sizeof(proto_head_t)); uint8_t is_cfg_save = FALSE; uint8_t i = 0; if (cfg->interval != dev_config.collect_interval) { is_cfg_save = TRUE; dev_config_collect_interval_set(cfg->interval); } if (cfg->wave_interval != dev_config.wave_interval) { is_cfg_save = TRUE; dev_config_wave_interval_set(cfg->wave_interval); } if (cfg->threshold != dev_config.threshold) { is_cfg_save = TRUE; dev_config.threshold = cfg->threshold; } if (cfg->wave_threshold != dev_config.wave_threshold) { is_cfg_save = TRUE; dev_config.wave_threshold = cfg->wave_threshold; } if (cfg->main_cable != dev_config.main_cable) { is_cfg_save = TRUE; dev_config.main_cable = cfg->main_cable; } if (cfg->normal_sleep != dev_config.normal_sleep) { is_cfg_save = TRUE; dev_config.normal_sleep = cfg->normal_sleep; } if (cfg->is_voltage_col != dev_config.is_voltage_col) { is_cfg_save = TRUE; dev_config.is_voltage_col = cfg->is_voltage_col; } if (cfg->is_temp_col != dev_config.is_temp_col) { is_cfg_save = TRUE; dev_config.is_temp_col = cfg->is_temp_col; } if (cfg->is_wave_col != dev_config.is_wave_col) { is_cfg_save = TRUE; dev_config.is_wave_col = cfg->is_wave_col; } if (is_cfg_save) { common_sys_set(COM_SYS_SAVE_CONFIG, 0); } is_cfg_save = FALSE; if (cfg->wave_force != st_data.wave_force) { st_data.wave_force = cfg->wave_force; is_cfg_save = TRUE; } /* 强制录波或者间隔时间到了, 并且当前录波上传已完成. */ if ((cfg->wave_force || abs_cal_u(cfg->utc, st_data.wave_time) > (dev_config.wave_interval * 3600)) && !st_data.wave_up_start && DEV_TYPE_CT_P != dev_info.type_s) { st_data.wave_time = cfg->utc; st_data.wave_start = TRUE; st_data.wave_up_start = TRUE; st_data.wave_index = 0; for(i = 0; i < WAVE_SUM; i++) { st_data.wave_max[i] = 0; } wl_ctrl.wave_index = 0; is_cfg_save = TRUE; } if (is_cfg_save) { st_write(&st_data); } /* 更新 RTC 时间. */ rtc_time_set(cfg->utc); wl_ctrl.state = WL_STATE_REALDATA; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; wl_ctrl.is_update = cfg->is_updata; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } else { _wl_4G_wakeup_send(); } return; } /* 设备 APP 升级回复. */ static void _wl_4G_update_reply(uint8_t *cmd, uint32_t len) { mul_head_t *m_head = (mul_head_t*)(cmd + sizeof(proto_head_t)); uint8_t *data = (uint8_t*)(cmd + sizeof(proto_head_t) + sizeof(mul_head_t)); uint32_t addr = TFTP_APP_ADDRESS; uint32_t app_len = 0; /* index 为 0 表示是首保, 需要擦除 FLASH. */ if (0 == m_head->index) { /* 开始时置升级结果为错误. */ wl_ctrl.update_rt = HAL_ERROR; while(addr != TFTP_APP_ADDRESS_END) { if (spi_flash_erase(addr, SPI_CMD_BLOCK64_ERASE) != HAL_OK) { return; } addr += SPI_FLASH_BLOCK64_SIZE; } } /* 计算写 FLASH 地址, 并写入 FLASH. */ addr = TFTP_APP_ADDRESS + m_head->index * DEBUG_DATA_SIZE; if (m_head->len > DEBUG_DATA_SIZE) { return; } else if(m_head->len > 0) { if (spi_flash_write(addr, data, m_head->len) != HAL_OK) { return; } } /* 长度小于 DEBUG_FLASH_BUF_SIZE 则认为是最后一包. */ if(m_head->len < DEBUG_DATA_SIZE) { /* 校验数据. */ app_len = addr - TFTP_APP_ADDRESS + m_head->len; if (HAL_OK == debug_app_check(TFTP_APP_ADDRESS, app_len, 2)) { /* 保存信息并重启设备进入 IAP 升级 APP. */ dev_info_fireware_size_set(app_len); dev_info_magic_set(UPDATE_MAGIC); common_sys_set(COM_SYS_SAVE_INFO, 0); wl_ctrl.update_rt = HAL_OK; } wl_ctrl.state = WL_STATE_UPDATE_RT; wl_ctrl.mul_idx = 0; wl_ctrl.update_len = 0; } else { wl_ctrl.mul_idx = m_head->index + 1; wl_ctrl.update_len = m_head->len; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } else { wl_ctrl.mul_idx = m_head->index; wl_ctrl.update_len = m_head->len; wl_ctrl.state = WL_STATE_UPDATE; _wl_4G_update_send(); } return; } /* 设备信息获取报文处理. */ static void _wl_4G_update_rt_reply(void) { /* 有线设备需要回复报文后再休眠. */ if (DEV_TYPE_ACDC == dev_info.type_s) { _wl_4G_update_rt_send(); } if (wl_ctrl.update_rt != HAL_OK) { if (DEV_TYPE_CT_P == dev_info.type_s) { wl_ctrl.state = WL_STATE_POSITION; } else { wl_ctrl.state = WL_STATE_WAVE; } } else { /* 延迟 1s 等待串口回复报文发送完成. */ osDelay(1000); flash_log_write(FLASH_LOG_TYPE_INFO, "Update APP system sleep 0s!\r\n"); _wl_4G_hw_close(0); } wl_ctrl.is_update = 0; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } return; } /* 工频数据回复. */ static void _wl_4G_power_fre_reply(uint8_t *cmd, uint32_t len) { mul_head_t *m_head = (mul_head_t*)(cmd + sizeof(proto_head_t)); mul_head_t *m_head_send = (mul_head_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); if (m_head->len < DEBUG_DATA_SIZE) { wl_ctrl.state = WL_STATE_UPDATE; wl_ctrl.mul_idx = 0; ADC_ctrl.up_finish = TRUE; ADC_ctrl.is_ADC_thr = FALSE; } else { wl_ctrl.mul_idx = m_head->index; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } else { _wl_4G_power_fre_send(); /* 发送完成需要通知 ADC继续采集. */ if (m_head_send->len < DEBUG_DATA_SIZE) { wl_ctrl.mul_idx = 0; ADC_ctrl.up_finish = TRUE; ADC_ctrl.is_ADC_thr = FALSE; } } return; } /* 高频数据回复. */ static void _wl_4G_wave_reply(uint8_t *cmd, uint32_t len) { mul_head_t *m_head = (mul_head_t*)(cmd + sizeof(proto_head_t)); mul_head_t *m_head_send = (mul_head_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); if (m_head->len < DEBUG_DATA_SIZE) { wl_ctrl.state = WL_STATE_WAVE_MAX; st_data.wave_up_start = FALSE; st_data.wave_index = 0; } else { st_data.wave_index = m_head->index; } if (!ADC_ctrl.up_finish) { wl_ctrl.state = WL_STATE_WAKEUP; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); } else { /* 发送完成需要通知 ADC继续采集. */ if (m_head_send->len < DEBUG_DATA_SIZE) { st_data.wave_up_start = FALSE; st_data.wave_index = 0; } } return; } /* 高频数据回复. */ static void _wl_4G_wave_max_reply(uint8_t *cmd, uint32_t len) { wl_ctrl.state = WL_STATE_END; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; _wl_4G_pkt_id_update(); if (dev_info.type_s != DEV_TYPE_ACDC) { _wl_4G_pkt_id_update(); st_data.wave_max[0] = 0; st_data.wave_max[1] = 0; st_data.wave_max[2] = 0; st_data.wave_max[3] = 0; } else { _wl_4G_wave_max_send(); } st_write(&st_data); return; } /* 故障定位波形回复 */ static void _wl_4G_position_wave_reply(uint8_t *cmd, uint32_t len) { position_head_t *p_head = (position_head_t*)(cmd + sizeof(proto_head_t)); if (p_head->len < DEBUG_DATA_SIZE) { wl_ctrl.state = WL_STATE_END; wl_ctrl.wave_index = 0; } else { wl_ctrl.wave_index = p_head->index; } if (!ADC_ctrl.up_finish) { wl_ctrl.state = WL_STATE_WAKEUP; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; _wl_4G_pkt_id_update(); return; } /* 保活报文回复. */ static void _wl_4G_wave_keepalive_reply(void) { wl_ctrl.state = WL_STATE_END; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; _wl_4G_pkt_id_update(); return; } /* 数据回复处理. */ static void _wl_4G_data_process(uint8_t *cmd, uint32_t len) { proto_head_t *head= (proto_head_t*)cmd; /* 报文头和 CRC 校验. */ if (_wl_4G_pkt_check(cmd, len) != HAL_OK) { wl_ctrl.time_send = 0; return; } if (DEBUG_CT_REQUEST == head->cmd_type) { /* 共有命令处理. */ switch (head->cmd) { case DEBUG_C_DEV_INFO: _wl_4G_dev_info_reply(cmd, len); break; case DEBUG_C_UPDATE_APP: _wl_4G_update_reply(cmd, len); break; case DEBUG_C_UPDATE_APP_RT: _wl_4G_update_rt_reply(); break; case DEBUG_C_KEEPALIVE: _wl_4G_wave_keepalive_reply(); break; default: break; } } else if (DEBUG_CT_PRV_REQUEST == head->cmd_type) { /* 私有命令处理. */ switch (head->cmd) { case DEBUG_PRV_REAL_DATA: _wl_4G_pkt_reply(); break; case DEBUG_PRV_POWER_FRE: _wl_4G_power_fre_reply(cmd, len); break; case DEBUG_PRV_WAVE: _wl_4G_wave_reply(cmd, len); break; case DEBUG_PRV_WAVE_MAX: _wl_4G_wave_max_reply(cmd, len); break; case DEBUG_PRV_POSITION_WAVE: _wl_4G_position_wave_reply(cmd, len); break; default: break; } } } /* 发送数据过程中收数据回复. */ void _wl_4G_data_recv(void) { static uint8_t state = 0; static uint32_t time = 0; wl_buf_list_t *buf_l = &wl_buf_list_rx; proto_head_t *head = (proto_head_t*)wl_ctrl.cmd_buf; mul_head_t *m_head = (mul_head_t*)(wl_ctrl.cmd_buf + sizeof(proto_head_t)); uint8_t *buf = NULL; uint16_t len = 0; /* 超过 3s 没有收包说明收包超时, 重新开始收包. */ if (HAL_GetTick() - time > 3000) { wl_ctrl.cmd_buf_index = 0; state = 0; } time = HAL_GetTick(); /* 遍历所有有效的 buf. */ while(buf_l->current != buf_l->valid) { buf = buf_l->buf[buf_l->current]; len = buf_l->buf_cnt[buf_l->current]; /* 更新 buf index. */ buf_l->current++; if (WL_BUF_LIST_LEN == buf_l->current) { buf_l->current = 0; } /* 如果收包大于协议报文长度或者大于 buf 长度, 认为报文错误. */ if (wl_ctrl.cmd_buf_index + len > WL_DMA_RX_BUF_LEN || (wl_ctrl.cmd_buf_index >= 2 && (wl_ctrl.cmd_buf_index + len) > (head->len + WL_CRC32_LEN))) { wl_ctrl.cmd_buf_index = 0; state = 0; continue; } /* 将 buf 中的数据解析成命令. */ memcpy(&wl_ctrl.cmd_buf[wl_ctrl.cmd_buf_index], buf, len); wl_ctrl.cmd_buf_index += len; if (!state) { /* 报文长度不对, 重新收包. */ if (head->len + WL_CRC32_LEN > WL_DMA_RX_BUF_LEN) { wl_ctrl.cmd_buf_index = 0; continue; } /* 报文长度与收包长度不对称, 等待后续报文. */ if (wl_ctrl.cmd_buf_index < head->len + WL_CRC32_LEN) { state = TRUE; continue; } } else { /* 报文长度与收包长度不对称, 等待后续报文. */ if (wl_ctrl.cmd_buf_index < head->len + WL_CRC32_LEN) { continue; } state = FALSE; } DBG(DBG_M_4G, "Recv(%d): %d %d %d %d\r\n", wl_ctrl.cmd_buf_index, HAL_GetTick(), head->cmd_type, head->cmd, m_head->index); if (dbg_stat_get(DBG_M_4G)) { buf_print(wl_ctrl.cmd_buf, wl_ctrl.cmd_buf_index > 32 ? 32 : wl_ctrl.cmd_buf_index); vty_print("\r\n"); } if (DEV_TYPE_ACDC == dev_info.type_s) { _wir_data_process(wl_ctrl.cmd_buf, wl_ctrl.cmd_buf_index); } else { _wl_4G_data_process(wl_ctrl.cmd_buf, wl_ctrl.cmd_buf_index); } wl_ctrl.cmd_buf_index = 0; wl_ctrl.err_cnt = 0; } } /* 4G 模块发送数据. */ static HAL_StatusTypeDef _wl_4G_transmit(uint8_t *data, uint16_t len) { HAL_StatusTypeDef rv = HAL_ERROR; if (wl_ctrl.state < WL_STATE_WAKEUP) { DBG(DBG_M_4G, "Send: %s\r\n", data); } else { proto_head_t *head = (proto_head_t*)data; mul_head_t *m_head = (mul_head_t*)(data + sizeof(proto_head_t)); DBG(DBG_M_4G, "Send(%d): %d %d %d %d\r\n", len, HAL_GetTick(), head->cmd_type, head->cmd, m_head->index); if (dbg_stat_get(DBG_M_4G)) { buf_print(data, len > 32 ? 32 : len); vty_print("\r\n"); } /* 每次发送数据更新保活时间. */ wl_ctrl.keepalive = HAL_GetTick() + 60000; } /* 开启串口空闲中断收包. */ HAL_UARTEx_ReceiveToIdle_DMA(wl_uart, wl_ctrl.dma_rx_buf, WL_DMA_RX_BUF_LEN); HAL_GPIO_WritePin(RS485_B_DE_GPIO_Port, RS485_B_DE_Pin, GPIO_PIN_SET); rv = HAL_UART_Transmit_DMA(wl_uart, data, len); return rv; } /* 4G模块接收数据. */ void _wl_4G_receive(void) { if (wl_ctrl.state < WL_STATE_WAKEUP) { /* 初始化过程中收 AT 指令. */ _wl_4G_AT_recv(); } else { if (DEV_TYPE_CSG == dev_info.type_s) { /* 南网协议报文处理. */ _csg_pkt_recv(); } else { /* 发送数据过程中收数据回复. */ _wl_4G_data_recv(); } } } /* 初始化 4G 模块软件 */ static void _wl_4G_init_cmd_send(uint8_t *cmd, uint32_t timeout) { uint8_t len = strlen((char*)cmd); /* 复制并发送 AT 命令. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "%s", cmd); if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, len)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + timeout; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + WL_USART_ERR_TIMEOUT; } } /* 通过 AT 命令进行模块初始化. */ void _wl_4G_init_soft(void) { uint8_t is_timeout = wl_ctrl.time_send < HAL_GetTick(); if ((WL_STATE_SOFT == wl_ctrl.state) && is_timeout) { wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; wl_ctrl.state++; } else if ((WL_STATE_AT_ATE == wl_ctrl.state) && is_timeout) { /* 关闭 AT 回显. */ _wl_4G_init_cmd_send("ATE0\r\n", 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICSGP == wl_ctrl.state) && is_timeout) { /* 创建场景. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICSGP=1,1,\"%s\",\"\",\"\",1\r\n", dev_config.APN_long); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QIACT == wl_ctrl.state) && is_timeout) { /* 使能场景. */ _wl_4G_init_cmd_send("AT+QIACT=1\r\n", 33000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_CSQ == wl_ctrl.state) && is_timeout) { /* 读取网络信号质量. */ osDelay(5000); _wl_4G_init_cmd_send("AT+CSQ\r\n", 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICFGTS == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICFG=\"transpktsize\",1460\r\n"); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICFGWT == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICFG=\"transwaittm\",0\r\n"); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QIOPEN == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QIOPEN=1,0,\"TCP\",\"%d.%d.%d.%d\",%d,19421,2\r\n", dev_info.wireless_server_ip[0], dev_info.wireless_server_ip[1], dev_info.wireless_server_ip[2], dev_info.wireless_server_ip[3], dev_info.wireless_server_port); //_wl_4G_init_cmd_send("AT+QIOPEN=1,0,\"TCP\",\"111.47.21.142\",9467,19421,2\r\n", 10000); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if (WL_STATE_ADC_WAIT == wl_ctrl.state) { if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC)) { /* 软件初始化完成. */ if (DEV_TYPE_CT_P == dev_info.type_s) { wl_ctrl.state = WL_STATE_END; } else { wl_ctrl.state = WL_STATE_WAKEUP; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else if (is_timeout) { wl_ctrl.time_send = HAL_GetTick() + 10000; wl_ctrl.send_cnt++; } } } /* 初始化报文头. */ static void _wl_4G_data_head_init(uint16_t len, uint8_t cmdType, uint8_t cmd) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; /* 封装报文头. */ head->len = len; head->dev_type_m = dev_info.type_m; head->dev_type_s= dev_info.type_s; head->dev_id = *(uint32_t*)dev_info.id; head->cmd_type = cmdType; head->cmd = cmd; if (dev_info.type_s != DEV_TYPE_ACDC) { head->pkt_id = wl_ctrl.pkt_id; } } /* 设备唤醒, 发送配置和数据请求. */ static void _wl_4G_wakeup_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; wl_proto_wakeup_t *data = (wl_proto_wakeup_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint32_t *crc = NULL; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t) + sizeof(wl_proto_wakeup_t), DEBUG_CT_REPLY, DEBUG_C_DEV_INFO); /* 封装数据. */ memcpy(data, &dev_info.type_m, sizeof(wl_proto_wakeup_t) - DEV_NAME_LEN); memcpy(data->name, dev_config.host, DEV_NAME_LEN); /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文 */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 实时数据发送. */ static void _wl_4G_realdata_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; wl_proto_realdata_t *data = (wl_proto_realdata_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint32_t *crc = NULL; uint8_t i = 0; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t) + sizeof(wl_proto_realdata_t), DEBUG_CT_PRV_REPLY, DEBUG_PRV_REAL_DATA); /* 装填数据. */ data->temperature = ADC_ctrl.ADCi_temp; data->vbat = ADC_ctrl.ADCi_vbat; data->vin = ADC_ctrl.ADCi_vin; data->vsc = ADC_ctrl.ADCi_vsc; data->CSQ = wl_ctrl.CSQ; for(i = 0; i < CFG_ADC_CH_CNT; i++) { data->elec[i] = ADC_ctrl.ADC_elec[i]; } data->run_time = HAL_GetTick() / 1000; data->fre_valid = !ADC_ctrl.up_finish && ADC_ctrl.is_ADC_thr; /* 有线设备不用发送工频时, 需要重新触发工频采样. 需要发送工频时, 在发送完成后设置该标志位. */ if (!data->fre_valid && DEV_TYPE_ACDC == dev_info.type_s) { ADC_ctrl.up_finish = TRUE; } /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文. */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 工频采样数据获取报文发送. */ static void _wl_4G_power_fre_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; mul_head_t *m_head = (mul_head_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint8_t *data = (uint8_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t) + sizeof(mul_head_t)); int32_t data_len = 0; uint32_t *crc = NULL; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t), DEBUG_CT_PRV_REPLY, DEBUG_PRV_POWER_FRE); m_head->index = wl_ctrl.mul_idx; /* 填充数据, 计算数据长度和报文长度. */ data_len = ADC_COLLECT_CNT * 5 * 2 - m_head->index * DEBUG_DATA_SIZE; if (data_len < 0) { m_head->len = 0; } else if (data_len > DEBUG_DATA_SIZE) { m_head->len = DEBUG_DATA_SIZE; } else { m_head->len = data_len; } head->len = sizeof(proto_head_t) + sizeof(mul_head_t) + m_head->len; if (m_head->len > 0) { memcpy(data, (uint8_t*)(&ADC_ctrl.ADC_value_elec[0][0]) + m_head->index * DEBUG_DATA_SIZE, m_head->len); } /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文 */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } return; } /* 升级请求报文发送. */ static void _wl_4G_update_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; mul_head_t *m_head = (mul_head_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint32_t *crc = NULL; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t), DEBUG_CT_REPLY, DEBUG_C_UPDATE_APP); head->len = sizeof(proto_head_t) + sizeof(mul_head_t); m_head->index = wl_ctrl.mul_idx; m_head->len = wl_ctrl.update_len; /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文 */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } return; } /* 升级请求报文发送. */ static void _wl_4G_update_rt_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; int32_t *rt = (int32_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint32_t *crc = NULL; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t), DEBUG_CT_REPLY, DEBUG_C_UPDATE_APP_RT); head->len = sizeof(proto_head_t) + sizeof(int32_t); *rt = wl_ctrl.update_rt; /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文 */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } return; } /* 高频录波最大值数据发送. */ static void _wl_4G_wave_max_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; wl_proto_wave_max_t *data = (wl_proto_wave_max_t*)(wl_ctrl.dma_tx_buf + sizeof(proto_head_t)); uint32_t *crc = NULL; uint8_t i = 0; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t) + sizeof(wl_proto_wave_max_t), DEBUG_CT_PRV_REPLY, DEBUG_PRV_WAVE_MAX); /* 装填数据. */ for(i = 0; i < WAVE_SUM; i ++) { data->wave[i] = st_data.wave_max[i]; } /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文. */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 保活报文发送. */ static void _wl_4G_wave_keepalive_send(void) { proto_head_t *head = (proto_head_t*)wl_ctrl.dma_tx_buf; uint32_t *crc = NULL; /* 封装报文头. */ _wl_4G_data_head_init(sizeof(proto_head_t), DEBUG_CT_REPLY, DEBUG_C_KEEPALIVE); /* 计算校验和. */ crc = (uint32_t*)(wl_ctrl.dma_tx_buf + head->len); *crc = crc32(wl_ctrl.dma_tx_buf, head->len); /* 发送报文. */ if (HAL_OK == _wl_4G_transmit(wl_ctrl.dma_tx_buf, head->len + 4)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 传感器数据发送. */ void _wl_4G_data_send(void) { uint8_t is_timeout = wl_ctrl.time_send < HAL_GetTick(); /* 循环内只发送一次报文, 没有报文发送的情况下要跳出循环. */ while(is_timeout) { if (WL_STATE_WAKEUP == wl_ctrl.state) { /* 设备唤醒, 发送配置和数据请求. */ _wl_4G_wakeup_send(); wl_ctrl.send_cnt++; break; } else if (WL_STATE_REALDATA == wl_ctrl.state) { /* 实时数据报文. */ _wl_4G_realdata_send(); wl_ctrl.send_cnt++; break; } else if (WL_STATE_PWR_FRE == wl_ctrl.state) { /* 工频录波报文. */ if (!ADC_ctrl.up_finish && ADC_ctrl.is_ADC_thr) { _wl_4G_power_fre_send(); wl_ctrl.send_cnt++; break; } else { ADC_ctrl.up_finish = TRUE; ADC_ctrl.is_ADC_thr = FALSE; wl_ctrl.state = WL_STATE_UPDATE; wl_ctrl.mul_idx = 0; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } } else if (WL_STATE_UPDATE == wl_ctrl.state) { if (wl_ctrl.is_update) { _wl_4G_update_send(); wl_ctrl.send_cnt++; break; } else { if (DEV_TYPE_CT_P == dev_info.type_s) { wl_ctrl.state = WL_STATE_POSITION; } else { wl_ctrl.state = WL_STATE_WAVE; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } } else if (WL_STATE_UPDATE_RT == wl_ctrl.state) { if (wl_ctrl.is_update) { _wl_4G_update_rt_send(); wl_ctrl.send_cnt++; break; } else { if (DEV_TYPE_CT_P == dev_info.type_s) { wl_ctrl.state = WL_STATE_POSITION; } else { wl_ctrl.state = WL_STATE_WAVE; } wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } } else if (WL_STATE_WAVE == wl_ctrl.state) { /* 高频录波报文. */ if (!st_data.wave_start && st_data.wave_up_start) { wl_ctrl.send_cnt++; break; } else { wl_ctrl.state = WL_STATE_WAVE_MAX; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } } else if (WL_STATE_WAVE_MAX == wl_ctrl.state) { /* 高频最大值报文. */ if (st_data.wave_max[0] || st_data.wave_max[1] || st_data.wave_max[2] || st_data.wave_max[3]) { _wl_4G_wave_max_send(); wl_ctrl.send_cnt++; } else { wl_ctrl.state = WL_STATE_END; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } break; } else if (WL_STATE_POSITION == wl_ctrl.state) { wl_ctrl.state = WL_STATE_POSITION_WAVE; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else if (WL_STATE_POSITION_WAVE == wl_ctrl.state) { wl_ctrl.state = WL_STATE_END; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } if (WL_STATE_KEEPALIVE == wl_ctrl.state) { /* 设备保活报文发送. */ _wl_4G_wave_keepalive_send(); wl_ctrl.send_cnt++; break; } else { break; } } } /* 无线模块主任务循环. */ static void _wl_4G_start(void *argument) { uint32_t notify_value = 0; /* 等待完成 1 次 ADC 采样. */ while(1) { if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC)) { break; } osDelay(1000); } /* 开启串口空闲中断收包. */ HAL_UARTEx_ReceiveToIdle_DMA(wl_uart, wl_ctrl.dma_rx_buf, WL_DMA_RX_BUF_LEN); /* 初始化 4G 模块硬件. */ _wl_4G_hw_init(); /* 20s 内要收到 4G 模块发出的 RDY. */ wl_ctrl.time_send = HAL_GetTick() + 20000; wl_ctrl.wave_index = st_data.wave_index; for (;;) { /* AT 指令发送失败, 直接退出. */ if (wl_ctrl.send_cnt > WL_SOFT_INIT_ERR && wl_ctrl.state < WL_STATE_WAKEUP) { //flash_log_write(FLASH_LOG_TYPE_INFO, "4G module is ERROR system sleep %ds!\r\n", dev_config.collect_interval * 60); //_wl_4G_hw_close(dev_config.collect_interval * 60); _wl_4G_hw_restart(); } /* 数据发送失败, 重启 4G 模块 1 次. */ if (wl_ctrl.send_cnt > WL_DATA_ERR && wl_ctrl.state >= WL_STATE_WAKEUP) { _wl_4G_hw_restart(); } if (wl_ctrl.state < WL_STATE_WAKEUP) { /* 进入软件初始化. */ _wl_4G_init_soft(); } else if (wl_ctrl.state != WL_STATE_END) { /* 进入数据交互模式. */ _wl_4G_data_send(); } else { /* 当状态为 WL_STATE_END 时, 先判断节能模式. */ if ((dev_config.normal_sleep && DEV_TYPE_CT_P != dev_info.type_s) || DEV_TYPE_BAT == dev_info.type_s) { if(DEV_TYPE_BAT == dev_info.type_s && st_data.wave_start && dev_config.is_wave_col != 0 && ADC_ctrl.ADCi_vbat >= 3600) { if (!st_data.wave_start && st_data.wave_up_start) { wl_ctrl.state = WL_STATE_WAVE; } } else { flash_log_write(FLASH_LOG_TYPE_INFO, "System sleep %ds!\r\n", dev_config.collect_interval * 60 - 30); _wl_4G_hw_close(dev_config.collect_interval * 60 - 30); } } else if (!ADC_ctrl.up_finish) { wl_ctrl.state = WL_STATE_WAKEUP; } else if(!st_data.wave_start && st_data.wave_up_start) { wl_ctrl.state = WL_STATE_WAVE; } else if(wl_ctrl.keepalive < HAL_GetTick()) { wl_ctrl.state = WL_STATE_KEEPALIVE; /* 每次发送数据更新保活时间. */ wl_ctrl.keepalive = HAL_GetTick() + 60000; } } /* 喂狗. */ common_watchdog_set(COM_WDG_WIR); /* 等待 DMA 收包中断. */ notify_value = ulTaskNotifyTake(pdTRUE, WL_RX_TIMEOUT); /* 收包超时, 返回循环头部. */ if (0 == notify_value) { continue; } /* 收包处理. */ _wl_4G_receive(); } } /* 有线数据处理. */ static void _wir_data_process(uint8_t *cmd, uint32_t len) { proto_head_t *head = (proto_head_t*)cmd; /* 报文头和 CRC 校验. */ if (_wl_4G_pkt_check(cmd, len) != HAL_OK) { return; } if (DEBUG_CT_REQUEST == head->cmd_type) { /* 共有命令处理. */ switch (head->cmd) { case DEBUG_C_DEV_INFO: _wl_4G_dev_info_reply(cmd, len); break; case DEBUG_C_UPDATE_APP: _wl_4G_update_reply(cmd, len); break; case DEBUG_C_UPDATE_APP_RT: _wl_4G_update_rt_reply(); break; default: break; } } else if (DEBUG_CT_PRV_REQUEST == head->cmd_type) { /* 私有命令处理. */ switch (head->cmd) { case DEBUG_PRV_REAL_DATA: _wl_4G_pkt_reply(); break; case DEBUG_PRV_POWER_FRE: _wl_4G_power_fre_reply(cmd, len); break; case DEBUG_PRV_WAVE: _wl_4G_wave_reply(cmd, len); break; case DEBUG_PRV_WAVE_MAX: _wl_4G_wave_max_reply(cmd, len); break; default: break; } } } /* 有线模式主任务循环. */ static void _wir_start(void *argument) { uint32_t notify_value = 0; /* RS485 供电打开. */ HAL_GPIO_WritePin(POWER_4G_GPIO_Port, POWER_4G_Pin, GPIO_PIN_SET); /* 开启串口空闲中断收包. */ HAL_UARTEx_ReceiveToIdle_DMA(wl_uart, wl_ctrl.dma_rx_buf, WL_DMA_RX_BUF_LEN); for (;;) { /* 喂狗. */ common_watchdog_set(COM_WDG_WIR); /* 等待 DMA 收包中断. */ notify_value = ulTaskNotifyTake(pdTRUE, WIR_RX_TIMEOUT); /* 收包超时, 返回循环头部. */ if (0 == notify_value) { continue; } /* 收包处理. */ _wl_4G_data_recv(); } } /* 4G 模块发送数据. */ static HAL_StatusTypeDef _csg_transmit(uint8_t *data, uint16_t len) { HAL_StatusTypeDef rv = HAL_ERROR; if (wl_ctrl.state < WL_STATE_WAKEUP) { DBG(DBG_M_4G, "Send: %s\r\n", data); } else { csg_head_t *head = (csg_head_t*)data; DBG(DBG_M_4G, "Send(%d): 0x%x\r\n", len, head->cmd); if (dbg_stat_get(DBG_M_4G)) { buf_print(data, len > 32 ? 32 : len); //buf_print(data, len); vty_print("\r\n"); } /* 每次发送数据更新保活时间. */ wl_ctrl.keepalive = HAL_GetTick() + 60000; } rv = HAL_UART_Transmit_DMA(wl_uart, data, len); return rv; } static uint8_t _csg_crc(uint8_t *data, uint16_t len) { uint8_t crc = 0x00; uint32_t sum = 0x0000; uint16_t i = 0; for(i = 0; i < len; i++) { sum += data[i]; } crc = ~(uint8_t)(sum); return crc; } /* 初始化报文头. */ static void _csg_data_head_init(uint16_t len, uint8_t cmd) { csg_head_t *head = (csg_head_t*)wl_ctrl.dma_tx_buf; /* 封装报文头. */ head->flag = CSG_START_FLAG; memcpy(head->dev_id, dev_info.csg_id, 6); head->cmd = cmd; head->len = PP_HTONS(len); } /* 错误回复报文. */ static void _csg_error_send(uint8_t cmd, uint16_t rt) { uint16_t *data = (uint16_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_ERROR_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_ERROR_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_ERROR_LEN, cmd); /* 封装数据. */ *data = PP_HTONS(rt); /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_ERROR_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ _csg_transmit(wl_ctrl.dma_tx_buf, CSG_ERROR_LEN + CSG_OTHER_LEN); } /* 开机联络报文. */ static void _csg_connect_send(uint8_t is_request) { uint16_t *data = (uint16_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_CONNECT_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_CONNECT_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_CONNECT_LEN, CSG_CONNECT); /* 封装数据. */ *data = PP_HTONS(dev_info.csg_version); /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_CONNECT_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ if (is_request) { _csg_transmit(wl_ctrl.dma_tx_buf, CSG_CONNECT_LEN + CSG_OTHER_LEN); } else { if (HAL_OK == _csg_transmit(wl_ctrl.dma_tx_buf, CSG_CONNECT_LEN + CSG_OTHER_LEN)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } } /* 对时报文. */ static void _csg_time_send(void) { uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_TIMING_LEN, CSG_TIMING); /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ if (HAL_OK == _csg_transmit(wl_ctrl.dma_tx_buf, CSG_OTHER_LEN)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 实时数据报文. */ static void _csg_data_send_his(void) { struct tm *day = NULL; csg_data_t *data = (csg_data_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_DATA_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_DATA_LEN + CSG_CRC_LEN); uint8_t i = 0; uint16_t temp = 0; uint32_t time = 0; /* 封装报文头. */ _csg_data_head_init(CSG_DATA_LEN, CSG_DATA); /* 封装数据. */ memcpy(data->Ciphertext, dev_config.csg_ciphertext, CSG_CIPHERTEXT_LEN); data->flag = 0; data->sum = 0; csg_adc_data.id = fd_id; for(i = 0; i < CSG_PKT_DATA_SUM; i++) { if (fd_read(csg_adc_data.id, &csg_adc_data) != HAL_OK) break; /* 读到全F,表示结束了. */ if (FD_INVALID_ID == csg_adc_data.id) break; /* 只要历史数据. */ if (!csg_adc_data.is_not_updata) { csg_adc_data.id--; if (0 == csg_adc_data.id) { break; } continue; } csg_data_idx[data->sum] = csg_adc_data.id; data->sum++; csg_data_idx[data->sum] = 0; vty_print("%d %d\r\n", data->sum, csg_adc_data.id); vty_print("%d/%d/%d %d:%d:%d\r\n", data->time[0], data->time[1], data->time[2], data->time[3], data->time[4], data->time[5]); time = csg_adc_data.run_time + 28800; day = localtime(&time); data->time[0] = day->tm_year - 100; data->time[1] = day->tm_mon + 1; data->time[2] = day->tm_mday; data->time[3] = day->tm_hour; data->time[4] = day->tm_min; data->time[5] = day->tm_sec; temp = csg_adc_data.elec[0] / 100; data->Ia = PP_HTONS(temp); temp = csg_adc_data.elec[1] / 100; data->Ib = PP_HTONS(temp); temp = csg_adc_data.elec[2] / 100; data->Ic = PP_HTONS(temp); temp = csg_adc_data.elec[3] / 100; data->ground = PP_HTONS(temp); temp = csg_adc_data.elec[4] / 100; data->rIa = PP_HTONS(temp); data->rIb = 0; data->rIc = 0; break; } if (0 == data->sum) { wl_ctrl.state = CSG_STATE_IDLE; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else { /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_DATA_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ if (HAL_OK == _csg_transmit(wl_ctrl.dma_tx_buf, CSG_DATA_LEN + CSG_OTHER_LEN)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } } /* 实时数据上传. */ static void _csg_data_send_realtime(void) { struct tm *day = NULL; csg_data_t *data = (csg_data_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_DATA_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_DATA_LEN + CSG_CRC_LEN); uint16_t temp = 0; uint32_t time = 0; /* 封装报文头. */ _csg_data_head_init(CSG_DATA_LEN, CSG_DATA); /* 封装数据. */ memcpy(data->Ciphertext, dev_config.csg_ciphertext, CSG_CIPHERTEXT_LEN); data->flag = 0x00; data->sum = 0x01; fd_read(fd_id, &csg_adc_data); csg_data_idx[0] = fd_id; csg_data_idx[1] = 0; time = csg_adc_data.run_time + 28800; day = localtime(&time); data->time[0] = day->tm_year - 100; data->time[1] = day->tm_mon + 1; data->time[2] = day->tm_mday; data->time[3] = day->tm_hour; data->time[4] = day->tm_min; data->time[5] = day->tm_sec; vty_print("%d/%d/%d %d:%d:%d\r\n", data->time[0], data->time[1], data->time[2], data->time[3], data->time[4], data->time[5]); temp = csg_adc_data.elec[0] / 100; data->Ia = PP_HTONS(temp); temp = csg_adc_data.elec[1] / 100; data->Ib = PP_HTONS(temp); temp = csg_adc_data.elec[2] / 100; data->Ic = PP_HTONS(temp); temp = csg_adc_data.elec[3] / 100; data->ground = PP_HTONS(temp); temp = csg_adc_data.elec[4] / 100; data->rIa = PP_HTONS(temp); data->rIb = 0; data->rIc = 0; /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_DATA_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ if (HAL_OK == _csg_transmit(wl_ctrl.dma_tx_buf, CSG_DATA_LEN + CSG_OTHER_LEN)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } } /* 心跳报文. */ static void _csg_beat_send(void) { csg_beat_t *data = (csg_beat_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_BEAT_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_BEAT_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_BEAT_LEN, CSG_BEAT); /* 封装数据. */ HAL_RTC_GetTime(&hrtc, &time_structure, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &date_structure, RTC_FORMAT_BIN); data->time[0] = date_structure.Year; data->time[1] = date_structure.Month; data->time[2] = date_structure.Date; data->time[3] = time_structure.Hours; data->time[4] = time_structure.Minutes; data->time[5] = time_structure.Seconds; data->CSQ = (wl_ctrl.CSQ + 115) * 100 / 64; data->vbat = ADC_ctrl.ADCi_vbat / 100; /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_BEAT_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ if (HAL_OK == _csg_transmit(wl_ctrl.dma_tx_buf, CSG_BEAT_LEN + CSG_OTHER_LEN)) { /* 发送成功, 如果指定时间内没有收到回复, 则根据 timeout 时间重发. */ wl_ctrl.time_send = HAL_GetTick() + 5500; } else { /* 发送失败, 等待 1s 重发. */ wl_ctrl.time_send = HAL_GetTick() + 1100; } wl_ctrl.time_beat = HAL_GetTick(); } /* 服务器信息报文发送. */ static void _csg_server_send(void) { csg_server_get_t *data = (csg_server_get_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_SERVER_GET_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_SERVER_GET_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_SERVER_GET_LEN, CSG_SERVER_GET); /* 封装数据. */ memcpy(data->ip, dev_info.wireless_server_ip, 4); data->port = PP_HTONS(dev_info.wireless_server_port); memcpy(data->card, dev_info.csg_card, 6); /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_SERVER_GET_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ _csg_transmit(wl_ctrl.dma_tx_buf, CSG_SERVER_GET_LEN + CSG_OTHER_LEN); } /* 配饰获取报文发送. */ static void _csg_config_send(void) { uint8_t *data = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_CONFIG_GET_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_CONFIG_GET_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_CONFIG_GET_LEN, CSG_CONFIG_GET); /* 封装数据. */ /* 心跳间隔. */ *data = dev_config.csg_beat_interval; data += 1; /* 采集间隔. */ *(uint16_t*)data = PP_HTONS(dev_config.collect_interval); data += 2; /* 休眠时间. */ *(uint16_t*)data = PP_HTONS(dev_config.csg_sleep); data += 2; /* 在线时间. */ *(uint16_t*)data = PP_HTONS(HAL_GetTick() / 1000 / 60); data += 2; /* 重启时间. */ memcpy(data, dev_config.csg_reset_time, 3); data += 3; memset(data, 0, 10); data += 10; *data = 0x44; /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_CONFIG_GET_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ _csg_transmit(wl_ctrl.dma_tx_buf, CSG_CONFIG_GET_LEN + CSG_OTHER_LEN); } /* 时间获取报文. */ static void _csg_time_get_send(void) { uint8_t *data = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN); uint8_t *crc = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_TIME_GET_LEN); uint8_t *end_flag = (uint8_t*)(wl_ctrl.dma_tx_buf + CSG_HEAD_LEN + CSG_TIME_GET_LEN + CSG_CRC_LEN); /* 封装报文头. */ _csg_data_head_init(CSG_TIME_GET_LEN, CSG_TIME_GET); /* 封装数据. */ HAL_RTC_GetTime(&hrtc, &time_structure, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &date_structure, RTC_FORMAT_BIN); data[0] = date_structure.Year; data[1] = date_structure.Month; data[2] = date_structure.Date; data[3] = time_structure.Hours; data[4] = time_structure.Minutes; data[5] = time_structure.Seconds; /* 计算校验和. */ *crc = _csg_crc(wl_ctrl.dma_tx_buf + 1, CSG_TIME_GET_LEN + CSG_HEAD_LEN - 1); *end_flag = CSG_END_FLAG; /* 发送报文 */ _csg_transmit(wl_ctrl.dma_tx_buf, CSG_TIME_GET_LEN + CSG_OTHER_LEN); } /* 状态机改变 */ void _csg_state_change(void) { if (wl_ctrl.state != CSG_STATE_IDLE) { return; } if (wl_ctrl.data_request) { if (CSG_DATA_TYPE_HIS == wl_ctrl.data_request) { wl_ctrl.state = CSG_STATE_DATA_HIS; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; } wl_ctrl.data_request = CSG_DATA_TYPE_NONE; } else if ((HAL_GetTick() - wl_ctrl.time_beat) > (dev_config.csg_beat_interval * 60000)) { wl_ctrl.state = CSG_STATE_BEAT; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; } else if (!ADC_ctrl.up_finish) { wl_ctrl.state = CSG_STATE_DATA; ADC_ctrl.up_finish = TRUE; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; } } /* 数据发送. */ void _csg_pkt_send(void) { uint8_t is_timeout = wl_ctrl.time_send < HAL_GetTick(); _csg_state_change(); if ((CSG_STATE_CONNECT == wl_ctrl.state) && is_timeout) { /* 开机联络. */ _csg_connect_send(FALSE); wl_ctrl.send_cnt++; } else if ((CSG_STATE_TIME == wl_ctrl.state) && is_timeout) { /* 设备对时. */ _csg_time_send(); wl_ctrl.send_cnt++; } else if ((CSG_STATE_BEAT == wl_ctrl.state) && is_timeout) { /* 心跳. */ _csg_beat_send(); wl_ctrl.send_cnt++; } else if ((CSG_STATE_DATA == wl_ctrl.state) && is_timeout) { /* 实时数据. */ _csg_data_send_realtime(); wl_ctrl.send_cnt++; } else if ((CSG_STATE_DATA_HIS == wl_ctrl.state) && is_timeout) { /* 历史数据. */ _csg_data_send_his(); wl_ctrl.send_cnt++; } } static int32_t _csg_pkt_check(uint8_t *cmd, uint32_t len) { csg_head_t *head = (csg_head_t*)cmd; /* 设备进入复位状态后不再处理报文. */ if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_RESET)) { vty_print("@0\r\n"); /* 这里挂住线程是因为重启时如果有收包, 会导致收包出错, 从而让设备进入休眠状态. */ osDelay(portMAX_DELAY); return HAL_ERROR; } if (len < CSG_OTHER_LEN || (CSG_OTHER_LEN + PP_HTONS(head->len) != len)) { vty_print("@1\r\n"); return HAL_ERROR; } if (head->flag != CSG_START_FLAG || cmd[len - 1] != CSG_END_FLAG) { vty_print("@2\r\n"); return HAL_ERROR; } /* 对主次设备号进行识别, 次设备号可以是广播. */ if (strncmp((char*)head->dev_id, (char*)dev_info.csg_id, 6)) { vty_print("@3\r\n"); return HAL_ERROR; } /* 验证 CRC32. */ if (_csg_crc(cmd + 1, PP_HTONS(head->len) + CSG_HEAD_LEN - 1) != cmd[len - 2]) { vty_print("@4: %x %x\r\n", _csg_crc(cmd + 1, PP_HTONS(head->len) + CSG_HEAD_LEN - 1), cmd[len - 2]); return HAL_ERROR; } return HAL_OK; } /* 开机联络回复. */ static void _csg_connect_reply(uint8_t *cmd, uint32_t len) { csg_head_t *head = (csg_head_t*)cmd; if (PP_HTONS(head->len) == 0) { _csg_connect_send(TRUE); } else { wl_ctrl.state = CSG_STATE_TIME; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; } } /* 对时回复. */ static void _csg_time_reply(uint8_t *cmd, uint32_t len) { csg_time_t *data = (csg_time_t*)(cmd + CSG_HEAD_LEN); time_t temp = 0; /* 更新 RTC 时间. */ tm_structure.tm_year = data->year + 100; tm_structure.tm_mon = data->mon - 1; tm_structure.tm_mday = data->day; tm_structure.tm_hour = data->hour; tm_structure.tm_min = data->min; tm_structure.tm_sec = data->sec; temp = mktime(&tm_structure); rtc_time_set(temp - 28800); if (CSG_STATE_TIME == wl_ctrl.state) { wl_ctrl.state = CSG_STATE_BEAT; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; } else { /* 发送回复报文. */ _csg_transmit(cmd, len); } } /* 对时回复. */ static void _csg_passwd_set_reply(uint8_t *cmd, uint32_t len) { csg_passwd_t *data = (csg_passwd_t*)(cmd + CSG_HEAD_LEN); if (0 == memcmp(data->passwd_old, dev_config.csg_passwd, CSG_PASSWD_LEN)) { memcpy(dev_config.csg_passwd, data->passwd_new, CSG_PASSWD_LEN); dev_config.csg_passwd[CSG_PASSWD_LEN] = 0; common_sys_set(COM_SYS_SAVE_CONFIG, 0); /* 发送回复报文. */ _csg_transmit(cmd, len); } else { _csg_error_send(CSG_PASSWD_SET, 0xffff); } } /* 配置设置回复. */ static void _csg_config_set_reply(uint8_t *cmd, uint32_t len) { uint8_t *data = (uint8_t*)(cmd + CSG_HEAD_LEN); if (0 == memcmp(data, dev_config.csg_passwd, CSG_PASSWD_LEN)) { /* 心跳间隔. */ data += 4; dev_config.csg_beat_interval = *data; /* 采集间隔. */ data += 1; dev_config.collect_interval = *(uint16_t*)data; dev_config.collect_interval = PP_HTONS(dev_config.collect_interval); /* 休眠时间. */ data += 2; dev_config.csg_sleep = *(uint16_t*)data; dev_config.csg_sleep = PP_HTONS(dev_config.csg_sleep); /* 在线时间. */ data += 2; dev_config.csg_online = *(uint16_t*)data; dev_config.csg_online = PP_HTONS(dev_config.csg_online); /* 重启时间. */ data += 2; memcpy(dev_config.csg_reset_time, data, 3); /* 验证密文. */ data += 3; memcpy(dev_config.csg_ciphertext, data, 4); common_sys_set(COM_SYS_SAVE_CONFIG, 0); /* 发送回复报文. */ _csg_transmit(cmd, len); } else { _csg_error_send(CSG_CONFIG_SET, 0xffff); } } /* 心跳回复处理. */ static void _csg_beat_reply(uint8_t *cmd, uint32_t len) { wl_ctrl.state = CSG_STATE_IDLE; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } /* 服务器设置回复. */ static void _csg_server_set_reply(uint8_t *cmd, uint32_t len) { csg_server_t *data = (csg_server_t*)(cmd + CSG_HEAD_LEN); if (0 == memcmp(data->passwd, dev_config.csg_passwd, CSG_PASSWD_LEN)) { if (0 == memcmp(data->ip1, data->ip2, CSG_PASSWD_LEN) && 0 == memcmp(data->card1, data->card2, 6) && data->port1 == data->port2) { memcpy(dev_info.wireless_server_ip, data->ip1, 4); dev_info.wireless_server_port = PP_HTONS(data->port1); memcpy(dev_info.csg_card, data->card1, 6); common_sys_set(COM_SYS_SAVE_INFO, 0); /* 发送回复报文. */ _csg_transmit(cmd, len); } else { _csg_error_send(CSG_SERVER_SET, 0); } } else { _csg_error_send(CSG_SERVER_SET, 0xffff); } } /* 服务器设置回复. */ static void _csg_server_get_reply(uint8_t *cmd, uint32_t len) { _csg_server_send(); } /* 设备重启回复. */ static void _csg_reset_reply(uint8_t *cmd, uint32_t len) { uint8_t *data = (uint8_t*)(cmd + CSG_HEAD_LEN); uint32_t reset_delay = 2; if (0 == memcmp(data, dev_config.csg_passwd, CSG_PASSWD_LEN)) { /* 发送回复报文. */ _csg_transmit(cmd, len); flash_log_write(FLASH_LOG_TYPE_INFO, "CSG system reset!\r\n"); common_sys_set(COM_SYS_RESET, (void*)&reset_delay); } else { _csg_error_send(CSG_RESET, 0xffff); } } /* 服务器设置回复. */ static void _csg_config_get_reply(uint8_t *cmd, uint32_t len) { _csg_config_send(); } /* 服务器设置回复. */ static void _csg_time_get_reply(uint8_t *cmd, uint32_t len) { _csg_time_get_send(); } /* 数据回复处理. */ static void _csg_data_get_reply(uint8_t *cmd, uint32_t len) { csg_head_t *head = (csg_head_t*)cmd; if (PP_HTONS(head->len) == 0) { /* 请求历史数据. */ wl_ctrl.data_request = CSG_DATA_TYPE_HIS; } else { /* 请求实时数据. */ wl_ctrl.data_request = CSG_DATA_TYPE_REAL; } _csg_transmit(cmd, len); } static void _csg_data_reply_id_updata(void) { uint8_t i = 0; for(i = 0; i < CSG_PKT_DATA_SUM; i++) { if (0 == csg_data_idx[i]) { break; } fd_read(csg_data_idx[i], &csg_adc_data); csg_adc_data.is_not_updata = FALSE; fd_modify(csg_data_idx[i], &csg_adc_data); } } /* 数据回复处理. */ static void _csg_data_reply(uint8_t *cmd, uint32_t len) { csg_head_t *head = (csg_head_t*)cmd; if (PP_HTONS(head->len) == 0) { _csg_transmit(cmd, len); } else { wl_ctrl.state = CSG_STATE_IDLE; wl_ctrl.send_cnt = 0; wl_ctrl.time_send = 0; _csg_data_reply_id_updata(); } } /* 有线数据处理. */ static void _csgp_pkt_process(uint8_t *cmd, uint32_t len) { csg_head_t *head = (csg_head_t*)cmd; /* 报文头和 CRC 校验. */ if (_csg_pkt_check(cmd, len) != HAL_OK) { return; } /* 共有命令处理. */ switch (head->cmd) { case CSG_CONNECT: _csg_connect_reply(cmd, len); break; case CSG_TIMING: _csg_time_reply(cmd, len); break; case CSG_PASSWD_SET: _csg_passwd_set_reply(cmd, len); break; case CSG_CONFIG_SET: _csg_config_set_reply(cmd, len); break; case CSG_BEAT: _csg_beat_reply(cmd, len); break; case CSG_SERVER_SET: _csg_server_set_reply(cmd, len); break; case CSG_SERVER_GET: _csg_server_get_reply(cmd, len); break; case CSG_RESET: _csg_reset_reply(cmd, len); break; case CSG_CONFIG_GET: _csg_config_get_reply(cmd, len); break; case CSG_TIME_GET: _csg_time_get_reply(cmd, len); break; case CSG_DATA_GET: _csg_data_get_reply(cmd, len); break; case CSG_DATA: _csg_data_reply(cmd, len); break; default: break; } } static void _csg_pkt_recv(void) { static uint8_t state = 0; static uint32_t time = 0; wl_buf_list_t *buf_l = &wl_buf_list_rx; csg_head_t *head = (csg_head_t*)wl_ctrl.cmd_buf; uint8_t *buf = NULL; uint16_t len = 0; int16_t i = 0; /* 超过 3s 没有收包说明收包超时, 重新开始收包. */ if (HAL_GetTick() - time > 3000) { state = 0; wl_ctrl.cmd_buf_index = 0; } time = HAL_GetTick(); /* 遍历所有有效的 buf. */ while(buf_l->current != buf_l->valid) { buf = buf_l->buf[buf_l->current]; len = buf_l->buf_cnt[buf_l->current]; /* 更新 buf index. */ buf_l->current++; if (WL_BUF_LIST_LEN == buf_l->current) { buf_l->current = 0; } /* 如果收包大于 buf 长度, 认为报文错误. */ if (wl_ctrl.cmd_buf_index + len >= WL_DMA_RX_BUF_LEN) { wl_ctrl.cmd_buf_index = 0; state = FALSE; continue; } /* 将 buf 中的数据解析成命令. */ memcpy(&wl_ctrl.cmd_buf[wl_ctrl.cmd_buf_index], buf, len); wl_ctrl.cmd_buf_index += len; /* 不够报文头长度的报文暂时不处理. */ if (wl_ctrl.cmd_buf_index < CSG_HEAD_LEN) { state = FALSE; continue; } if (!state) { /* 报文长度不对或者起始位不对, 重新收包. */ if (PP_HTONS(head->len) + CSG_OTHER_LEN > WL_DMA_RX_BUF_LEN || head->flag != CSG_START_FLAG) { wl_ctrl.cmd_buf_index = 0; continue; } /* 报文长度与收包长度不对称, 等待后续报文. */ if (wl_ctrl.cmd_buf_index < PP_HTONS(head->len) + CSG_OTHER_LEN) { state = TRUE; continue; } } else { /* 报文长度与收包长度不对称, 等待后续报文. */ if (wl_ctrl.cmd_buf_index < PP_HTONS(head->len) + CSG_OTHER_LEN) { continue; } state = FALSE; } len = PP_HTONS(head->len) + CSG_OTHER_LEN; wl_ctrl.cmd_buf_index -= len; buf = wl_ctrl.cmd_buf + len; memcpy(wl_ctrl.csg_buf, wl_ctrl.cmd_buf, len); for(i = 0; i < wl_ctrl.cmd_buf_index; i++) { wl_ctrl.cmd_buf[i] = buf[i]; } DBG(DBG_M_4G, "Recv(%d:%d): 0x%x\r\n", len, wl_ctrl.cmd_buf_index, wl_ctrl.csg_buf[7]); if (dbg_stat_get(DBG_M_4G)) { buf_print(wl_ctrl.csg_buf, len > 32 ? 32 : len); vty_print("\r\n"); } _csgp_pkt_process(wl_ctrl.csg_buf, len); } } /* 通过 AT 命令进行模块初始化. */ void _csg_init_soft(void) { uint8_t is_timeout = wl_ctrl.time_send < HAL_GetTick(); if ((WL_STATE_SOFT == wl_ctrl.state) && is_timeout) { wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; wl_ctrl.state++; } else if ((WL_STATE_AT_ATE == wl_ctrl.state) && is_timeout) { /* 关闭 AT 回显. */ _wl_4G_init_cmd_send("ATE0\r\n", 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICSGP == wl_ctrl.state) && is_timeout) { /* 创建场景. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICSGP=1,1,\"%s\",\"\",\"\",1\r\n", dev_config.APN_long); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QIACT == wl_ctrl.state) && is_timeout) { /* 使能场景. */ _wl_4G_init_cmd_send("AT+QIACT=1\r\n", 33000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_CSQ == wl_ctrl.state) && is_timeout) { /* 读取网络信号质量. */ osDelay(5000); _wl_4G_init_cmd_send("AT+CSQ\r\n", 1100); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICFGTS == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICFG=\"transpktsize\",1460\r\n"); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QICFGWT == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QICFG=\"transwaittm\",0\r\n"); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if ((WL_STATE_AT_QIOPEN == wl_ctrl.state) && is_timeout) { /* 连接远程服务器. */ snprintf((char*)wl_ctrl.dma_tx_buf, WL_DMA_TX_BUF_LEN, "AT+QIOPEN=1,0,\"UDP\",\"%d.%d.%d.%d\",%d,19421,2\r\n", dev_info.wireless_server_ip[0], dev_info.wireless_server_ip[1], dev_info.wireless_server_ip[2], dev_info.wireless_server_ip[3], dev_info.wireless_server_port); //_wl_4G_init_cmd_send("AT+QIOPEN=1,0,\"TCP\",\"111.47.21.142\",9467,19421,2\r\n", 10000); _wl_4G_init_cmd_send(wl_ctrl.dma_tx_buf, 11000); wl_ctrl.send_cnt++; } else if (WL_STATE_ADC_WAIT == wl_ctrl.state) { if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC)) { /* 软件初始化完成. */ wl_ctrl.state = CSG_STATE_CONNECT; wl_ctrl.time_send = 0; wl_ctrl.send_cnt = 0; } else if (is_timeout) { wl_ctrl.time_send = HAL_GetTick() + 10000; wl_ctrl.send_cnt++; } } } static void _csg_start(void *argument) { uint32_t notify_value = 0; /* 等待完成 1 次 ADC 采样. */ while(1) { if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC)) { break; } osDelay(1000); } /* 开启串口空闲中断收包. */ HAL_UARTEx_ReceiveToIdle_DMA(wl_uart, wl_ctrl.dma_rx_buf, WL_DMA_RX_BUF_LEN); /* 初始化 4G 模块硬件. */ _wl_4G_hw_init(); /* 20s 内要收到 4G 模块发出的 RDY. */ wl_ctrl.time_send = HAL_GetTick() + 20000; wl_ctrl.wave_index = st_data.wave_index; for (;;) { /* AT 指令发送失败, 直接退出. */ if (wl_ctrl.send_cnt > WL_SOFT_INIT_ERR) { wl_ctrl.err_cnt = 0; _wl_4G_hw_restart(); } if (wl_ctrl.state < WL_STATE_WAKEUP) { /* 进入软件初始化. */ _csg_init_soft(); } else { /* 发送数据给 */ _csg_pkt_send(); } /* 喂狗. */ common_watchdog_set(COM_WDG_WIR); /* 等待 DMA 收包中断. */ notify_value = ulTaskNotifyTake(pdTRUE, WL_RX_TIMEOUT); /* 收包超时, 返回循环头部. */ if (0 == notify_value) { continue; } /* 收包处理. */ _wl_4G_receive(); } } /* Interface functions -------------------------------------------------------*/ /* 无线通讯任务初始化. */ void wl_init(void) { if (DEV_TYPE_CSG == dev_info.type_s) { WLHandle = osThreadNew(_csg_start, NULL, &WL_attributes); } else if (DEV_TYPE_ACDC == dev_info.type_s) { WLHandle = osThreadNew(_wir_start, NULL, &WL_attributes); } else { WLHandle = osThreadNew(_wl_4G_start, NULL, &WL_attributes); } } void wl_show(void) { vty_print("ST\r\n"); vty_print("%-03d %d\r\n\n", wl_ctrl.state, wl_ctrl.send_cnt); } /******************* (C) COPYRIGHT LandPower ***** END OF FILE ****************/