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

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