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

© COPYRIGHT(c) 2023 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 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 #include #include #include #include #include #include #include /* 用户代码头文件. */ #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, ¶m); 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, ¶m); 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 ****************/