You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1474 lines
47 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*****************************************************************************
* file lib/process/ca_dbg.c
* author YuLiang
* version 1.0.0
* date 30-Nov-2023
* brief This file provides all the debug server related operation functions.
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT(c) 2023 LandPower</center></h2>
*
* 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 LandPower 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 ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef CFG_DEV_TYPE_LAND_CA
/* 标准C库头文件. */
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/stat.h>
/* 用户代码头文件. */
#include "cmd.h"
#include "mtimer.h"
#include "process.h"
#include "ca_db.h"
#include "ca_collect.h"
#include "ca_mqtt.h"
#include "ca_land.h"
/* Private define ------------------------------------------------------------*/
#define CA_DBG_TOOL_PORT 20111
#define CA_DBG_BUF_SIZE 1512
#define CA_DBG_CMD_BUF_LEN 3024
#define CA_DBG_CRC32_LEN 4
#define CA_DBG_VERSION_LEN 32
#define CA_DBG_COMPILE_LEN 32
#define CA_DBG_NAME_LEN 128
#define CA_DBG_SHIQUCHA (28800)
#define CA_DBG_DATA_MAX 1024
#define CA_DBG_CMU_FILE "CableMQTT"
#define CA_DBG_CMU_FILE_BAK "CableMQTT.bak"
#define CA_DBG_CMU_FILE_DIR "./bak/CableMQTT"
#define CA_DBG_CABLE_FILE "cableMonitor.bak"
#define CA_DBG_LOG_FILE "PowerIoT.db.bak"
#define CA_DBG_HDATA_FILE "Cable.db.bak"
#define CA_DBG_PPP_FILE "/home/Cable/quectel-chat-connect"
#define CA_DBG_PPP_FILE_ETC "/etc/ppp/peers/quectel-chat-connect"
#define CA_DBG_PPP_FILE_BAK "/home/Cable/bak/quectel-chat-connect"
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* 命令类型. */
enum CA_DBG_CMD_TYPE
{
CA_DBG_CT_REQUEST = 1,
CA_DBG_CT_REPLY = 2,
CA_DBG_CT_PRV_REQUEST = 128,
CA_DBG_CT_PRV_REPLY = 129,
};
/* 共有命令字. */
enum CA_DBG_CMD
{
CA_DBG_C_DEV_INFO = 1,
CA_DBG_C_DEV_INFO_SET = 2,
CA_DBG_C_DEV_RESET = 3,
CA_DBG_C_DEV_UPDATE = 5,
CA_DBG_C_DEV_CONFIG = 7,
CA_DBG_C_DEV_CONFIG_SET = 8
};
/* 私有命令字. */
enum CA_DBG_CMD_PRV
{
CA_DBG_C_PRV_CABLE_INFO = 1,
CA_DBG_C_PRV_CABLE_CFG = 2,
CA_DBG_C_PRV_CABLE_DATA = 3,
CA_DBG_C_PRV_CABLE_CFG_SET = 4,
CA_DBG_C_PRV_CABLE_UPDATE = 5,
CA_DBG_C_PRV_CABLE_UPDATE_RT = 6,
CA_DBG_C_PRV_CABLE_STATE = 7,
CA_DBG_C_PRV_CABLE_LOG = 8,
CA_DBG_C_PRV_CABLE_HDATA = 9,
CA_DBG_C_PRV_MQTT_INFO = 10,
CA_DBG_C_PRV_MQTT_INFO_SET = 11,
};
/* 协议头 */
typedef struct
{
uint16_t len; // 报文总长度, 包括报文头, 数据段和报文尾总长度
uint8_t dev_type_m; // 设备主设备号: 有效值 (1-240), 255 表示广播设备号, 表示接收设备无需在意设备号, 其他值暂时预留
uint8_t dev_type_s; // 设备次设备号: 有效值 (1-240), 255 表示广播设备号, 表示接收设备无需在意设备号, 其他值暂时预留
uint32_t dev_id; // 设备 id: 有效值 (1-0xEFFFFFFF), 0xFFFFFFFF 表示广播设备 id, 其他值暂时预留
uint8_t cmd_type; // 命令类型: 有效值(1-240), (1-120) 为共有命令类型, (121-240) 为私有命令类型, 其他值暂时预留
uint8_t cmd; // 命令: 有效值(1-240), 其他值暂时预留
uint16_t pkt_id; // 报文 id, 设备启动后的第一条命令为 1, 依次累加
uint8_t reserve[8]; // 预留位
} ca_dbg_proto_head_t;
/* 连续报文头 */
typedef struct
{
uint32_t index;
uint32_t len;
} ca_dbg_proto_mul_head_t;
/* bin报文头结构体. */
typedef struct
{
uint8_t dev_type_m;
uint8_t dev_type_s;
uint8_t file_type;
uint8_t version_m;
uint16_t version_s;
int8_t reserve[10];
uint32_t crc32;
} ca_dbg_bin_tail_t;
/* 联络报文回复. */
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[CA_DBG_VERSION_LEN];
uint8_t boot_compile_time[CA_DBG_COMPILE_LEN];
uint8_t img_version[CA_DBG_VERSION_LEN];
uint8_t img_compile_time[CA_DBG_COMPILE_LEN];
uint8_t hardware_version[CA_DBG_VERSION_LEN];
uint8_t FPGA_version[CA_DBG_VERSION_LEN];
uint8_t factory_time[CA_DBG_COMPILE_LEN];
/* 设备其他信息. 128byte */
uint8_t name[CA_DBG_NAME_LEN];
} ca_dbg_dev_info_t;
typedef struct
{
uint32_t update_index; // 环流升级报文索引
bool is_update_cable; // 环流设备升级中
bool is_connect; // 环流连接状态
bool is_connect_mqtt; // MQTT 是否连接
bool is_connect_land; // 私有协议是否连接
uint32_t run_time; // 程序运行时长
bool is_connect_4g; // 4G 是否连接
int8_t reserve[3];
} ca_dbg_state_t;
/* 调试工具全局结构 */
typedef struct{
int fd; // TCP server 监听使用的 socket
int fd_client; // TCP client 通讯使用的 socket
int fd_wr; // 文件读写描述符
char buf[CA_DBG_BUF_SIZE]; // 通讯使用收发包 buf
char buf_send[CA_DBG_BUF_SIZE]; // 通讯使用收发包 buf
char cmd_buf[CA_DBG_CMD_BUF_LEN]; // 收到的完整报文 buf
} ca_dbg_ctrl_t;
/* Private variables ---------------------------------------------------------*/
ca_dbg_ctrl_t ca_dbg_ctrl;
/* Private function prototypes -----------------------------------------------*/
/* Internal functions --------------------------------------------------------*/
void _ca_dbg_file_bak(char *src, char *dest)
{
char cmd[256] = {0};
snprintf(cmd, 256, "cp -rf %s %s", src, dest);
system(cmd);
system("sync");
return;
}
void _ca_dbg_file_check(char *source, char *dest, char *mode)
{
struct stat file_stat;
char cmd[64] = {0};
int fd = -1;
off_t size = 0;
int32_t ret = -1;
if (!access(source, F_OK))
{
fd = open(source, O_RDONLY);
if (fd != -1)
{
ret = fstat(fd, &file_stat);
if (ret != -1)
{
size = file_stat.st_size;
}
}
}
if (size > 16)
{
return;
}
log_err(LOG_CA_DBG, "File %s is ERROR, recover %s!", source, dest);
_ca_dbg_file_bak(dest, source);
snprintf(cmd, 64, "chmod %s %s", mode, source);
system(cmd);
system("sync");
}
int32_t _ca_dbg_apn_change(char *apn)
{
int32_t i = 0;
int32_t num = 0;
char str[100][256] = {0};
char linedata[256] = {0};
FILE *fp = NULL;
fp = fopen(CA_DBG_PPP_FILE, "r");
if (NULL == fp)
{
DBG(DBG_M_CA_DBG_ERR, "Open quectel-chat-connect ERROR\r\n");
return E_SYS_CALL;
}
// "OK \rAT+CGDCONT=1,"IP","3gnet",,0,0"
while(fgets(linedata, sizeof(linedata) - 1, fp))
{
if (strstr(linedata, "AT+CGDCONT") != NULL)
{
sprintf(str[i],"OK \\rAT+CGDCONT=1,\"IP\",\"%s\",,0,0\n", apn);
}
else
{
strcpy(str[i], linedata);
}
i++;
}
fclose(fp);
num = i;
fp = fopen(CA_DBG_PPP_FILE, "w");
if (NULL == fp)
{
DBG(DBG_M_CA_DBG_ERR, "Open quectel-chat-connect ERROR\r\n");
return E_SYS_CALL;
}
for(i = 0; i < num; i++)
{
fputs(str[i], fp);
}
fflush(fp);
fclose(fp);
_ca_dbg_file_bak(CA_DBG_PPP_FILE, CA_DBG_PPP_FILE_ETC);
return E_NONE;
}
/* 初始化报文头. */
void _ca_dbg_pkt_head_init(char *buf, uint16_t len, uint8_t cmd_type, uint8_t cmd)
{
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
/* 封装报文头. */
head->len = len;
head->dev_type_m = device_info.id_major;
head->dev_type_s = device_info.id_minor;
head->dev_id = device_info.dev_id;
head->cmd_type = cmd_type;
head->cmd = cmd;
}
/* 报文发送 */
int32_t _ca_dbg_pkt_send(char *buf, uint16_t len)
{
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(buf + sizeof(ca_dbg_proto_head_t));
if (write(ca_dbg_ctrl.fd_client, buf, len) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "DBG send ERR!\r\n");
return E_SYS_CALL;
}
DBG(DBG_M_CA_DBG, "DBG send(%d): %d %d %d %d\r\n", len, time(NULL), head->cmd_type, head->cmd, m_head->index);
if (dbg_stat_get(DBG_M_CA_DBG))
{
buf_print(buf, len > 32 ? 32 : len);
//buf_print(buf, len);
}
return E_NONE;
}
/* 对数据进行校验 */
int32_t _ca_dbg_pkt_dev_update_check(char *file_name)
{
struct stat file_stat;
ca_dbg_bin_tail_t *pkt_tail = NULL;
char *buf = ca_dbg_ctrl.buf;
uint32_t size = 0;
uint16_t write_size = 0;
uint32_t crc32_value = 0xffffffff;
/* 打开描述符, 读取文件大小 */
ca_dbg_ctrl.fd_wr = open(file_name, O_RDONLY, 0777);
if (ca_dbg_ctrl.fd_wr < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Open %s ERROR\r\n", file_name);
return E_SYS_CALL;
}
if (fstat(ca_dbg_ctrl.fd_wr, &file_stat) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "fstat %s ERROR\r\n", file_name);
return E_SYS_CALL;
}
/* 计算 crc32 */
size = file_stat.st_size - 4;
while(size > 0)
{
/* 计算每次写入的数据大小. */
if (size > CA_DBG_BUF_SIZE)
write_size = CA_DBG_BUF_SIZE;
else
write_size = size;
/* 读取升级包. */
if (read(ca_dbg_ctrl.fd_wr, buf, write_size) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "read %s ERROR\r\n", file_name);
return E_SYS_CALL;
}
crc32_value = crc32_update(crc32_value, buf, write_size);
/* 重新计算剩余数据大小. */
size -= write_size;
}
/* 读取报文头 */
lseek(ca_dbg_ctrl.fd_wr, file_stat.st_size - sizeof(ca_dbg_bin_tail_t), SEEK_SET);
if (read(ca_dbg_ctrl.fd_wr, buf, sizeof(ca_dbg_bin_tail_t)) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "read %s ERROR\r\n", file_name);
return E_SYS_CALL;
}
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
/* 比较报文头信息 */
pkt_tail = (ca_dbg_bin_tail_t*)buf;
if (crc32_value != pkt_tail->crc32
|| device_info.id_major != pkt_tail->dev_type_m
|| pkt_tail->file_type != 3)
{
DBG(DBG_M_CA_DBG_ERR, "%d %d 0x%x 0x%x\r\n", pkt_tail->dev_type_m, pkt_tail->file_type, pkt_tail->crc32, crc32_value);
return E_NOT_IDENTIFY;
}
return E_NONE;
}
int32_t _ca_dbg_pkt_dev_update_write(char *cmd)
{
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
char *data = cmd + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t);
/* 初始化文件描述符 */
if (0 == m_head_cmd->index || ca_dbg_ctrl.fd_wr <= 0)
{
if (ca_dbg_ctrl.fd_wr > 0)
{
close(ca_dbg_ctrl.fd_wr);
}
ca_dbg_ctrl.fd_wr = open(CA_DBG_CMU_FILE_BAK, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (ca_dbg_ctrl.fd_wr < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Open " CA_DBG_CMU_FILE_BAK " ERROR\r\n");
return E_SYS_CALL;
}
}
/* 偏移到相应地址, 只要服务器不出错, 理论上不用偏移 */
//lseek(ca_dbg_ctrl.fd_wr, m_head_cmd->index << 10, SEEK_SET);
if (write(ca_dbg_ctrl.fd_wr, data, m_head_cmd->len) < 0)
{
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
DBG(DBG_M_CA_DBG_ERR, "Write " CA_DBG_CMU_FILE_BAK " ERROR\r\n");
return E_SYS_CALL;
}
/* 小于 CA_DBG_DATA_MAX 表示结束 */
if (m_head_cmd->len < CA_DBG_DATA_MAX)
{
/* 关闭描述符 */
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
/* 文件检查 */
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_dev_update_check(CA_DBG_CMU_FILE_BAK));
/* 替换文件 */
if (rename(CA_DBG_CMU_FILE_BAK, CA_DBG_CMU_FILE) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Rename " CA_DBG_CMU_FILE_BAK " ERROR\r\n");
return E_SYS_CALL;
}
/* 备份 img */
_ca_dbg_file_bak(CA_DBG_CMU_FILE, CA_DBG_CMU_FILE_DIR);
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_info_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_dev_info_t *info = (ca_dbg_dev_info_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
uint32_t *temp = NULL;
struct tm *day = NULL;
time_t utc = 0;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_dev_info_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_INFO);
/* 封装数据 */
info->type_m = device_info.id_major;
info->type_s = device_info.id_minor;
info->id = device_info.dev_id;
memcpy(info->mac, device_info.mac, MAC_ADDR_LEN);
temp = (uint32_t*)info->ip; *temp = inet_addr(device_info.host_ip);
temp = (uint32_t*)info->ip_mask; *temp = inet_addr(device_info.host_mask);
temp = (uint32_t*)info->ip_gw; *temp = inet_addr(device_info.host_gw);
memcpy(info->img_version, host.version, CA_DBG_VERSION_LEN);
memcpy(info->img_compile_time, host.compile, CA_DBG_COMPILE_LEN);
utc = device_info.factory_date;
day = localtime(&utc);
strftime((char*)info->factory_time, CA_DBG_COMPILE_LEN, "%Y-%m-%d", day);
memcpy(info->name, host.name, CA_DBG_NAME_LEN);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_info_set_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_dev_info_t *info = (ca_dbg_dev_info_t*)(cmd + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
uint32_t utc = 0;
/* 封装数据 */
memcpy(host.name, info->name, FILE_NAME_LEN);
device_info.dev_id = info->id;
snprintf(device_info.host_ip, INET_ADDRSTRLEN, "%d.%d.%d.%d", info->ip[0], info->ip[1], info->ip[2], info->ip[3]);
snprintf(device_info.host_mask, INET_ADDRSTRLEN, "%d.%d.%d.%d", info->ip_mask[0], info->ip_mask[1], info->ip_mask[2], info->ip_mask[3]);
snprintf(device_info.host_gw, INET_ADDRSTRLEN, "%d.%d.%d.%d", info->ip_gw[0], info->ip_gw[1], info->ip_gw[2], info->ip_gw[3]);
time_str_to_long((char*)info->factory_time, "0:0:0", &utc);
device_info.factory_date = utc;
vtysh_device_save();
vtysh_config_save();
mac_generate_from_ip(device_info.host_ip, device_info.mac);
vtysh_eth0_save();
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_INFO_SET);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
reboot_system(LOG_CA_DBG, BOOT_REMOTE_CFG_SET);
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_reset_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_RESET);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
reboot_system(LOG_CA_DBG, BOOT_REMOTE_RESET);
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_update_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(buf + sizeof(ca_dbg_proto_head_t));
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
int32_t *rt = (int32_t*)(buf + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t));
uint32_t *crc = NULL;
/* 复制文件 */
*rt = _ca_dbg_pkt_dev_update_write(cmd);
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t) + sizeof(int32_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_UPDATE);
m_head->index = m_head_cmd->index;
m_head->len = m_head_cmd->len;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
if (m_head_cmd->len < CA_DBG_DATA_MAX && E_NONE == *rt)
{
reboot_system(LOG_CA_DBG, BOOT_REMOTE_UPDATE);
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_cfg_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_cfg_t *cfg = (ca_coll_cfg_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_coll_cfg_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_CONFIG);
/* 封装数据 */
memcpy(cfg, ca_coll_cfg_get(), sizeof(ca_coll_cfg_t));
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_dev_cfg_set_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_cfg_t *cfg = (ca_coll_cfg_t*)(cmd + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装数据 */
memcpy(ca_coll_cfg_get(), cfg, sizeof(ca_coll_cfg_t));
vtysh_config_save();
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_REPLY, CA_DBG_C_DEV_CONFIG_SET);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
_ca_dbg_file_check(CA_DBG_PPP_FILE, CA_DBG_PPP_FILE_BAK, "600");
cfg = ca_coll_cfg_get();
_ca_dbg_apn_change(cfg->apn);
return E_NONE;
}
int32_t _ca_dbg_pkt_cable_update_write(char *cmd)
{
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
char *data = cmd + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t);
/* 初始化文件描述符 */
if (0 == m_head_cmd->index || ca_dbg_ctrl.fd_wr <= 0)
{
if (ca_dbg_ctrl.fd_wr > 0)
{
close(ca_dbg_ctrl.fd_wr);
}
ca_dbg_ctrl.fd_wr = open(CA_DBG_CABLE_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (ca_dbg_ctrl.fd_wr < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Open " CA_DBG_CABLE_FILE " ERROR\r\n");
return E_SYS_CALL;
}
}
/* 偏移到相应地址, 只要服务器不出错, 理论上不用偏移 */
//lseek(ca_dbg_ctrl.fd_wr, m_head_cmd->index << 10, SEEK_SET);
if (write(ca_dbg_ctrl.fd_wr, data, m_head_cmd->len) < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Write " CA_DBG_CABLE_FILE " ERROR\r\n");
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
return E_SYS_CALL;
}
/* 小于 CA_DBG_DATA_MAX 表示结束 */
if (m_head_cmd->len < CA_DBG_DATA_MAX)
{
/* 关闭描述符 */
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_info_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_dev_info_t *info = (ca_coll_dev_info_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_coll_dev_info_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_INFO);
/* 封装数据 */
memcpy(info, ca_coll_cable_info_get(), sizeof(ca_coll_dev_info_t));
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_cfg_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_dev_cfg_t *cfg = (ca_coll_dev_cfg_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_coll_dev_cfg_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_CFG);
/* 封装数据 */
memcpy(cfg, ca_coll_cable_cfg_get(), sizeof(ca_coll_dev_cfg_t));
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_data_recv(char *cmd)
{
uint32_t *utc = (uint32_t*)(cmd + sizeof(ca_dbg_proto_head_t));
uint32_t t = *utc + CA_DBG_SHIQUCHA;
if (abs(t - time(NULL)) > 1)
{
time_set(t); //北京时间
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_data_send(void)
{
char *buf = ca_dbg_ctrl.buf_send;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_dev_data_t *data = (ca_coll_dev_data_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_coll_dev_data_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_DATA);
/* 封装数据 */
memcpy(data, ca_coll_cable_data_get(), sizeof(ca_coll_dev_data_t));
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_cfg_set_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_coll_dev_cfg_t *cfg = (ca_coll_dev_cfg_t*)(cmd + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装数据 */
memcpy(ca_coll_cable_cfg_get(), cfg, sizeof(ca_coll_dev_cfg_t));
vtysh_config_save();
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_CFG_SET);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_update_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(buf + sizeof(ca_dbg_proto_head_t));
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
int32_t *rt = (int32_t*)(buf + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t));
uint32_t *crc = NULL;
/* 复制文件 */
*rt = _ca_dbg_pkt_cable_update_write(cmd);
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t) + sizeof(int32_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_UPDATE);
m_head->index = m_head_cmd->index;
m_head->len = m_head_cmd->len;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
if (m_head_cmd->len < CA_DBG_DATA_MAX && E_NONE == *rt)
{
ca_coll_cable_update_set(TRUE);
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_cable_state_send(void)
{
char *buf = ca_dbg_ctrl.buf_send;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_state_t *state = (ca_dbg_state_t*)(buf + sizeof(ca_dbg_proto_head_t));
ca_coll_state_t *ca_coll_state = NULL;
ca_mqtt_state_t *ca_mqtt_state = NULL;
ca_land_state_t *ca_land_state = NULL;
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_state_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_STATE);
/* 封装数据 */
ca_coll_state = ca_coll_cable_state_get();
state->is_connect = ca_coll_state->send_err_cnt < CA_COLL_ERR_CNT_MAX;
state->is_update_cable = ca_coll_state->is_update_cable;
state->update_index = ca_coll_state->update_index;
state->is_connect_4g = ca_coll_state->is_4g_connect;
ca_mqtt_state = ca_mqtt_state_get();
state->is_connect_mqtt = ca_mqtt_state->is_connect;
ca_land_state = ca_land_state_get();
state->is_connect_land = ca_land_state->is_connect;
state->run_time = start_time;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_log_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(buf + sizeof(ca_dbg_proto_head_t));
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
char *data = buf + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t);
uint32_t *crc = NULL;
int32_t len = 0;
/* 初始化文件描述符 */
if (0 == m_head_cmd->index || ca_dbg_ctrl.fd_wr <= 0)
{
_ca_dbg_file_bak(LOG_FILE, CA_DBG_LOG_FILE);
if (ca_dbg_ctrl.fd_wr > 0)
{
close(ca_dbg_ctrl.fd_wr);
}
ca_dbg_ctrl.fd_wr = open(CA_DBG_LOG_FILE, O_RDONLY, 0777);
if (ca_dbg_ctrl.fd_wr < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Open " CA_DBG_LOG_FILE " ERROR\r\n");
return E_SYS_CALL;
}
}
/* 偏移到相应地址, 只要服务器不出错, 理论上不用偏移 */
lseek(ca_dbg_ctrl.fd_wr, m_head_cmd->index << 10, SEEK_SET);
len = read(ca_dbg_ctrl.fd_wr, data, CA_DBG_DATA_MAX);
if (len < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Read " CA_DBG_LOG_FILE " ERROR\r\n");
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
return E_SYS_CALL;
}
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_LOG);
m_head->index = m_head_cmd->index;
m_head->len = len;
head->len += sizeof(ca_dbg_proto_mul_head_t) + m_head->len;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
if (len < CA_DBG_DATA_MAX)
{
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
remove(CA_DBG_LOG_FILE);
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_hdata_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(buf + sizeof(ca_dbg_proto_head_t));
ca_dbg_proto_mul_head_t *m_head_cmd = (ca_dbg_proto_mul_head_t*)(cmd + sizeof(ca_dbg_proto_head_t));
char *data = buf + sizeof(ca_dbg_proto_head_t) + sizeof(ca_dbg_proto_mul_head_t);
uint32_t *crc = NULL;
int32_t len = 0;
/* 初始化文件描述符 */
if (0 == m_head_cmd->index || ca_dbg_ctrl.fd_wr <= 0)
{
_ca_dbg_file_bak(CA_DB_FILE, CA_DBG_HDATA_FILE);
if (ca_dbg_ctrl.fd_wr > 0)
{
close(ca_dbg_ctrl.fd_wr);
}
ca_dbg_ctrl.fd_wr = open(CA_DBG_HDATA_FILE, O_RDONLY, 0777);
if (ca_dbg_ctrl.fd_wr < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Open " CA_DBG_HDATA_FILE " ERROR\r\n");
return E_SYS_CALL;
}
}
/* 偏移到相应地址, 只要服务器不出错, 理论上不用偏移 */
lseek(ca_dbg_ctrl.fd_wr, m_head_cmd->index << 10, SEEK_SET);
len = read(ca_dbg_ctrl.fd_wr, data, CA_DBG_DATA_MAX);
if (len < 0)
{
DBG(DBG_M_CA_DBG_ERR, "Read " CA_DBG_HDATA_FILE " ERROR\r\n");
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
return E_SYS_CALL;
}
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_HDATA);
m_head->index = m_head_cmd->index;
m_head->len = len;
head->len += sizeof(ca_dbg_proto_mul_head_t) + m_head->len;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
if (len < CA_DBG_DATA_MAX)
{
close(ca_dbg_ctrl.fd_wr);
ca_dbg_ctrl.fd_wr = 0;
remove(CA_DBG_HDATA_FILE);
}
return E_NONE;
}
/* 设备信息报文处理. */
int32_t _ca_dbg_pkt_mqtt_info_send(void)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_mqtt_dev_info_t *info = (ca_mqtt_dev_info_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_mqtt_dev_info_t) + sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_MQTT_INFO);
/* 封装数据 */
memcpy(info, &device_info.mqtt, sizeof(ca_mqtt_dev_info_t));
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
int32_t _ca_dbg_pkt_mqtt_info_set_send(char *cmd)
{
char *buf = ca_dbg_ctrl.buf;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
ca_mqtt_dev_info_t *info = (ca_mqtt_dev_info_t*)(cmd + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装数据 */
memcpy(&device_info.mqtt, info, sizeof(ca_mqtt_dev_info_t));
vtysh_device_save();
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_MQTT_INFO_SET);
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
return E_NONE;
}
int32_t _ca_dbg_pkt_check(char *cmd)
{
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)cmd;
/* 对主次设备号进行识别, 次设备号可以是广播. */
if ((head->dev_type_m != 1)
|| (head->dev_type_s != 0xFF && head->dev_type_s != device_info.id_minor))
{
DBG(DBG_M_CA_DBG_ERR, "Dev type %d:%d error\r\n", head->dev_type_m, head->dev_type_s);
return E_NOT_FOUND;
}
/* 对设备 id 进行识别, 可以是广播. */
//if (head->dev_id != 0xFFFFFFFF && head->dev_id != device_info.dev_id)
//{
// DBG(DBG_M_CA_DBG_ERR, "Dev id %x error\r\n", head->dev_id);
// return E_NOT_FOUND;
//}
/* 验证 CRC32. */
if (crc32(cmd, head->len) != (*(uint32_t*)(cmd + head->len)))
{
DBG(DBG_M_CA_DBG_ERR, "CRC %x:%x error\r\n", crc32(cmd, head->len), *(uint32_t*)(cmd + head->len));
return E_ERROR;
}
return E_NONE;
}
/* 调试工具报文数据处理. */
int32_t _ca_dbg_pkt_process(char *buf)
{
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
/* 报文格式检查. */
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_check(buf));
/* 报文处理. */
if (CA_DBG_CT_REQUEST == head->cmd_type)
{
/* 共有命令处理. */
switch (head->cmd)
{
case CA_DBG_C_DEV_INFO:
_ca_dbg_pkt_dev_info_send();
break;
case CA_DBG_C_DEV_INFO_SET:
_ca_dbg_pkt_dev_info_set_send(buf);
break;
case CA_DBG_C_DEV_RESET:
_ca_dbg_pkt_dev_reset_send();
break;
case CA_DBG_C_DEV_UPDATE:
_ca_dbg_pkt_dev_update_send(buf);
break;
case CA_DBG_C_DEV_CONFIG:
_ca_dbg_pkt_dev_cfg_send();
break;
case CA_DBG_C_DEV_CONFIG_SET:
_ca_dbg_pkt_dev_cfg_set_send(buf);
break;
default:
DBG(DBG_M_CA_DBG_ERR, "Cmd %d not found\r\n", head->cmd);
return E_NOT_FOUND;
}
}
else if(CA_DBG_CT_PRV_REQUEST == head->cmd_type)
{
/* 私有命令处理. */
switch (head->cmd)
{
case CA_DBG_C_PRV_CABLE_INFO:
_ca_dbg_pkt_cable_info_send();
break;
case CA_DBG_C_PRV_CABLE_CFG:
_ca_dbg_pkt_cable_cfg_send();
break;
case CA_DBG_C_PRV_CABLE_DATA:
_ca_dbg_pkt_cable_data_recv(buf);
break;
case CA_DBG_C_PRV_CABLE_CFG_SET:
_ca_dbg_pkt_cable_cfg_set_send(buf);
break;
case CA_DBG_C_PRV_CABLE_UPDATE:
_ca_dbg_pkt_cable_update_send(buf);
break;
case CA_DBG_C_PRV_CABLE_LOG:
_ca_dbg_pkt_log_send(buf);
break;
case CA_DBG_C_PRV_CABLE_HDATA:
_ca_dbg_pkt_hdata_send(buf);
break;
case CA_DBG_C_PRV_MQTT_INFO:
_ca_dbg_pkt_mqtt_info_send();
break;
case CA_DBG_C_PRV_MQTT_INFO_SET:
_ca_dbg_pkt_mqtt_info_set_send(buf);
break;
default:
DBG(DBG_M_CA_DBG_ERR, "Cmd %d not found\r\n", head->cmd);
return E_NOT_FOUND;
}
}
return E_NONE;
}
/* 调试工具报文接收处理线程. */
void *_ca_dbg_pkt_handle_recv(void *arg)
{
uint8_t state = FALSE;
uint32_t utc = 0;
int32_t cmd_buf_index = 0;
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)ca_dbg_ctrl.cmd_buf;
ca_dbg_proto_mul_head_t *m_head = (ca_dbg_proto_mul_head_t*)(ca_dbg_ctrl.cmd_buf + sizeof(ca_dbg_proto_head_t));
char *buf = ca_dbg_ctrl.buf;
uint32_t now = 0;
int len = 0;
while(1)
{
/* 读取数据. */
len = read(ca_dbg_ctrl.fd_client, buf, CA_DBG_BUF_SIZE);
if (len <= 0)
{
/* 连接中断, 关闭 socket 和手动采样. */
DBG(DBG_M_CA_DBG_ERR, "Read len %d, close fd!\r\n", len);
close(ca_dbg_ctrl.fd_client);
ca_dbg_ctrl.fd_client = -1;
break;
}
/* 超过 3s 没有收包说明收包超时, 重新开始收包. */
now = time(NULL);
if (now - utc > 3)
{
cmd_buf_index = 0;
state = 0;
}
utc = now;
/* 如果收包大于协议报文长度或者大于 buf 长度, 认为报文错误. */
if (cmd_buf_index + len >= CA_DBG_CMD_BUF_LEN)
{
cmd_buf_index = 0;
state = 0;
continue;
}
/* 将 buf 中的数据解析成命令. */
memcpy(&ca_dbg_ctrl.cmd_buf[cmd_buf_index], buf, len);
cmd_buf_index += len;
if (!state)
{
if (cmd_buf_index < sizeof(ca_dbg_proto_head_t) + CA_DBG_CRC32_LEN)
{
continue;
}
/* 报文长度不对, 重新收包. */
if (head->len + CA_DBG_CRC32_LEN > CA_DBG_CMD_BUF_LEN)
{
cmd_buf_index = 0;
state = FALSE;
continue;
}
/* 报文长度与收包长度不对称, 等待后续报文. */
if (cmd_buf_index < head->len + CA_DBG_CRC32_LEN)
{
state = TRUE;
continue;
}
}
else
{
/* 报文长度与收包长度不对称, 等待后续报文. */
if (cmd_buf_index < head->len + CA_DBG_CRC32_LEN)
{
continue;
}
state = FALSE;
}
DBG(DBG_M_CA_DBG, "Recv(%d): %d %d %d %d\r\n", cmd_buf_index, utc, head->cmd_type, head->cmd, m_head->index);
if (dbg_stat_get(DBG_M_CA_DBG))
{
buf_print(ca_dbg_ctrl.cmd_buf, cmd_buf_index > 32 ? 32 : cmd_buf_index);
//buf_print(ca_dbg_ctrl.cmd_buf, cmd_buf_index);
}
/* 数据处理. */
while(1)
{
_ca_dbg_pkt_process(ca_dbg_ctrl.cmd_buf);
len = head->len + CA_DBG_CRC32_LEN;
cmd_buf_index -= len;
if (cmd_buf_index <= 0)
{
cmd_buf_index = 0;
break;
}
memcpy(ca_dbg_ctrl.cmd_buf, ca_dbg_ctrl.cmd_buf + len, cmd_buf_index);
if (cmd_buf_index < sizeof(ca_dbg_proto_head_t) + CA_DBG_CRC32_LEN)
{
break;
}
/* 报文长度与收包长度不对称, 等待后续报文. */
if (cmd_buf_index < head->len + CA_DBG_CRC32_LEN)
{
break;
}
}
}
pthread_exit("thread exit");
return NULL;
}
int32_t _ca_dbg_client_create(void)
{
struct sched_param param;
pthread_attr_t attr;
int32_t rv = 0;
pthread_t thread;
/* 初始化报文处理线程. */
/* 配置线程RR调度, 优先级25. */
pthread_attr_init(&attr);
param.sched_priority = 25;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
rv = pthread_create(&thread, &attr, _ca_dbg_pkt_handle_recv, NULL);
if (rv != 0)
{
DBG(DBG_M_CA_DBG_ERR, "PD can't create debug pthread %d!\r\n", rv);
return E_SYS_CALL;
}
pthread_attr_destroy(&attr);
return E_NONE;
}
int32_t _ca_dbg_keep_alive(int fd)
{
// 开启保活,保活参数 表示60秒内无交互后每隔6秒检测一次40次都没得到响应时会断开连接。
int keep_alive = 1;
int keep_idle = 60;
int keep_interval = 6;
int keep_count = 10;
int keep_time = 60000;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive, sizeof(keep_alive)))
{
DBG(DBG_M_CA_DBG_ERR, "Error setsockopt(SO_KEEPALIVE) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_idle, sizeof(keep_idle)))
{
DBG(DBG_M_CA_DBG_ERR, "Error setsockopt(TCP_KEEPIDLE) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)))
{
DBG(DBG_M_CA_DBG_ERR, "Error setsockopt(TCP_KEEPINTVL) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keep_count, sizeof(keep_count)))
{
DBG(DBG_M_CA_DBG_ERR, "Error setsockopt(TCP_KEEPCNT) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, (void *)&keep_time, sizeof(keep_time)))
{
DBG(DBG_M_CA_DBG_ERR, "Error setsockopt(TCP_KEEPCNT) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
return E_NONE;
}
void *_ca_dbg_accept_handle(void *arg)
{
struct sockaddr_in cliaddr = {0};
socklen_t clilen;
int connfd = 0;
while (!is_system_init)
{
sleep(1);
}
/* 监听端口. */
if ((listen(ca_dbg_ctrl.fd, 5)) != 0)
{
DBG(DBG_M_CA_DBG_ERR, "ERROR at socket listen return %s!\r\n", safe_strerror(errno));
return NULL;
}
while (1)
{
clilen = sizeof(cliaddr);
connfd = accept(ca_dbg_ctrl.fd, (struct sockaddr*)&cliaddr, &clilen);
if (connfd < 0)
{
DBG(DBG_M_CA_DBG_ERR, "ERROR at socket accept return %s!\r\n", safe_strerror(errno));
continue;
}
if (ca_dbg_ctrl.fd_client < 0)
{
ca_dbg_ctrl.fd_client = connfd;
_ca_dbg_keep_alive(ca_dbg_ctrl.fd_client);
_ca_dbg_client_create();
}
else
{
DBG(DBG_M_CA_DBG_ERR, "There is a link trying to connect...\r\n");
close(connfd);
connfd = -1;
}
}
return NULL;
}
/* 用于定时将数据发送给调试软件. */
void* _ca_dbg_data_send(void *arg)
{
/* 如果手动采样开启, 则发送数据. */
if (ca_dbg_ctrl.fd_client > 0)
{
_ca_dbg_pkt_cable_data_send();
_ca_dbg_pkt_cable_state_send();
}
/* 重新加入定时器. */
mtimer_add(_ca_dbg_data_send, NULL, 3, "CA_DBG_DATA_SEND");
return NULL;
}
/* Interface functions -------------------------------------------------------*/
/* 调试工具初始化. */
int32_t ca_dbg_handle_init_after(void)
{
struct sockaddr_in server;
struct sched_param param;
pthread_attr_t attr;
pthread_t pid;
int32_t rv = 0;
int fd = 0;
int opt = 1;
/* 创建 socket */
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
log_err(LOG_CA_DBG, "ERROR at socket create return %s!", safe_strerror(errno));
return E_SYS_CALL;
}
/* 绑定端口 */
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(CA_DBG_TOOL_PORT);
if (bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0)
{
log_err(LOG_CA_DBG, "ERROR at socket bind return %s!", safe_strerror(errno));
close(fd);
return E_SYS_CALL;
}
/* fd 为需要端口复用的套接字 */
opt = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
/* 保存数据. */
ca_dbg_ctrl.fd = fd;
ca_dbg_ctrl.fd_client = -1;
pthread_attr_init(&attr);
param.sched_priority = 25;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _ca_dbg_accept_handle, NULL);
if (rv != 0)
{
log_err(LOG_CA_DBG, "Can't create debug pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("CA_DBG_ACCEPT", pid);
}
pthread_attr_destroy(&attr);
mtimer_add(_ca_dbg_data_send, NULL, 3, "CA_DBG_DATA_SEND");
return E_NONE;
}
int32_t ca_dbg_update_rt_send(int32_t rt)
{
char buf[128] = {0};
ca_dbg_proto_head_t *head = (ca_dbg_proto_head_t*)buf;
int32_t *data = (int32_t*)(buf + sizeof(ca_dbg_proto_head_t));
uint32_t *crc = NULL;
/* 封装报文头 */
_ca_dbg_pkt_head_init(buf, sizeof(ca_dbg_proto_head_t) + sizeof(int32_t), CA_DBG_CT_PRV_REPLY, CA_DBG_C_PRV_CABLE_UPDATE_RT);
/* 封装数据 */
*data = rt;
/* 计算校验和 */
crc = (uint32_t*)(buf + head->len);
*crc = crc32(buf, head->len);
LD_E_RETURN(DBG_M_CA_DBG_ERR, _ca_dbg_pkt_send(buf, head->len + CA_DBG_CRC32_LEN));
remove(CA_DBG_CABLE_FILE);
return E_NONE;
}
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/