/***************************************************************************** * file lib/process/pd_dbg.c * author YuLiang * version 1.0.0 * date 01-June-2023 * brief This file provides all the debug server related operation functions. ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2021 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_PD /* 标准C库头文件. */ #include #include #include #include #include #include /* 用户代码头文件. */ #include "cJSON.h" #include "main.h" #include "mtimer.h" #include "pd_dbg.h" #include "pd_csg.h" #include "pd_dau.h" #include "pd_upgrade.h" /* Private define ------------------------------------------------------------*/ #define DEBUG_HEAD 0x55AA #define DEBUG_TAIL 0x5AA5 #define DEBUG_CMD_LEN 10 * 1024 * 1024 #define DEBUG_CMU_FILE "PDMonitor" #define DEBUG_CMU_FILE_BAK "./bak/PDMonitor.bak" #define DEBUG_CMU_FILE_UPGRADE "PDMonitor.upgrade" /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ debug_ctrl_t debug_ctrl; dbg_device_info_t dbg_base_config; dbg_global_config_t dbg_global_config; dbg_port_config_t dbg_port_config; static char buf_cmd[DEBUG_CMD_LEN]; /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ void _debug_pkt_head_int(dbg_pkt_head_t *head, uint16_t cmd, uint32_t len) { head->head = DEBUG_HEAD; head->cmd = cmd; head->len = len; } /* 回复报文处理. */ int32_t _debug_pkt_common_send(char *buf, uint16_t cmd, uint32_t data_len) { uint16_t total_len; dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; head->len = data_len; uint16_t *tail = (uint16_t*)(buf + sizeof(dbg_pkt_head_t) + data_len); _debug_pkt_head_int(head, cmd, data_len); *tail = DEBUG_TAIL; total_len = sizeof(dbg_pkt_head_t) + data_len + 2; DBG(DBG_M_DEBUG, "数据包 (总长度: %u bytes):\r\n", total_len); DBG(DBG_M_DEBUG, " 头部: head=0x%04X, cmd=0x%04X, len=%u\r\n", head->head, head->cmd, head->len); DBG(DBG_M_DEBUG, " 尾部: 0x%04X\r\n", *tail); if (write(debug_ctrl.fd_client, buf, total_len) <= 0) { DBG(DBG_M_DEBUG, "Write cmd %x ERROR\r\n", head->cmd); return E_SYS_CALL; } return E_NONE; } /* 获取配置报文处理. */ int32_t _debug_pkt_factory_cfg_get(char *buf, int len) { uint16_t len_pkt = 0; dbg_device_info_t *info = (dbg_device_info_t *)(buf+sizeof(dbg_pkt_head_t)); memset(info, 0, sizeof(dbg_device_info_t)); info->type_m = device_info.type_m; info->type_s = device_info.type_s; info->dev_id = device_info.dev_id; snprintf((char*)info->hostname, PD_DEV_NUM_LEN, "%s", device_info.hostname); info->factory_date = device_info.factory_date; info->deployment_date = device_info.deployment_date; info->ip = device_info.ip; memcpy(info->mac, device_info.mac, MAC_ADDR_LEN); info->mask = device_info.mask; info->gw = device_info.gw; strncpy((char*)info->app_version, host.version, 32); strncpy((char*)info->app_compile_time, host.compile, 32); //strncpy((char*)info->hardware_version, host.hardversion, 32); // 赋值 FPGA_version info->csg_port = csg.server_port; info->csg_ipv4 = csg.server_ip; info->running_time = start_time; len_pkt += sizeof(dbg_device_info_t); int32_t ret = _debug_pkt_common_send(buf, DEBUG_CONFIG_FACTORY_GET, len_pkt); /* 发送数据. */ return ret; } int32_t _debug_pkt_factory_cfg_set(char *buf, int len) { REBOOT_MSG boottype = REBOOT_NONE; dbg_device_info_t *info = (dbg_device_info_t *)(buf+sizeof(dbg_pkt_head_t)); if(device_info.type_m != info->type_m|| device_info.type_s != info->type_s|| device_info.dev_id != info->dev_id) { device_info.type_m = info->type_m; device_info.type_s = info->type_s; device_info.dev_id = info->dev_id; boottype = REBOOT_LOCAL_HOST_NAME_CHANGE; } snprintf(device_info.hostname, PD_DEV_NUM_LEN, "%s", (const char*)info->hostname); device_info.factory_date = info->factory_date; device_info.deployment_date = info->deployment_date; if (device_info.ip != info->ip) { DBG(DBG_M_DEBUG, "IP 地址变更: %u.%u.%u.%u -> %u.%u.%u.%u\r\n", device_info.ip & 0xFF, (device_info.ip >> 8) & 0xFF, (device_info.ip >> 16) & 0xFF, (device_info.ip >> 24) & 0xFF, info->ip & 0xFF, (info->ip >> 8) & 0xFF, (info->ip >> 16) & 0xFF, (info->ip >> 24) & 0xFF); device_info.ip = info->ip; mac_generate_from_ip(device_info.ip, info->mac); memcpy(device_info.mac, info->mac, MAC_ADDR_LEN); boottype = REBOOT_REMOTE_IP_CHANGE; vtysh_eth0_save(); } device_info.gw = info->gw; device_info.mask = info->mask; vtysh_device_save(); if (csg.server_ip != info->csg_ipv4) { csg.server_ip = info->csg_ipv4; boottype = REBOOT_REMOTE_SERVER_IP_CHANGE; } if (csg.server_port != info->csg_port) { csg.server_port = info->csg_port; boottype = REBOOT_REMOTE_SERVER_IP_CHANGE; } vtysh_config_save(); // 打印接收到的设备信息 DBG(DBG_M_DEBUG, "================================================\r\n"); DBG(DBG_M_DEBUG, "接收到的设备信息:\r\n"); DBG(DBG_M_DEBUG, " 主设备号 (type_m): %u\r\n", info->type_m); DBG(DBG_M_DEBUG, " 次设备号 (type_s): %u\r\n", info->type_s); DBG(DBG_M_DEBUG, " 设备ID (dev_id): %u\r\n", info->dev_id); DBG(DBG_M_DEBUG, " 主机名 (hostname): %s\r\n", info->hostname); DBG(DBG_M_DEBUG, " 出厂时间 (factory_date): %u\r\n", info->factory_date); DBG(DBG_M_DEBUG, " 部署时间 (deployment_date): %u\r\n", info->deployment_date); DBG(DBG_M_DEBUG, " IP 地址 (ip): %u.%u.%u.%u\r\n", (info->ip) & 0xFF, (info->ip >> 8) & 0xFF, (info->ip >> 16) & 0xFF, (info->ip >> 24) & 0xFF); DBG(DBG_M_DEBUG, " 子网掩码 (mask): %u.%u.%u.%u\r\n", (info->mask) & 0xFF, (info->mask >> 8) & 0xFF, (info->mask >> 16) & 0xFF, (info->mask >> 24) & 0xFF); DBG(DBG_M_DEBUG, " 网关 (gw): %u.%u.%u.%u\r\n", (info->gw) & 0xFF, (info->gw >> 8) & 0xFF, (info->gw >> 16) & 0xFF, (info->gw >> 24) & 0xFF); DBG(DBG_M_DEBUG, " MAC 地址 (mac): %02X:%02X:%02X:%02X:%02X:%02X\r\n", info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5]); DBG(DBG_M_DEBUG, " CSG 端口 (csg_port): %u\r\n", info->csg_port); DBG(DBG_M_DEBUG, " CSG 服务器 IP (csg_ipv4): %u.%u.%u.%u\r\n", (info->csg_ipv4 >> 24) & 0xFF, (info->csg_ipv4 >> 16) & 0xFF, (info->csg_ipv4 >> 8) & 0xFF, info->csg_ipv4 & 0xFF); if (boottype) { _debug_pkt_common_send(buf, DEBUG_CONFIG_FACTORY_SET, 0); sleep(1); reboot_system(LOG_DEBUG, boottype); } return E_NONE; } /* 设置报文处理. */ int32_t _debug_pkt_global_cfg_set(char *pkt, int len) { dbg_global_config_t *pnet = (dbg_global_config_t *)(pkt + sizeof(dbg_pkt_head_t)); //pd_config.config.power_frequency = pnet->power_frequency * 10; //pd_config.config.trend_period = pnet->trend_period * 60; //pd_config.config.sync_mode = pnet->sync_mode; //pd_config.config.heartbeat_period = pnet->heartbeat_period; //pd_config.config.pps_mode = pnet->pps_mode; //pd_config.config.trend_storage = pnet->trend_storage; //pd_config.config.event_storage = pnet->event_storage; //pd_config.config.is_4G_enable = pnet->is_4G_enable; vtysh_config_save(); return _debug_pkt_common_send(pkt, DEBUG_CONFIG_GLOBAL_SET, 0); } /* 查询用户参数查询报文处理. */ int32_t _debug_pkt_global_cfg_get(char *pkt, int len) { uint16_t len_pkt = 0; dbg_global_config_t *pnet = (dbg_global_config_t *)(pkt + sizeof(dbg_pkt_head_t)); _debug_pkt_common_send(pkt, DEBUG_CONFIG_GLOBAL_GET, len_pkt); return E_NONE; } /* 设置报文处理. */ int32_t _debug_pkt_port_cfg_set(char *pkt, int len) { return E_NONE; } /* 查询用户参数查询报文处理. */ int32_t _debug_pkt_port_cfg_get(char *pkt, int len) { return E_NONE; } /* 重启报文处理. */ int32_t _debug_pkt_reboot(char *buf, int len) { /* 发送数据. */ _debug_pkt_common_send(buf, DEBUG_REBOOT, 0); /* 重启. */ reboot_system(LOG_DEBUG, REBOOT_LOCAL_RESET); return E_NONE; } /* 时间设置报文处理. */ int32_t _debug_pkt_time_set(char *buf, int len) { uint32_t *timestamp = (uint32_t*)(buf + sizeof(dbg_pkt_head_t)); /* 配置时间. */ time_set(*timestamp); /* 发送数据. */ _debug_pkt_common_send(buf, DEBUG_TIME_SET, 0); return E_NONE; } /* 数据手动设置报文处理. */ int32_t _debug_pkt_manual_col(char *buf, int len) { char *flag = buf + sizeof(dbg_pkt_head_t); DBG(DBG_M_DEBUG, " 手动采集 flag : %d\r\n", (*flag) ? TRUE : FALSE); /* 修改标志位. */ debug_ctrl.is_manual_col = (*flag) ? TRUE : FALSE; /* 发送数据. */ return _debug_pkt_common_send(buf, DEBUG_NOISE_CAREFOR, 0); } /* 获取校准系数报文处理. */ int32_t _debug_pkt_adj_get(char *buf, int len) {} /* 获取校准系数报文处理. */ int32_t _debug_pkt_adj_set(char *buf, int len) {} /* 获取运行状态报文处理. */ int32_t _debug_pkt_status_get(char *buf, int len) { debug_pkt_status_t *status = (debug_pkt_status_t*)(buf + sizeof(debug_pkt_head_t)); status->idx = 0; status->UTC_TimeScale = time(NULL); //status->F50Hz_Frequency = dau_power_frequency_get(); status->F50Hz_SynStatus = pd_state.sync; status->dau_status = dau_connect_get(); status->sensor_status = 0; status->is_server_link = csg.is_connect; status->version = version_hex; status->communication_time = csg.communication_time; status->run_time = start_time; /* 发送数据. */ //return _debug_pkt_common_send(buf, DEBUG_RUN_STATUS_GET, sizeof(debug_pkt_status_t)); return E_NONE; } /* 获取运行状态报文处理. */ int32_t _debug_pkt_dev_connect_status_get(char *buf, int len) { debug_pkt_dev_connect_status_t *status = (debug_pkt_dev_connect_status_t*)(buf + sizeof(dbg_pkt_head_t)); status->csg_connect_status = csg.is_connect; DBG(DBG_M_DEBUG, " ec20_connect_status %d\r\n", status->ec20_connect_status); DBG(DBG_M_DEBUG, " csg_connect_status %d\r\n", status->csg_connect_status); /* 发送数据. */ return _debug_pkt_common_send(buf, DEBUG_DEVICE_STATUS, sizeof(debug_pkt_dev_connect_status_t)); } /* CMU 升级报文处理. */ int32_t _debug_pkt_mcu_upgrade(char *buf, int len) { dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; char *type = buf + sizeof(dbg_pkt_head_t); DBG(DBG_M_DEBUG, "upgrade type is %d\r\n", type[0]); char *data = buf + sizeof(dbg_pkt_head_t) + 1; int fd = 0; /* 保存文件. */ fd = open(DEBUG_CMU_FILE_UPGRADE, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (fd <= 0) { DBG(DBG_M_PD_ERR, "Open " DEBUG_CMU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } if (write(fd, data, head->len) != head->len) { DBG(DBG_M_PD_ERR, "Write " DEBUG_CMU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } close(fd); //保存旧文件 if (rename(DEBUG_CMU_FILE, DEBUG_CMU_FILE_BAK) < 0) { DBG(DBG_M_PD_ERR, "Rename " DEBUG_CMU_FILE_BAK " ERROR\r\n"); return E_SYS_CALL; } // 升级新文件 if (rename(DEBUG_CMU_FILE_UPGRADE, DEBUG_CMU_FILE) < 0) { DBG(DBG_M_PD_ERR, "Rename " DEBUG_CMU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } /* 发送回复. */ _debug_pkt_common_send(buf, DEBUG_ARM_UPGRADE, 0); DBG(DBG_M_DEBUG, "reboot_system arm upgrade\r\n"); reboot_system(LOG_DEBUG, REBOOT_LOCAL_ARM_UPGRADE); return E_NONE; } /* DAU 升级报文处理. */ int32_t _debug_pkt_dau_upgrade(char *buf, int len, uint8_t bitmap) { dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; char *type = buf + sizeof(dbg_pkt_head_t); DBG(DBG_M_DEBUG, "upgrade type is %d\r\n", type[0]); char *data = buf + sizeof(dbg_pkt_head_t) + 1; int fd = 0; fd = open(DEBUG_DAU_FILE_UPGRADE, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd <= 0) { DBG(DBG_M_DEBUG, "Open " DEBUG_DAU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } if (write(fd, data, head->len) != head->len) { DBG(DBG_M_DEBUG, "Write " DEBUG_DAU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } close(fd); //保存旧文件 if (rename(DEBUG_DAU_FILE, DEBUG_DAU_FILE_BAK) < 0) { DBG(DBG_M_PD_ERR, "Rename " DEBUG_CMU_FILE_BAK " ERROR\r\n"); return E_SYS_CALL; } // 升级新文件 if (rename(DEBUG_DAU_FILE_UPGRADE, DEBUG_DAU_FILE) < 0) { DBG(DBG_M_PD_ERR, "Rename " DEBUG_CMU_FILE_UPGRADE " ERROR\r\n"); return E_SYS_CALL; } DBG(DBG_M_DEBUG, "reboot_system dau upgrade\r\n"); _debug_pkt_common_send(buf, head->cmd, 1); reboot_system(LOG_DEBUG, REBOOT_LOCAL_ARM_UPGRADE); return E_NONE; } int32_t _debug_all_upgrade(char *buf, int len) { dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; char *data = buf + sizeof(dbg_pkt_head_t); uint8_t type = 0; int32_t *rt = (int32_t*)data; int fd = 0; int32_t rv = 0; if (buf == NULL) { return E_BAD_PARAM; } /* 获取升级类型, 更新数据指针 */ type = *data; data++; /* 保存文件 */ fd = open(PD_UPG_SOFTWARE, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd <= 0) { DBG(DBG_M_DEBUG, "Open " PD_UPG_SOFTWARE " ERROR\r\n"); return E_SYS_CALL; } if (write(fd, data, head->len - 1) != (head->len - 1)) { DBG(DBG_M_DEBUG, "Write " PD_UPG_SOFTWARE " ERROR\r\n"); return E_SYS_CALL; } close(fd); /* 升级 */ rv = pd_upg_start(PD_UPG_FROM_DBG, type); if (rv != E_NONE) { DBG(DBG_M_DEBUG, "Write " PD_UPG_SOFTWARE " ERROR\r\n"); *rt = 1; _debug_pkt_common_send(buf, head->cmd, 4); } return rv; } /* 报文校验. */ int32_t _debug_pkt_check(char *buf, int len) { dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; uint16_t *tail = (uint16_t*)(buf + len - 2); DBG(DBG_M_DEBUG, "receive data head->head is 0X%X!,tail is 0X%X!\r\n", head->head, *tail); if (*tail != DEBUG_TAIL) { return E_ERROR; } if(head->head != DEBUG_HEAD) { return E_ERROR; } return E_NONE; } /* 调试工具报文数据处理. */ int32_t _debug_pkt_process(char *buf, int32_t len) { dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf; /* 报文格式检查. */ LD_E_RETURN(DBG_M_DEBUG, _debug_pkt_check(buf, len)); /* 报文处理. */ switch(head->cmd) { case DEBUG_CONFIG_FACTORY_GET: DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_FACTORY_GET data!\r\n"); _debug_pkt_factory_cfg_get(buf, len); break; case DEBUG_CONFIG_FACTORY_SET: DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_FACTORY_SET data!\r\n"); _debug_pkt_factory_cfg_set(buf, len); break; case DEBUG_CONFIG_GLOBAL_GET: DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_GLOBAL_GET data!\r\n"); _debug_pkt_global_cfg_get(buf, len); break; case DEBUG_CONFIG_GLOBAL_SET: DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_GLOBAL_SET data!\r\n"); _debug_pkt_global_cfg_set(buf, len); break; case DEBUG_CONFIG_PORT_GET: DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_PORT_GET data!\r\n"); _debug_pkt_port_cfg_get(buf, len); break; case DEBUG_CONFIG_PORT_SET: DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_GLOBAL_SET data!\r\n"); _debug_pkt_port_cfg_set(buf, len); break; case DEBUG_NOISE_CAREFOR: _debug_pkt_manual_col(buf, len); break; case DEBUG_REBOOT: _debug_pkt_reboot(buf, len); break; case DEBUG_TIME_SET: _debug_pkt_time_set(buf, len); break; case DEBUG_ADJSUT_COEFFICIENT_GET: _debug_pkt_adj_get(buf, len); break; case DEBUG_ADJSUT_COEFFICIENT_SET: _debug_pkt_adj_set(buf, len); break; case DEBUG_DEVICE_STATUS: _debug_pkt_dev_connect_status_get(buf, len); break; case DEBUG_ARM_UPGRADE: _debug_pkt_mcu_upgrade(buf, len); break; case DEBUG_FPGA1_UPGRADE: _debug_pkt_dau_upgrade(buf, len, 0x01); break; case DEBUG_UPGRADE_ALL: _debug_all_upgrade(buf, len); break; default: DBG(DBG_M_DEBUG, "Debug not support cmd:%x\n", head->cmd); break; } return E_NONE; } /* tcp 连接粘包处理函数. */ int32_t _debug_pkt_recv_adhesion(char *buf, int len, int *len_recv) { dbg_pkt_head_t *head = NULL; static int len_pkt = 0; static int bytes_cnt = 0; static int state = 0; if (0 == state) { /* 首包处理. */ head = (dbg_pkt_head_t*)buf; bytes_cnt = 0; if (head->len > 10485000) { /* 报文太长不处理. */ return -1; } else if (0x55aa == head->head) { DBG(DBG_M_DEBUG, "pkt datalen head->len is %d\r\n", head->len); /* 报文头处理, 置标志位. */ state = 1; /* 计算剩余报文长度, 复制数据, 并计算收包总长度. */ len_pkt = head->len + 10 - len; memcpy(buf_cmd + bytes_cnt, buf, len); bytes_cnt += len; /* 计算下一包应该接收多大的数据. */ if (len_pkt > DEBUG_BUG_SIZE) { *len_recv = DEBUG_BUG_SIZE; } else { *len_recv = len_pkt; } } else { /* 在状体 0 下, 收到的报文不是以 0x55aa 开头, 无效报文不处理. */ return -1; } } else if(1 == state) { /* 报文内容处理. */ /* 计算剩余报文长度, 复制数据, 并计算收包总长度. */ len_pkt -= len; memcpy(buf_cmd + bytes_cnt, buf, len); bytes_cnt += len; /* 计算下一包应该接收多大的数据. */ if (len_pkt > DEBUG_BUG_SIZE) { *len_recv = DEBUG_BUG_SIZE; } else { *len_recv = len_pkt; } } /* 报文没有收全, 继续等待数据. */ if (len_pkt > 0) { return 0; } state = 0; return bytes_cnt; } int _debug_keep_alive(int fd) { // 开启保活,保活参数 表示60秒内无交互后,每隔6秒检测一次,40次都没得到响应时会断开连接。 int keep_alive = 1; int keep_idle = 60; int keep_interval = 6; int keep_count = 10; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive, sizeof(keep_alive))) { log_err(LOG_DEBUG, "Error setsockopt(SO_KEEPALIVE) failed, return %s!", safe_strerror(errno)); return -1; } if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_idle, sizeof(keep_idle))) { log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPIDLE) failed, return %s!", safe_strerror(errno)); return -1; } if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval))) { log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPINTVL) failed, return %s!", safe_strerror(errno)); return -1; } if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keep_count, sizeof(keep_count))) { log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPCNT) failed, return %s!", safe_strerror(errno)); return -1; } return 0; } /* 调试工具报文接收处理线程. */ void *_debug_pkt_recv_handle(void *arg) { char *buf = debug_ctrl.buf; int len = 0; int len_pkt = 0; int len_recv = DEBUG_BUG_SIZE; while(1) { /* 连接成功. */ len_recv = DEBUG_BUG_SIZE; if (debug_ctrl.fd_client > 0) { /* 读取数据. */ len = read(debug_ctrl.fd_client, buf, len_recv); if (len <= 0) { /* 连接中断, 关闭 socket 和手动采样. */ DBG(DBG_M_DEBUG, "Read len %d, close fd!\r\n", len); debug_ctrl.is_manual_col = FALSE; close(debug_ctrl.fd_client); debug_ctrl.fd_client = -1; break; } /* 粘包处理. */ len_pkt = _debug_pkt_recv_adhesion(buf, len, &len_recv); if (len_pkt <= 0) { continue; } _debug_pkt_process(buf_cmd, len_pkt); len_recv = DEBUG_BUG_SIZE; } usleep(10*1000); } pthread_exit("thread exit"); return NULL; } int32_t _debug_create_recv_thread() { 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, _debug_pkt_recv_handle, NULL); if (rv != 0) { log_err(LOG_DEBUG, "PD can't create debug pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DEBUG", thread); } pthread_attr_destroy(&attr); return E_NONE; } void *_debug_accept_connect_handle() { struct sockaddr_in cliaddr = {0}; socklen_t clilen; int connfd; /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } /* 监听端口. */ if ((listen(debug_ctrl.fd, 5)) != 0) { log_err(LOG_DEBUG, "ERROR at socket listen return %s!", safe_strerror(errno)); return NULL; } while (1) { clilen = sizeof(cliaddr); connfd = accept(debug_ctrl.fd, (struct sockaddr*)&cliaddr, &clilen); if (connfd < 0) { log_err(LOG_DEBUG, "ERROR at socket accept return %s!", safe_strerror(errno)); continue; } char buf[20] = {0}; DBG(DBG_M_DEBUG, "new client: %s, port: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, buf, sizeof(buf)), ntohs(cliaddr.sin_port)); if (debug_ctrl.fd_client < 0) { debug_ctrl.fd_client = connfd; _debug_create_recv_thread(); _debug_keep_alive(debug_ctrl.fd_client); } else { DBG(DBG_M_DEBUG, "There is a link trying to connect...\n"); close(connfd); connfd = -1; } } return NULL; } /* 用于定时将端口的状态发送给调试软件. */ void* _debug_port_state_get(void *arg) { /* 如果手动采样开启, 则发送数据. */ if (debug_ctrl.is_manual_col) { debug_pkt_port_state_post(); } /* 重新加入定时器. */ mtimer_add(_debug_port_state_get, NULL, 1, "DEBUG_PORT_STATE_GET"); return NULL; } /* Interface functions -------------------------------------------------------*/ /* 调试工具初始化. */ int32_t debug_handle_init(void) { return E_NONE; } int32_t debug_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_DEBUG, "ERROR at socket create return %s!", safe_strerror(errno)); return E_SYS_CALL; } /* fd 为需要端口复用的套接字. */ opt = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt)); /* 绑定端口. */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(DEBUG_MANAGE_TOOL_PORT); if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_DEBUG, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } /* 保存数据. */ debug_ctrl.fd = fd; debug_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, _debug_accept_connect_handle, NULL); if (rv != 0) { log_err(LOG_DEBUG, "PD can't create debug pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("PD_DEBUG_ACCEPT", pid); } pthread_attr_destroy(&attr); /* 每秒上传 DAU 状态寄存器. */ mtimer_add(_debug_port_state_get, NULL, 1, "DEBUG_PORT_STATE_GET"); return E_NONE; } /* 数据手动上传报文处理. */ int32_t debug_pkt_port_state_post(void) {} /* 升级结果回复处理 */ void debug_upgrade_result_send(int32_t rv, char *buf) { char buffer[32] = {0}; int32_t *rt = (int32_t*)(buffer + sizeof(debug_pkt_head_t)); *rt = rv; _debug_pkt_common_send(buffer, DEBUG_UPGRADE_ALL, 4); } #endif /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/