/******************************************************************************
* 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 ****************/