/****************************************************************************** * file lib/process/pd_csg.c * author YuLiang * version 1.0.0 * date 09-Jun-2025 * brief This file provides all the csg server 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 用户代码头文件. */ #include "main.h" #include "cmd.h" #include "fifo.h" #include "pd_main.h" #include "pd_dau.h" #include "pd_csg.h" #include "pd_upgrade.h" /* Private define ------------------------------------------------------------*/ #define CSG_LOCK pthread_mutex_lock(&csg.mutex) #define CSG_UNLOCK pthread_mutex_unlock(&csg.mutex) #define MKDIR(dir) mkdir(dir, 0755) /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ csg_t csg; extern int upg_state; channel_t channel[8]; /* Private function prototypes -----------------------------------------------*/ extern void _csg_server_set(int32_t ip, uint16_t port); extern void _csg_show(); extern int _csg_server_mac_set(char* input); extern void doy_to_date(struct tm *tmpr, uint16_t btime[]); /* Internal functions --------------------------------------------------------*/ CMD(csg_server_set, csg_server_set_cmd, "csg server A.B.C.D <1-65535>", "Csg\n" "Server\n" "IPv4 address\n" "UDP port\n") { _csg_server_set(inet_addr((char*)argv[0]), strtol((char*)argv[1], NULL, 10)); return CMD_SUCCESS; } /* 显示模块状态 */ CMD(csg_show, csg_show_cmd, "show csg", "Show\n" "CSG\n") { _csg_show(); return CMD_SUCCESS; } CMD(csg_server_mac_set, csg_server_mac_set_cmd, "csg serverMac A-B-C-D-E-F", "Csg\n" "Server mac\n" "mac address\n") { int ret = 0; ret = _csg_server_mac_set((char*)argv[0]); return ret; } int _csg_get_connection_status() { int status; pthread_mutex_lock(&csg.lock); status = csg.is_connect; pthread_mutex_unlock(&csg.lock); return status; } void _csg_show() { printh("CSG connect: %s \n", (csg.is_connect == 1)? "OK" : "FAIL"); } /* 设置服务器地址. */ void _csg_server_set(int32_t ip, uint16_t port) { /* 比较配置 */ if (csg.server_ip != ip || csg.server_port != port) { csg.server_ip = ip; csg.server_port = port; /* 发送数据. */ bzero(&csg.server, sizeof(csg.server)); csg.server.sin_family = AF_INET; csg.server.sin_addr.s_addr = csg.server_ip; csg.server.sin_port = htons(csg.server_port); } } /* 设置服务器的 MAC 地址. */ int _csg_server_mac_set(char* input) { uint8_t mac_dest[6]; char *endptr; int i; // 检查参数是否有效 if (!input) { log_err(LOG_CSG, "ERROR: No MAC address provided"); return CMD_ERR_NO_MATCH; } // 复制输入字符串以便安全操作 char mac_str[18]; // 最大长度为 17(12 位十六进制 + 5 个连字符)+ 1(终止符) if (strlen(input) >= sizeof(mac_str)) { log_err(LOG_CSG, "ERROR: MAC address string too long"); return CMD_ERR_NO_MATCH; } strncpy(mac_str, input, sizeof(mac_str) - 1); mac_str[sizeof(mac_str) - 1] = '\0'; // 分割并解析 MAC 地址 char *token = strtok(mac_str, "-"); for (i = 0; i < 6; i++) { if (!token) { log_err(LOG_CSG, "ERROR: Invalid MAC address format, missing segment %d", i + 1); return CMD_ERR_NO_MATCH; } // 重置 errno errno = 0; // 解析十六进制数 long value = strtol(token, &endptr, 16); // 检查是否解析成功 if (endptr == token || *endptr != '\0') { log_err(LOG_CSG, "ERROR: Invalid hex value in segment %d: %s", i + 1, token); return CMD_ERR_NO_MATCH; } // 检查是否在 uint8_t 范围内 if (value < 0 || value > 0xFF || errno == ERANGE) { log_err(LOG_CSG, "ERROR: Value out of range in segment %d: %ld", i + 1, value); return CMD_ERR_NO_MATCH; } // 存储到 mac_dest mac_dest[i] = (uint8_t)value; // 获取下一个 token token = strtok(NULL, "-"); } // 检查是否有额外的 token if (strtok(NULL, "-") != NULL) { log_err(LOG_CSG, "ERROR: Too many segments in MAC address"); return CMD_ERR_NO_MATCH; } // 打印结果(用于调试) printf("server mac address: %02X:%02X:%02X:%02X:%02X:%02X\n", mac_dest[0], mac_dest[1], mac_dest[2], mac_dest[3], mac_dest[4], mac_dest[5]); return CMD_SUCCESS; } /* 配置保存函数. */ int _csg_config_save(vty_t* vty) { int16_t i = 0; struct in_addr addr; addr.s_addr = csg.server_ip; vty_out(vty, "csg server %s %d%s", inet_ntoa(addr), csg.server_port, VTY_NEWLINE); i++; vty_out(vty, "csg serverMac %02x-%02x-%02x-%02x-%02x-%02x%s", csg.dest_mac[0], csg.dest_mac[1], csg.dest_mac[2], csg.dest_mac[3], csg.dest_mac[4], csg.dest_mac[5], VTY_NEWLINE); i++; return i; } /* 校验收到包的包头, 长度, 校验码. */ int32_t _csg_pkt_check(char *pkt) { //unsigned int crc = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; /* 对主次设备号进行识别, 次设备号可以是广播. */ if (head->dev_id != device_info.dev_id || head->dev_type_m != device_info.type_m || head->dev_type_s != device_info.type_s) { DBG(DBG_M_PD_CSG_ERR, "Device type not match:0x%x(0x%x) %d-%d(%d-%d)\r\n", device_info.dev_id, head->dev_id, device_info.type_m, device_info.type_s, head->dev_type_m, head->dev_type_s); return E_ERROR; } if (head->len > 2048) { DBG(DBG_M_PD_CSG_ERR, "@2 receive packet len(%d) is out of range\r\n", head->len); return E_ERROR; } return E_NONE; } /* 包头填充. */ void _csg_head_init(char *buf, uint16_t len, uint8_t cmdType, uint8_t cmd) { csg_pkt_head_t *head = (csg_pkt_head_t*)buf; /* 封装报文头. */ head->len = len; head->dev_type_m = device_info.type_m; head->dev_type_s= device_info.type_s; head->dev_id = device_info.dev_id; head->cmd_type = cmdType; head->cmd = cmd; head->version = 1; head->pkt_id = csg.pkt_index++; } /* 数据发送 */ void _csg_send_data(uint8_t cmd_type, uint8_t cmd, char *pkt, int32_t len) { int32_t rv = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; /* 封装报文头. */ _csg_head_init(pkt, sizeof(csg_pkt_head_t) + len, cmd_type, cmd); rv = sendto(csg.skfd, pkt, head->len, 0, (struct sockaddr*)&csg.server, sizeof(csg.server)); if (rv < 0) { DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } /* 与后台连接断开 */ void _csg_disconnect_set(const char *message) { if (csg.is_connect) { csg.is_connect = FALSE; log_warn(LOG_CSG, "[%s]CSG Connection lost!!!\r\n", message); } } /* 主动连接请求. */ int32_t _csg_connect_send(void) { char *pkt = csg.buf_send; csg_contact_t *pinfo = (csg_contact_t *)(pkt + sizeof(csg_pkt_head_t)); pinfo->type_m = device_info.type_m; pinfo->type_s = device_info.type_s; pinfo->dev_id = device_info.dev_id; strncpy(pinfo->hostname, host.name, sizeof(pinfo->hostname)-1); pinfo->factory_date = device_info.factory_date; pinfo->deployment_date = device_info.deployment_date; strncpy((char *)pinfo->app_version, host.version, sizeof(pinfo->app_version)-1); strncpy((char *)pinfo->app_compile_time, host.compile, sizeof(pinfo->app_compile_time)-1); //strncpy((char *)pinfo->hardware_version, host.hardversion, 31); //strncpy((char *)pinfo->FPGA_version, host.FPGAversion, 31); strncpy((char *)pinfo->hardware_version, "RFSOC_V1.0", 31); strncpy((char *)pinfo->FPGA_version, "20250730", 31); pinfo->ip = device_info.ip; pinfo->mask = device_info.mask; pinfo->gw = device_info.gw; memcpy(pinfo->mac, device_info.mac, sizeof(pinfo->mac)); pinfo->server_port = csg.server_port; pinfo->server_ipv4 = csg.server_ip; memset(pinfo->port, 0, sizeof(pinfo->port)); memset(pinfo->port, 0, sizeof(pinfo->port_type)); for (int i = 0; i < 8; i++) { pinfo->port[i] = i + 1; pinfo->port_type[i] = 1; } _csg_send_data(CSG_REPLY, CSG_C_CONTACT, pkt, sizeof(csg_contact_t)); return E_NONE; } /* 心跳包. */ int32_t _csg_heartbeat_send(void) { char *pkt = csg.buf_send; csg_heartbeat_t *pinfo = (csg_heartbeat_t *)(pkt + sizeof(csg_pkt_head_t)); uint16_t i = 0; pinfo->power_freq = 50; //电网频率默认为50Hz,后续获取实际值 pinfo->pt_sync_mode = 0; for(i = 0; i < PD_DAU_PORT_SUM; i++) { pinfo->dau_state[i] = pd_config.config_port[0][i].is_enbale; } pinfo->dau_port_nums = PD_DAU_PORT_SUM; _csg_send_data(CSG_REPLY, CSG_C_HEARTBEAT, pkt, sizeof(csg_heartbeat_t)); return E_NONE; } int32_t _csg_trend_send(pd_trend_port_t *ptrend) { char *pkt = csg.buf_send; csg_trend_t *pinfo = (csg_trend_t *)(pkt + sizeof(csg_pkt_head_t)); pinfo->port = ptrend->port + 1; pinfo->century_second = ptrend->century_second; pinfo->pulse_num = ptrend->pulse_num; pinfo->pulse_max = ptrend->pulse_max; pinfo->pulse_avg = ptrend->pulse_avg; pinfo->noise = ptrend->noise; pinfo->phase = ptrend->phase; _csg_send_data(CSG_PRV_REPLY, CSG_PRV_TREND, pkt, sizeof(csg_trend_t)); return E_NONE; } #if CSG_TYPE_SELF /* 主动提交特征量数据 */ int32_t _csg_real_eigen_send(channel_t * ch, pd_original_port_t *real) { char *pkt = NULL; uint8_t port_idx; uint32_t nums; uint32_t len; int32_t rv = 0; char *data_point = NULL; int fd; if (!ch) { return E_NONE; } port_idx = ch->port; pkt = ch->pbuf; fd = ch->skfd; csg_pkt_head_t *pkt_head = (csg_pkt_head_t*)pkt; pd_original_port_t *data = real; int sum = 0; if (!csg.real_cfg[port_idx].is_concern) { return E_NONE; } if(data->data_vaild == FALSE) { nums = 0; } else { nums = data->frame_numbers; } if(nums > CSG_SEND_SELF_WAVE_NUM) { nums = CSG_SEND_SELF_WAVE_NUM; } ch->times++; ch->eigen.vport = pd_config.config_port[0][port_idx].vport;; ch->eigen.channel_type = pd_config.config_port[0][port_idx].type; ch->eigen.unit = 2; ch->eigen.power_frequency = _pd_get_frequency(); ch->eigen.discharge_nums += data->total_pulse_nums; for (int i = 0; i < nums; i++) { data_point = (char*)(data->original_pointer) + (i * data->single_frame_length * sizeof(int16_t)); if (data_point == NULL) { DBG(DBG_M_PD_CSG_ERR, "Original pointer is NULL for port %d!\r\n", port_idx); return E_ERROR; } wave_additional_data_t *header = _dau_get_wave_addtion_data(data_point, data->single_frame_length); if (!header) { DBG(DBG_M_PD_CSG_ERR, "addion data is NULL\r\n"); return E_ERROR; } ch->noise_sum += abs(header->noise); if (header->max > ch->eigen.pulse_peak) { ch->eigen.pulse_peak = header->max; } if (ch->times == 1) { ch->eigen.first_sec = header->epoch_sec; ch->eigen.first_ns = header->nano_sec; } else if (ch->times == 500) { ch->eigen.last_sec = header->epoch_sec; ch->eigen.last_ns = header->nano_sec; } ch->wave[ch->inums+i].amplitude = header->max; ch->wave[ch->inums+i].period = ch->cycle++; if (ch->cycle > 50) ch->cycle = 1; ch->wave[ch->inums+i].phase = header->phase; } ch->inums += nums; if (ch->times < 500) { return E_NONE; } ch->eigen.frame_num = ch->inums; ch->eigen.noise = ch->noise_sum / ch->inums; int total_len = sizeof(csg_pkt_head_t) + sizeof(csg_eigen_value_t) + sizeof(prps_t) * ch->inums; sum = total_len / CSG_ADBUF_MAX_LEN; if (total_len % CSG_ADBUF_MAX_LEN) { sum += 1; } ch->eigen.pkt_sum = sum; DBG(DBG_M_PD_CSG_EIGEN,"vport=%d pkt_sum=%d noise_sum=%d noise=%d pulse_peak=%d frame_num=%d\r\n", ch->eigen.vport, ch->eigen.pkt_sum, ch->noise_sum, ch->eigen.noise, ch->eigen.pulse_peak, ch->eigen.frame_num); ch->times = 0; ch->inums = 0; ch->noise_sum = 0; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ch->eigen, sizeof(csg_eigen_value_t)); int index = 0; while (index < sum) { ch->eigen.pkt_index = index; len = total_len > CSG_ADBUF_MAX_LEN ? CSG_ADBUF_MAX_LEN : total_len; _csg_head_init(pkt, sizeof(csg_pkt_head_t) + sizeof(csg_eigen_value_t) + len, CSG_PRV_REPLY, CSG_PRV_REAL_EIGEN); memcpy(pkt + sizeof(csg_pkt_head_t) + sizeof(csg_eigen_value_t), (char *)ch->wave, len); total_len -= len; index++; } rv = sendto(fd, pkt, pkt_head->len, 0, (struct sockaddr*)&csg.server, sizeof(csg.server)); if (rv < 0) { DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); usleep(100); } memset(&ch->eigen, 0, sizeof(csg_eigen_value_t)); return E_NONE; } /* 主动提交实时波形 */ int32_t _csg_real_image_send(channel_t * ch, pd_original_port_t *real) { char *data_point = NULL; char *pkt = NULL; char *pdata = NULL; uint8_t port_idx; uint32_t nums; uint32_t len; int32_t rv = 0; int i; int fd; if (!ch) { return E_NONE; } port_idx = ch->port; pkt = ch->pbuf; fd = ch->skfd; csg_pkt_head_t *pkt_head = (csg_pkt_head_t*)pkt; csg_real_image_t *image_head = NULL; pd_original_port_t *data = real; if(data->data_vaild == FALSE) { return E_NONE; } /* 封装帧报文头 */ len = DEFAULT_SEND_WAVE_POINTS * sizeof(int16_t); _csg_head_init(pkt, sizeof(csg_pkt_head_t) + sizeof(csg_real_image_t) + len, CSG_PRV_REPLY, CSG_PRV_REAL_WAVE); /* 波形数据报文头 */ pdata = pkt + sizeof(csg_pkt_head_t); image_head = (csg_real_image_t*)pdata; image_head->channel_id = pd_config.config_port[0][port_idx].vport; image_head->channel_type = pd_config.config_port[0][port_idx].type; image_head->unit = 2; image_head->sample_rate = DEFAULT_SAMPLE_FREQ_MHZ; image_head->record_points = pd_config.config.trigger_sample_nums; //发送10000个点 image_head->pre_trigger = (pd_config.config.trig_location * 100)>>4; image_head->trigger_level = pd_config.config.trig_threshold; image_head->century_second = 0; image_head->nanosecond = 0; image_head->frequency = _pd_get_frequency(); image_head->sampling_time = 2; nums = data->frame_numbers; if(nums > CSG_SEND_SELF_WAVE_NUM) { nums = CSG_SEND_SELF_WAVE_NUM; } for(i = 0; i < nums; i++) { if(csg.new_data_flag[port_idx] == FALSE) { // 发送波形数据 data_point = (char*)(data->original_pointer) + (i * data->single_frame_length * sizeof(int16_t)); if (data_point == NULL) { DBG(DBG_M_PD_CSG_ERR, "Original pointer is NULL for port %d!\r\n", port_idx); return E_ERROR; } wave_additional_data_t *header = _dau_get_wave_addtion_data(data_point, data->single_frame_length); if (!header) { DBG(DBG_M_PD_CSG_ERR, "addion data is NULL\r\n"); return E_ERROR; } image_head->phase = header->phase; image_head->pulse_peak = header->max; image_head->cycle_count = (header->pt_frame_num % 50) + 1; image_head->noise = header->noise; image_head->century_second = header->epoch_sec; image_head->nanosecond = header->nano_sec; memcpy(pkt + sizeof(csg_pkt_head_t) + sizeof(csg_real_image_t), data_point, image_head->record_points*sizeof(int16_t)); rv = sendto(fd, pkt, pkt_head->len, 0, (struct sockaddr*)&csg.server, sizeof(csg.server)); if (rv < 0) { DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); usleep(50); } } else if(csg.new_data_flag[port_idx] == TRUE) { csg.new_data_flag[port_idx] = FALSE; break; } } return E_NONE; } #elif CSG_TYPE_NANRUI /* 主动提交特征量数据 */ int32_t _csg_real_eigen_send(int fd, char buf[], uint8_t port, pd_original_port_t *real, struct sockaddr_ll *sa, uint8_t *dest_mac) { static uint8_t pkt_id[PD_DAU_PORT_SUM] = {0,0,0,0,0,0,0,0}; // 包ID char *pkg_point = NULL; char *pkt = buf; char *pdata = NULL; wave_additional_data_t* wave_additional_data = NULL; uint8_t port_idx = port; uint32_t nums; uint32_t len; uint32_t send_frame_len = 0; //单帧传输长度 int32_t rv = 0; uint32_t i = 0; int16_t temp_max_buf[1] = {1000}; uint16_t temp_phase_buf[1] = {100}; uint16_t time_buf[5]; struct tm tptr = {0}; time_t timestamp; csg_pkt_nanrui_head_t *pkt_head = (csg_pkt_nanrui_head_t *)pkt; pd_original_port_t *data = real; csg_eigen_value_t *eigen_head = NULL; if(data->data_vaild == FALSE) { nums = 0; } else { nums = data->frame_numbers; } len = nums * 4; /* 封装帧报文头 */ memcpy(pkt_head->src_mac, device_info.mac, 6); memcpy(pkt_head->dest_mac, dest_mac, 6); pkt_head->reserve = 0; pkt_head->port_nums = 1; // 发送数据端口数量 pkt_head->cmd_type[0] = 0xf0; pkt_head->cmd_type[1] = 0x10; pkt_id[port_idx]++; if(pkt_id[port_idx] > 127) { pkt_id[port_idx] = 0; } /* 特征量数据报文头 */ pdata = pkt + sizeof(csg_pkt_nanrui_head_t); eigen_head = (csg_eigen_value_t*)pdata; eigen_head->vport = pd_config.config_port[0][port_idx].send_port_num; eigen_head->count = pkt_id[port_idx]; eigen_head->port_type = pd_config.config_port[0][port_idx].type; eigen_head->unit = 2; eigen_head->discharge_nums = nums; eigen_head->ground_noise = 0; eigen_head->century_second = 0; eigen_head->nano_second = 0; //数据 pkg_point = pkt + sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_eigen_value_t); for(i=0; ioriginal_pointer + ((i+1)*data->single_frame_length - ALL_ADDITIONAL_LEN)* sizeof(int16_t)); temp_max_buf[0] = wave_additional_data->max; temp_phase_buf[0] = wave_additional_data->phase * 100; if(i==0) { time_buf[0] = wave_additional_data->year; time_buf[1] = wave_additional_data->day; time_buf[2] = wave_additional_data->hour; time_buf[3] = wave_additional_data->minute; time_buf[4] = wave_additional_data->sec; doy_to_date(&tptr, time_buf); // 转换为 time_t timestamp = mktime(&tptr); eigen_head->ground_noise = wave_additional_data->noise * 10; eigen_head->century_second = timestamp; eigen_head->nano_second = wave_additional_data->nano_sec; // printf("noise:%d\n",eigen_head->ground_noise); } // printf("phase:%d\n",temp_buf[1]); memcpy(pkg_point, (char *)temp_max_buf, 2); memcpy(pkg_point+2, (char *)temp_phase_buf, 2); if(i < nums-1) pkg_point = pkg_point + 4; } send_frame_len = sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_eigen_value_t) + len; rv = sendto(fd, pkt, send_frame_len, 0, (const struct sockaddr *)sa, sizeof(struct sockaddr_ll)); if (rv < 0) { DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); usleep(100); rv = sendto(fd, pkt, send_frame_len, 0, (const struct sockaddr *)sa, sizeof(struct sockaddr_ll)); } return E_NONE; } // 单帧波形数据发送. int _csg_wave_signel_frame_send(int fd, char buf[], char* data_addr, pd_original_port_t *real, uint8_t port, struct sockaddr_ll *sa_temp) { static uint8_t pkt_id[PD_DAU_PORT_SUM] = {0,0,0,0,0,0,0,0}; // 包ID csg_real_image_t *image_head = NULL; pd_original_port_t *data = real; char *pdata = NULL; wave_additional_data_t* wave_additional_data = NULL; char *pkt = buf; uint32_t send_frame_len = 0; //单帧传输长度 uint32_t len = 0; //临时变量 uint16_t i = 0; uint16_t send_nums = 0; //波形分帧传输次数 uint16_t send_remainder = 0; //波形分帧传输剩余点数 int ret = E_NONE; char *data_addr_point = NULL; uint16_t time_buf[5]; struct tm tptr = {0}; time_t timestamp; /* 波形数据报文头 */ pdata = (char *)(pkt + sizeof(csg_pkt_nanrui_head_t)); image_head = (csg_real_image_t*)pdata; image_head->vport = pd_config.config_port[0][port].send_port_num; image_head->port_type = pd_config.config_port[0][port].type; image_head->unit = 2; image_head->sample_freq_val = DEFAULT_SAMPLE_FREQ_MHZ; wave_additional_data = (wave_additional_data_t*)(data_addr + (data->single_frame_length - ALL_ADDITIONAL_LEN)* sizeof(int16_t)); time_buf[0] = wave_additional_data->year; time_buf[1] = wave_additional_data->day; time_buf[2] = wave_additional_data->hour; time_buf[3] = wave_additional_data->minute; time_buf[4] = wave_additional_data->sec; doy_to_date(&tptr, time_buf); // 转换为 time_t timestamp = mktime(&tptr); image_head->century_second = timestamp; image_head->nano_second = wave_additional_data->nano_sec; /* 计算波形传输次数 */ send_nums = DEFAULT_SEND_WAVE_POINTS / CSG_MAX_POINTS; send_remainder = DEFAULT_SEND_WAVE_POINTS % CSG_MAX_POINTS; if(send_nums >= 1) { image_head->sample_nums = CSG_MAX_POINTS; len = CSG_MAX_POINTS * sizeof(int16_t); send_frame_len = sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_real_image_t) + len; for(i=0; i 127) { pkt_id[port] = 0; } image_head->count = pkt_id[port] + 0x80; data_addr_point = data_addr + i*CSG_MAX_POINTS*sizeof(int16_t); memcpy(pkt + sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_real_image_t), (char *)data_addr_point, len); if (sendto(fd, pkt, send_frame_len, 0, (const struct sockaddr *)sa_temp, sizeof(struct sockaddr_ll)) < 0) { ret = E_ERROR; DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } } if(send_remainder != 0) { data_addr_point = data_addr + i*CSG_MAX_POINTS*sizeof(int16_t); image_head->sample_nums = send_remainder; len = send_remainder * sizeof(int16_t); send_frame_len = sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_real_image_t) + len; pkt_id[port]++; if(pkt_id[port] > 127) { pkt_id[port] = 0; } image_head->count = pkt_id[port]; memcpy(pkt + sizeof(csg_pkt_nanrui_head_t) + sizeof(csg_real_image_t), (char *)data_addr_point, len); if (sendto(fd, pkt, send_frame_len, 0, (const struct sockaddr *)sa_temp, sizeof(struct sockaddr_ll)) < 0) { ret = E_ERROR; DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } return ret; } /* 主动提交实时波形*/ int32_t _csg_real_image_send(int fd, char buf[], uint8_t port, pd_original_port_t *real, struct sockaddr_ll *sa, uint8_t *dest_mac) { char *pkt = buf; char *data_point = NULL; uint8_t port_idx = port; uint32_t nums; int32_t rv = 0; uint32_t i = 0; csg_pkt_nanrui_head_t *pkt_head = (csg_pkt_nanrui_head_t *)pkt; pd_original_port_t *data = real; if(data->data_vaild == FALSE) { return E_NONE; } /* 封装帧报文头 */ memcpy(pkt_head->src_mac, device_info.mac, 6); memcpy(pkt_head->dest_mac, dest_mac, 6); pkt_head->reserve = 0; pkt_head->port_nums = 1; // 发送数据端口数量 pkt_head->cmd_type[0] = 0xf0; pkt_head->cmd_type[1] = 0x11; nums = data->frame_numbers; if(nums > CSG_SEND_NR_WAVE_NUM) { nums = CSG_SEND_NR_WAVE_NUM; } for(i = 0; i < nums; i++) { if(csg.new_data_flag[port_idx] == FALSE) { // 发送波形数据 data_point = (char*)(data->original_pointer) + (i * data->single_frame_length * sizeof(int16_t)); if (data_point == NULL) { DBG(DBG_M_PD_CSG_ERR, "Original pointer is NULL for port %d!\r\n", port_idx); return E_ERROR; } rv = _csg_wave_signel_frame_send(fd, pkt, data_point, data, port_idx, sa); if (rv < 0) { DBG(DBG_M_PD_CSG_ERR, "Send wave failed\r\n"); usleep(50); } } else if(csg.new_data_flag[port_idx] == TRUE) { csg.new_data_flag[port_idx] = FALSE; break; } } return E_NONE; } #endif void _csg_connect_recv(char *pkt) { uint32_t server_time = *(uint32_t*)(pkt + sizeof(csg_pkt_head_t)); csg.is_connect = TRUE; csg.heartbeat = 0; // printf("server_time:%d now:%ld\n", server_time, time(NULL)); if (abs(server_time - time(NULL)) > 3) { //server_time += 8*3600; time_set(server_time); //北京时间 _dau_set_time(server_time); } log_warn(LOG_CSG, "CSG connection OK!"); } /* 解析心跳报文. */ void _csg_heartbeat_recv(char *pkt) { csg.heartbeat = 0; uint32_t server_time = *(uint32_t*)(pkt + sizeof(csg_pkt_head_t)); // printf("server_time:%d now:%ld\n", server_time, time(NULL)); if (abs(server_time - time(NULL)) > 3) { //server_time += 8*3600; time_set(server_time); //北京时间 _dau_set_time(server_time); } } /* 设备重启报文. */ void _csg_reboot_recv(char *pkt) { csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_ack_t ack = {0}; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); sleep(3); reboot_system(LOG_CSG, REBOOT_REMOTE_RESET); } /* 厂家参数设置报文处理. 说明: 调用本接口会导致设备重启 */ int32_t _csg_dev_info_set_recv(char *pkt) { csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_dev_info_t *pinfo = (csg_dev_info_t *)(pkt + sizeof(csg_pkt_head_t)); bool change_ip = FALSE; uint8_t mac[MAC_ADDR_LEN] = {0}; device_info.dev_id = pinfo->dev_id; device_info.mask = pinfo->mask; device_info.gw = pinfo->gw; snprintf((char*)device_info.hostname, FILE_NAME_LEN, "%s", pinfo->hostname); if (device_info.ip != pinfo->ip) { device_info.ip = pinfo->ip; change_ip = TRUE; } memcpy(device_info.mac, pinfo->mac, MAC_ADDR_LEN); csg.server_ip = pinfo->server_ipv4; csg.server_port = pinfo->server_port; csg_ack_t ack = {0}; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); vtysh_config_save(); if (change_ip) { mac_generate_from_ip(device_info.ip, mac); memcpy(device_info.mac, mac, MAC_ADDR_LEN); vtysh_eth0_save(); } vtysh_device_save(); reboot_system(LOG_CSG, REBOOT_REMOTE_DEVINFO_CHANGE); return 0; } /* 厂家参数查询报文处理. */ int32_t _csg_dev_info_get_recv(char *pkt) { printf("%s\n", __FUNCTION__); csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_dev_info_t *pinfo = (csg_dev_info_t *)(pkt + sizeof(csg_pkt_head_t)); pinfo->type_m = device_info.type_m; pinfo->type_s = device_info.type_s; pinfo->dev_id = device_info.dev_id; strcpy(pinfo->hostname, device_info.hostname); pinfo->factory_date = device_info.factory_date; pinfo->deployment_date = device_info.deployment_date; strncpy((char *)pinfo->app_compile_time, host.compile, 31); strncpy((char *)pinfo->app_version, host.version, 31); //strncpy((char *)pinfo->hardware_version, host.hardversion, 31); //strncpy((char *)pinfo->FPGA_version, host.FPGAversion, 31); strncpy((char *)pinfo->hardware_version, "RFSOC_V1.0", 31); strncpy((char *)pinfo->FPGA_version, "20250730", 31); pinfo->ip = device_info.ip; pinfo->mask = device_info.mask; pinfo->gw = device_info.gw; memcpy(pinfo->mac, device_info.mac, sizeof(pinfo->mac)); pinfo->server_port = csg.server_port; pinfo->server_ipv4 = csg.server_ip; _csg_send_data(CSG_REPLY, head->cmd, pkt, sizeof(csg_dev_info_t)); return E_NONE; } /* 配置用户参数报文报文处理. */ int32_t _csg_config_set_recv(char *pkt) { csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_global_config_t *config = (csg_global_config_t *)(pkt + sizeof(csg_pkt_head_t)); pd_config.config.sample_frequency = config->sample_frequency; pd_config.config.trigger_sample_nums = config->trigger_sample_numbers; pd_config.config.trig_location = (config->pre_trigger_percent << 4) / 100.00; pd_config.config.trig_threshold = config->trigLevel; pd_config.config.trend_up_period = config->trend_up_period; pd_config.config.heartbeat_period = config->heartbeat_period; pd_config.config.ch_en_mask = config->ch_en_mask; if (config->sync_mode == 0) { BITMAP_RESET(pd_config.config.pt_B_sync_mode, PD_BIT_PT); } else { BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_PT); } pd_config.config.pt_internal_period = 1000000000UL / config->pt_internal_period; vtysh_config_save(); csg_ack_t ack = {0}; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_NONE; } /* 查询用户参数查询报文处理. */ int32_t _csg_config_get_recv(char *pkt) { printf("%s\n", __FUNCTION__); csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_global_config_t *config = (csg_global_config_t *)(pkt + sizeof(csg_pkt_head_t)); config->sample_frequency = pd_config.config.sample_frequency; config->trigger_sample_numbers = pd_config.config.trigger_sample_nums; config->pre_trigger_percent = (uint32_t)(pd_config.config.trig_location * 100 / 16.00 + 0.5); config->trigLevel = pd_config.config.trig_threshold; config->trend_up_period = pd_config.config.trend_up_period; config->heartbeat_period = pd_config.config.heartbeat_period; config->ch_en_mask = pd_config.config.ch_en_mask; if (IS_BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_PT)) { config->sync_mode = 1; } else { config->sync_mode = 0; } config->pt_internal_period = 1000000000UL / pd_config.config.pt_internal_period; _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_global_config_t)); return E_NONE; } /* 配置南瑞参数设置报文处理. */ int32_t _csg_nr_config_set_recv(char *pkt) { int i; int need_save = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_nr_config_t *pnet = (csg_nr_config_t *)(pkt + CSG_HEAD_LEN); if ((pd_config.config.ch_en_mask != pnet->ch_en_mask) || (pd_config.config.trig_threshold != pnet->trigLevel)) { need_save++; if(pnet->ch_en_mask <= 0xFF) { pd_config.config.ch_en_mask = pnet->ch_en_mask; for(i=0; ich_en_mask, 0x1<reg->reg_global.port_enable = pd_config.config.ch_en_mask; } if(pnet->trigLevel <= 32767) { pd_config.config.trig_threshold = pnet->trigLevel; dau[0]->reg->reg_global.trig_threshold = pd_config.config.trig_threshold; } } for(i=0; isend_port_num[i]) { pd_config.config_port[0][i].send_port_num = pnet->send_port_num[i]; dau[0]->reg->reg_port[i].ch_send_num = pd_config.config_port[0][i].send_port_num; need_save++; } } if (need_save) { vtysh_config_save(); } csg_ack_t ack = {0}; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_NONE; } /* 查询南瑞参数查询报文处理. */ int32_t _csg_nr_config_get_recv(char *pkt) { csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_nr_config_t *config = (csg_nr_config_t *)(pkt + sizeof(csg_pkt_head_t)); config->ch_en_mask = pd_config.config.ch_en_mask; config->trigLevel = pd_config.config.trig_threshold; for(int i = 0; i < PD_DAU_PORT_SUM; i++) { config->send_port_num[i] = pd_config.config_port[0][i].send_port_num; } _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_nr_config_t)); return E_NONE; } /* 通道提交端口参数设置. */ int32_t _csg_port_config_set_recv(char *pkt) { uint8_t unit = 0; uint8_t port = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_config_port_t *pnet = (csg_config_port_t *)(pkt + sizeof(csg_pkt_head_t)); csg_config_port_ack_t ack = {0}; if (dau_vport_to_port(pnet->vport, &unit, &port) != E_NONE) { DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", pnet->vport); ack.vport = pnet->vport; ack.result = FALSE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_config_port_ack_t)); _csg_send_data(CSG_REPLY, head->cmd, pkt, sizeof(csg_config_port_ack_t)); } pd_config.config_port[unit][port].vport = pnet->vport; pd_config.config_port[unit][port].type = pnet->channel_type; vtysh_config_save(); ack.vport = pnet->vport; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_config_port_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_config_port_ack_t)); return E_NONE; } /* 按通道提交端口参数查询结果. */ int32_t _csg_port_config_get_recv(char *pkt) { csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_config_port_t *pnet = (csg_config_port_t *)(pkt + sizeof(csg_pkt_head_t)); uint8_t unit = 0; uint8_t port = 0; if (dau_vport_to_port(pnet->vport, &unit, &port) != E_NONE) { DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", pnet->vport); return E_ERROR; } pnet->vport = pd_config.config_port[unit][port].vport; pnet->channel_type = pd_config.config_port[unit][port].type; _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_config_port_t)); return E_NONE; } int32_t _csg_config_eigen_set_recv(char *pkt) { uint8_t vport; uint8_t unit = 0; uint8_t port = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_config_real_wave_t *config = (csg_config_real_wave_t *)(pkt + sizeof(csg_pkt_head_t)); vport = config->vport; DBG(DBG_M_PD_CSG_ERR, "vport:%d is_concern=%d\r\n", config->vport, config->is_concern); if (dau_vport_to_port(vport, &unit, &port) != E_NONE) { DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", vport); csg_ack_t ack = {0}; ack.result = FALSE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); //_csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_PRV_REPLY, head->cmd); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_ERROR; } DBG(DBG_M_PD_CSG_ERR, "vport(%d)-->port(%d)\r\n", vport, port); DBG(DBG_M_PD_CSG_ERR, "is_concern=%d\r\n", config->is_concern); //csg.channel[port].real_cfg.vport = vport; //csg.channel[port].real_cfg.is_concern = config->is_concern; csg.real_cfg[port].vport = vport; csg.real_cfg[port].is_concern = config->is_concern; csg_channel_ack_t ack = {0}; ack.vport = vport; ack.result = TRUE; memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); //_csg_send_data(pkt, (char *)&ack, sizeof(csg_channel_ack_t), CSG_PRV_REPLY, head->cmd); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_NONE; } int32_t _csg_config_eigen_get_recv(char *pkt) { uint8_t vport; uint8_t unit = 0; uint8_t port = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_config_real_wave_t *pinfo = (csg_config_real_wave_t *)(pkt + sizeof(csg_pkt_head_t)); vport = *(uint8_t*)(pkt + CSG_HEAD_LEN); if (dau_vport_to_port(vport, &unit, &port) != E_NONE) { DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", vport); csg_ack_t ack = {0}; ack.result = FALSE; //_csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_PRV_REPLY, head->cmd); memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_ERROR; } //_csg_send_data(pkt, (char *)&csg.channel[port].real_cfg, sizeof(csg_config_real_wave_t), CSG_PRV_REPLY, head->cmd); memcpy(pinfo, &csg.real_cfg[port], sizeof(csg_config_real_wave_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_config_real_wave_t)); return E_NONE; } /* 升级文件接收 */ int32_t _csg_upgrade_recv(char *pkt) { static int fd = -1; static uint32_t fix_len = 0; csg_pkt_head_t *head = (csg_pkt_head_t*)pkt; csg_upgrade_data_t *head_msg = (csg_upgrade_data_t*)(pkt + sizeof(csg_pkt_head_t)); char *pdata = pkt + sizeof(csg_pkt_head_t) + sizeof(csg_upgrade_data_t); csg_upgrade_ack_t ack = {0}; int32_t size = 0; int32_t len_wr = 0; uint32_t offset = 0; csg.is_connect = FALSE; //关闭主动上传 /* 首保处理, 打开文件描述符, 初始化变量 */ if (head_msg->index == 0) { if (fd > 0) { close(fd); fd = -1; } fd = open(PD_UPG_SOFTWARE, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (fd < 0) { DBG(DBG_M_PD_CSG_ERR, "Open file " PD_UPG_SOFTWARE " error!\r\n"); return E_SYS_CALL; } fix_len = head_msg->len; DBG(DBG_M_PD_CSG, "Receive upgrade file start.\r\n"); } // DBG(DBG_M_PD_CSG,"type=%d,sum=%d,index=%d,len=%d,fix_len=%d\r\n", head_msg->type, head_msg->sum, head_msg->index, head_msg->len, fix_len); /* 收包流程 */ size = head_msg->len; offset = head_msg->index * fix_len; if (lseek(fd, offset, SEEK_SET) < 0) { int error = errno; DBG(DBG_M_PD_CSG_ERR, "lseek file " PD_UPG_SOFTWARE " error: %s, fd=%d, offset=%ld\r\n", strerror(error), fd, offset); // 检查具体错误类型 switch(error) { case EBADF: // 无效文件描述符 DBG(DBG_M_PD_CSG_ERR, "Invalid file descriptor\r\n"); break; case EINVAL: // 无效的 whence 或 offset DBG(DBG_M_PD_CSG_ERR, "Invalid offset or whence\r\n"); break; case EOVERFLOW: // offset 过大 DBG(DBG_M_PD_CSG_ERR, "Offset overflow\r\n"); break; } ack.index = head_msg->index; ack.result = FALSE; //_csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_REPLY, head->cmd); memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_SYS_CALL; } // if (lseek(fd, offset, SEEK_SET) < 0) // { // DBG(DBG_M_PD_CSG_ERR, "lseek file " PD_UPG_SOFTWARE " error!\r\n"); // ack.index = head_msg->index; // ack.result = FALSE; // /* 发送应答 */ // _csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_REPLY, head->cmd); // return E_SYS_CALL; // } len_wr = write(fd, pdata, size); if (len_wr != size) { DBG(DBG_M_PD_CSG_ERR, "Write file " PD_UPG_SOFTWARE " error!\r\n"); ack.index = head_msg->index; ack.result = FALSE; /* 发送应答 */ //_csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_REPLY, head->cmd); memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); return E_SYS_CALL; } /* 最后一个报文处理 */ if (head_msg->sum - 1 == head_msg->index) { close(fd); fd = -1; DBG(DBG_M_PD_CSG, "Receive upgrade file end.\r\n"); pd_upg_start(PD_UPG_FROM_CSG, head_msg->type); } ack.index = head_msg->index; ack.result = TRUE; /* 发送应答 */ memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_ack_t)); _csg_send_data(CSG_PRV_REPLY, head->cmd, pkt, sizeof(csg_ack_t)); //_csg_send_data(pkt, (char *)&ack, sizeof(csg_ack_t), CSG_REPLY, head->cmd); return E_NONE; } int32_t _csg_recv_process(char *pkt, uint32_t len) { csg_pkt_head_t *head = (csg_pkt_head_t *)pkt; /* 报文头和 CRC 校验. */ LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_pkt_check(pkt)); if (CSG_REQUEST == head->cmd_type) { switch (head->cmd) { #if CSG_TYPE_SELF case CSG_C_CONTACT: _csg_connect_recv(pkt); break; case CSG_C_HEARTBEAT: _csg_heartbeat_recv(pkt); break; #endif case CSG_C_RESET: _csg_reboot_recv(pkt); break; case CSG_C_UPDATE: _csg_upgrade_recv(pkt); break; case CSG_C_DEV_INFO_SET: _csg_dev_info_set_recv(pkt); break; case CSG_C_DEV_INFO_GET: _csg_dev_info_get_recv(pkt); break; default: break; } } else if (CSG_PRV_REQUEST == head->cmd_type) { switch (head->cmd) { case CSG_PRV_CONFIG_GLOBAL_SET: _csg_config_set_recv(pkt); break; case CSG_PRV_CONFIG_GLOBAL_GET: _csg_config_get_recv(pkt); break; case CSG_PRV_CONFIG_PORT_SET: _csg_port_config_set_recv(pkt); break; case CSG_PRV_CONFIG_PORT_GET: _csg_port_config_get_recv(pkt); break; case CSG_PRV_CONFIG_EIGEN_SET: _csg_config_eigen_set_recv(pkt); break; case CSG_PRV_CONFIG_EIGEN_GET: _csg_config_eigen_get_recv(pkt); break; case CSG_PRV_CONFIG_NANRUI_SET: _csg_nr_config_set_recv(pkt); break; case CSG_PRV_CONFIG_NANRUI_GET: _csg_nr_config_get_recv(pkt); break; default: break; } } return E_NONE; } /* 心跳和连接处理函数. */ void *_csg_recv_handle(void *arg) { struct sockaddr_in server; int32_t addr = 0; socklen_t addr_len = sizeof(server); fd_set readfds; /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } prctl(PR_SET_NAME, "CSG_RCVE", 0, 0, 0); while(1) { // 初始化 fd_set FD_ZERO(&readfds); int max_fd = -1; // 将需要监听的 socket 描述符加入集合,并找出最大的描述符 for (int i = 0; i < csg.num_sockets; i++) { FD_SET(csg.sockfds[i], &readfds); if (csg.sockfds[i] > max_fd) { max_fd = csg.sockfds[i]; } } // 使用 select 等待任何一个 socket 变得可读 // 参数:最大fd+1, 读集合, 写集合, 异常集合, 超时时间(NULL为无限等待) int activity = select(max_fd + 1, &readfds, NULL, NULL, NULL); if ((activity < 0) && (errno != EINTR)) { perror("select error"); } else if (activity > 0) { // 遍历所有 socket,检查哪个有数据到达 for (int i = 0; i < csg.num_sockets; i++) { if (FD_ISSET(csg.sockfds[i], &readfds)) { // 接收数据 memset(csg.buf_recv, 0, sizeof(csg.buf_recv)); memset(&server, 0, sizeof(server)); ssize_t recv_len = recvfrom(csg.sockfds[i], csg.buf_recv, CSG_PKT_LEN, 0, (struct sockaddr*)&server, &addr_len); if (recv_len < 0) { DBG(DBG_M_PD_CSG_ERR, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno)); continue; } addr = server.sin_addr.s_addr; if (addr != csg.server_ip) { continue; } _csg_recv_process(csg.buf_recv, recv_len); } } } } return NULL; } /* 心跳和连接处理函数. */ void *_csg_heartbeat_handle(void *arg) { time_t now = 0; time_t t_connect = 0; time_t t_heartbeat = 0; prctl(PR_SET_NAME, "CSG_HEARTBEAT", 0, 0, 0); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while(1) { usleep(100000); now = time(NULL); /* 发送连接报文. */ if (!csg.is_connect) { if (now - t_connect >= 10) { _csg_connect_send(); t_connect = now; } continue; } /* 发送心跳包. */ if (abs(now - t_heartbeat) / pd_config.config.heartbeat_period >= 1/*pd_config.config.heartbeat_period*/) { _csg_heartbeat_send(); t_heartbeat = now; } } return NULL; } //自有传输协议------------------------------------------------------------------------------------------------------自有传输协议 #if CSG_TYPE_SELF /* 主动提交ad原始波形. */ void *_csg_real_image_handle(void *arg) { channel_t *pch = (channel_t *)arg; pd_csg_msg_t *recv_msg = NULL; socklen_t optlen; int send_size = 16 * 1024 * 1024; int recv_size = 16 * 1024 * 1024; optlen = sizeof(send_size); printf("port = %d skfd = %d \n", pch->port, pch->skfd); if (pch->port >= 8 || pch->skfd < 0) { return NULL; } setsockopt(pch->skfd, SOL_SOCKET, SO_SNDBUF, &send_size, optlen); setsockopt(pch->skfd, SOL_SOCKET, SO_RCVBUF, &recv_size, optlen); pch->pbuf = XMALLOC_Q(MTYPE_CSG, sizeof(CSG_ADBUF_MAX_LEN)); if (!pch->pbuf) { DBG(DBG_M_PD_CSG_ERR, "csg %dport send data malloc failed!\r\n",pch->port); return NULL; } pch->cycle = 1; /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while (1) { if (fifo_read(csg.fifo_real_image_id[pch->port], (void**)&recv_msg) != 0) { DBG(DBG_M_PD_CSG_ERR, "ERROR at fifo %d read!\r\n", csg.fifo_real_image_id[pch->port]); continue; } csg.new_data_flag[pch->port] = FALSE; if (csg.is_connect) { _csg_real_image_send(pch, (pd_original_port_t *)recv_msg->data); //波形数据上传 _csg_real_eigen_send(pch, (pd_original_port_t *)recv_msg->data); //特征数据上传 } XFREE(MTYPE_CSG, recv_msg->data); fifo_push(csg.fifo_real_image_id[pch->port]); } close(pch->skfd); XFREE(MTYPE_CSG, pch->pbuf); pch->pbuf = NULL; return NULL; } //南瑞传输协议---------------------------------------------------------------------------------------------------南瑞传输协议 #elif CSG_TYPE_NANRUI /* 主动提交ad原始波形. */ void *_csg_real_image_handle(void *arg) { unsigned char dest_mac[6] = {0x01, 0x0C, 0xCD, 0x01, 0x00, 0x01}; // 南瑞MAC地址固定 char buf_send[ETH_FRAME_LEN]; uint8_t port = *(uint8_t *)arg; pd_csg_msg_t *recv_msg = NULL; int fd = 0; socklen_t optlen; int send_size = 16 * 1024 * 1024; int recv_size = 16 * 1024 * 1024; optlen = sizeof(send_size); fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (fd < 0) { log_err(LOG_CSG, "ERROR at socket create return %s!", safe_strerror(errno)); return NULL; } setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &send_size, optlen); setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &recv_size, optlen); // 获取网络接口索引 struct ifreq ifr; strncpy(ifr.ifr_name, "eth0", IFNAMSIZ); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { log_err(LOG_CSG, "ERROR at socket create return %s!", safe_strerror(errno)); close(fd); return NULL; } // 设置发送地址 struct sockaddr_ll sa; memset(&sa, 0, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_ifindex = ifr.ifr_ifindex; sa.sll_halen = ETH_ALEN; memcpy(sa.sll_addr, dest_mac, 6); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while (1) { memcpy(dest_mac, csg.dest_mac, 6); memcpy(sa.sll_addr, dest_mac, 6); if (fifo_read(csg.fifo_real_image_id[port], (void**)&recv_msg) != 0) { DBG(DBG_M_PD_CSG_ERR, "ERROR at fifo %d read!\r\n", csg.fifo_real_image_id[port]); continue; } csg.new_data_flag[port] = FALSE; //_csg_real_image_send(fd, buf_send, port, (pd_original_port_t *)recv_msg->data, &sa, dest_mac); //_csg_real_eigen_send(fd, buf_send, port, (pd_original_port_t *)recv_msg->data, &sa, dest_mac); XFREE(MTYPE_CSG, recv_msg->data); fifo_push(csg.fifo_real_image_id[port]); } close(fd); return NULL; } #endif void *_csg_trend_handle(void *arg) { pd_csg_msg_t *recv_msg = NULL; /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while (1) { if (fifo_read(csg.fifo_trend_id, (void**)&recv_msg) != 0) { DBG(DBG_M_PD_CSG_ERR, "ERROR at fifo %d read!\r\n", csg.fifo_trend_id); continue; } if (csg.is_connect) { _csg_trend_send((pd_trend_port_t *)recv_msg->data); } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); fifo_push(csg.fifo_trend_id); } return NULL; } int32_t _csg_udp_create(int port) { int fd; struct sockaddr_in server; /* 创建socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_CSG, "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(9000 + port); if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_CSG, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } return fd; } /* 后台通讯公共部分初始化. */ int32_t _csg_handle_init_common(void) { struct sockaddr_in server; int fd = 0; thread_param_t param = {0}; uint8_t idx = 0; char str[20]; /* 创建协议 socket. */ if (0 == csg.skfd) { /* 创建socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_CSG, "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(7777); if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_CSG, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } /* 保存数据. */ csg.skfd = fd; csg.sockfds[csg.num_sockets] = fd; csg.num_sockets++; } pthread_mutex_init(&csg.mutex, NULL); param.arg = NULL; param.priority = 80; param.thread_name = "CSG_RCVE"; create_thread(_csg_recv_handle, ¶m); #if CSG_TYPE_SELF param.priority = 80; param.thread_name = "CSG_HEARTBEAT"; create_thread(_csg_heartbeat_handle, ¶m); #endif for (idx = 0; idx < PD_DAU_PORT_SUM; idx++) { csg.fifo_real_image_id[idx] = fifo_create(CSG_ORIG_ID, ORI_FIFO_NUM); param.log_module = LOG_CSG; channel_t *pchannel = XMALLOC_Q(MTYPE_CSG, sizeof(channel_t)); if (!pchannel) { DBG(DBG_M_PD_CSG_ERR, "csg port%d malloc channel_t data failed!\r\n", idx); return E_ERROR; } memset(pchannel, 0, sizeof(channel_t)); pchannel->port = idx; fd = _csg_udp_create(idx); if (fd < 0) { XFREE(MTYPE_CSG, pchannel); DBG(DBG_M_PD_CSG_ERR, "csg port%d create udp failed!\r\n", idx); return E_ERROR; } pchannel->skfd = fd; csg.sockfds[csg.num_sockets] = fd; csg.num_sockets++; param.arg = (void *)pchannel; param.priority = 90; sprintf(str,"CSG_RT_REAL_IMAGE%d", idx); param.thread_name = str; create_thread(_csg_real_image_handle, ¶m); if (csg.fifo_real_image_id[idx] < 0) { XFREE(MTYPE_CSG, pchannel); log_err(LOG_CSG, "Open fifo " CSG_ORIG_ID "%d error!",idx); return E_ERROR; } } csg.fifo_trend_id = fifo_create(CSG_FIFO_TREND, CSG_TREND_FIFO_NUM); if (csg.fifo_trend_id < 0) { log_err(LOG_CSG, "Open fifo " CSG_FIFO_TREND " error!"); return E_ERROR; } param.priority = 60; param.thread_name = "CSG_TREND"; create_thread(_csg_trend_handle, ¶m); return E_NONE; } /* Interface functions -------------------------------------------------------*/ /* 后台通讯模块预初始化. */ int32_t csg_handle_init(void) { int32_t rv = 0; unsigned char dest_mac[6] = {0x01, 0x0C, 0xCD, 0x01, 0x00, 0x01}; // 南瑞MAC地址固定 memset(&csg, 0, sizeof(csg_t)); /* 发送数据. */ csg.server_ip = inet_addr("192.168.0.1"); csg.server_port = 1885; bzero(&csg.server, sizeof(csg.server)); csg.server.sin_family = AF_INET; csg.server.sin_addr.s_addr = csg.server_ip; csg.server.sin_port = htons(csg.server_port); memcpy(csg.dest_mac, dest_mac, 6); cmd_install_element(CONFIG_NODE, &csg_server_set_cmd); cmd_install_element(CONFIG_NODE, &csg_server_mac_set_cmd); cmd_install_element(COMMON_NODE, &csg_show_cmd); /* 注册配置保存函数 */ rv = cmd_config_node_config_register(CONFIG_PRI_CSG, _csg_config_save); if (rv != E_NONE) { log_err(LOG_CSG, "Command save register ERROR %d!", rv); return rv; } return E_NONE; } /* description: 远程升级结果返回回调函数 param: rv -- 返回结果 buf -- 描述字符串 return: */ void csg_upgrade_result_send(int32_t rv, char *buf) { csg_upgrade_res_t ack = {0}; char *pkt = csg.buf_send; ack.result = rv; strcpy(ack.context, buf); memcpy(pkt + sizeof(csg_pkt_head_t), (char *)&ack, sizeof(csg_upgrade_res_t)); _csg_send_data(CSG_REPLY, CSG_C_UPDATE_RESULT, pkt, sizeof(csg_upgrade_res_t)); } /* 后台通讯模块初始化. */ int32_t csg_handle_init_after(void) { /* 初始化模块. */ LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_handle_init_common()); return E_NONE; } /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/ #endif