/* 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 "fifo.h" #include "pd_net.h" #include "pd_dau.h" #include "main.h" net_t net; void _net_server_set(int32_t ip, uint16_t port); int _net_config_save(vty_t* vty); void _net_sync_time_set(); void _print_sockaddr_in(const struct sockaddr_in *addr) { // 将IP地址从网络字节序转换为点分十进制格式 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &addr->sin_addr, ip_str, sizeof(ip_str)); // 将端口号从网络字节序转换为主机字节序并打印 unsigned short port = ntohs(addr->sin_port); DBG(DBG_M_PD_CSG, "IP Address: %s, Port: %u\r\n", ip_str, port); } CMD(net_server_set, net_server_set_cmd, "net server A.B.C.D <1-65535>", "Net\n" "Server\n" "IPv4 address\n" "UDP port\n") { _net_server_set(inet_addr((char*)argv[0]), strtol((char*)argv[1], NULL, 10)); return CMD_SUCCESS; } /* 设置密码. */ CMD(net_passwd, net_passwd_cmd, "net password WORD", "Net\n" "Passwd\n" "Ex: 1234\n") { memcpy(net.config.passwd, argv[0], 4); return CMD_SUCCESS; } /* 设置校验码. */ CMD(net_verify, net_verify_cmd, "net verify WORD", "Net\n" "Verify\n" "Ex: 1234\n") { memcpy(net.config.verify, argv[0], 4); return CMD_SUCCESS; } CMD(net_test_day, net_test_day_cmd, "net test day WORD", "Net\n" "Test\n" "Day\n" "Ex: net test day 03\n") { net.last_sync_day = atoi( argv[0]); printf("last_sync_day=%d\n", net.last_sync_day); return CMD_SUCCESS; } CMD(net_test_month, net_test_month_cmd, "net test month WORD", "Net\n" "Test\n" "Month\n" "Ex: net test month 03\n") { net.last_sync_mon = atoi( argv[0]); printf("last_sync_mon=%d\n", net.last_sync_mon); return CMD_SUCCESS; } CMD(show_net, show_net_cmd, "show net", SHOW_STR "Displays net config\n") { char tmp[5]; printh("Net Connect: %s\r\n", net.is_connect ? "yes" : "no"); memcpy(tmp, net.config.passwd, 4); tmp[4] = '\0'; printh("passwd: %s\r\n", tmp); memcpy(tmp, net.config.verify, 4); tmp[4] = '\0'; printh("verify: %s\r\n", tmp); printh("heartbeat-interval: %d(min)\r\n", net.config.heartbeat_interval); printh("collect-interval: %d(min)\r\n", net.config.collect_interval); printh("sleep-time: %d(min)\r\n", net.config.sleep_time); printh("online-time: %d(min)\r\n", net.config.online_time); printh("reset-time: %d-%d-%d\r\n", net.config.reset_time.mday, net.config.reset_time.hour, net.config.reset_time.min); printh("dev_id: %04X\r\n", device_info.dev_id); return CMD_SUCCESS; } void _net_server_set(int32_t ip, uint16_t port) { /* 比较配置 */ if (net.server_ip != ip || net.server_port != port) { net.server_ip = ip; net.server_port = port; /* 发送数据. */ bzero(&net.server, sizeof(net.server)); net.server.sin_family = AF_INET; net.server.sin_addr.s_addr = net.server_ip; net.server.sin_port = htons(net.server_port); } } /* 配置保存函数. */ int _net_config_save(vty_t* vty) { int16_t i = 0; struct in_addr addr; char tmp[128]; addr.s_addr = net.server_ip; vty_out(vty, "net server %s %d%s", inet_ntoa(addr), net.server_port, VTY_NEWLINE); i++; memcpy(tmp, net.config.passwd, 4); tmp[4] = '\0'; vty_out(vty, "net password %s%s", tmp, VTY_NEWLINE); i++; memcpy(tmp, net.config.verify, 4); tmp[4] = '\0'; vty_out(vty, "net verify %s%s", tmp, VTY_NEWLINE); i++; return i; } void _net_set_system_time(net_time_t *ptime) { struct tm tptr = {0}; struct timeval tv = {0}; tptr.tm_year = ptime->year + 2000 - 1900; tptr.tm_mon = ptime->month - 1; tptr.tm_mday = ptime->day; tptr.tm_hour = ptime->hour; tptr.tm_min = ptime->minute; tptr.tm_sec = ptime->second; tv.tv_sec = mktime(&tptr); tv.tv_usec = 0; settimeofday(&tv, NULL); } void _net_get_system_time(net_time_t *ptime) { time_t rawtime; struct tm * timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); ptime->year = timeinfo->tm_year + 1900 - 2000; ptime->month = timeinfo->tm_mon + 1; ptime->day = timeinfo->tm_mday; ptime->hour = timeinfo->tm_hour; ptime->minute = timeinfo->tm_min; ptime->second = timeinfo->tm_sec; } long _net_time_to_long(net_time_t *ptime) { struct tm timeinfo; time_t t; // 设置年月日时分秒 timeinfo.tm_year = ptime->year + 2000 - 1900; // 年份需要减去1900 timeinfo.tm_mon = ptime->month - 1; // 月份需要减去1(因为tm_mon是从0开始计数的,即0代表1月) timeinfo.tm_mday = ptime->day; // 日 timeinfo.tm_hour = ptime->hour; // 时 timeinfo.tm_min = ptime->minute; // 分 timeinfo.tm_sec = ptime->second; // 秒 timeinfo.tm_isdst = -1; // 自动判断夏令时 // 将结构体转换为time_t类型 t = mktime(&timeinfo); return t; } void _net_long_to_time(uint32_t rawtime, net_time_t *ptime) { struct tm *timeinfo; timeinfo = localtime((time_t *)&rawtime); ptime->year = timeinfo->tm_year + 1900 - 2000; ptime->month = timeinfo->tm_mon + 1; ptime->day = timeinfo->tm_mday; ptime->hour = timeinfo->tm_hour; ptime->minute = timeinfo->tm_min; ptime->second = timeinfo->tm_sec; } /* 包头填充. */ void _net_head_init(char *buf, uint16_t len, uint8_t cmd) { int slen = 0; int i = 0; char tmp[16] = {0}; net_pkt_head_t *head = (net_pkt_head_t*)buf; snprintf(tmp, 16, "%04X", device_info.dev_id); slen = strlen(tmp); /* 封装报文头. */ head->start_code = NET_START; head->device_id[0] = 'L'; head->device_id[1] = 'D'; head->device_id[2+i] = tmp[slen-4+i]; i++; head->device_id[2+i] = tmp[slen-4+i]; i++; head->device_id[2+i] = tmp[slen-4+i]; i++; head->device_id[2+i] = tmp[slen-4+i]; head->cmd = cmd; head->length = htons(len); } /* 计算校验码(累加和取反) */ uint8_t net_calc_checksum(char *pkt, int len) { uint8_t calc_checksum = 0; const uint8_t* check_ptr = (uint8_t *)(pkt + 1); size_t check_len = 6 + 1 + 2 + len; for (int i = 0; i < check_len; i++) { calc_checksum += check_ptr[i]; } calc_checksum = ~calc_checksum; return calc_checksum; } void _net_send_data(char *pkt, int32_t len, uint8_t cmd) { int32_t rv = 0; int32_t send_len; uint8_t *ptail = (uint8_t *)(pkt + NET_HEADER_LEN + len); /* 封装报文头. */ _net_head_init(pkt, len, cmd); /* 计算校验和. */ *ptail = net_calc_checksum(pkt, len); ptail++; *ptail = NET_END; send_len = len + NET_FIX_LEN; rv = sendto(net.skfd, pkt, send_len, 0, (struct sockaddr*)&net.server, sizeof(net.server)); if (rv < 0) { DBG(DBG_M_PD_NET_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } // 按照原命令返回 void _net_send_data_ex(char *pkt) { net_pkt_head_t *head = (net_pkt_head_t*)pkt; int send_len; int rv; send_len = NET_FIX_LEN + ntohs(head->length); rv = sendto(net.skfd, pkt, send_len, 0, (struct sockaddr*)&net.server, sizeof(net.server)); if (rv < 0) { DBG(DBG_M_PD_NET_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } /* 校验收到包的包头, 长度, 校验码. */ int32_t _net_pkt_check(char *pkt) { net_pkt_head_t *head = (net_pkt_head_t*)pkt; int datalen = 0; uint8_t checksum = 0; uint8_t *pcheck = NULL; datalen = ntohs(head->length); printf("recv:\n"); buf_print(pkt, NET_FIX_LEN + datalen); if (pkt[0] != NET_START && pkt[NET_FIX_LEN + datalen - 1] != NET_END) { DBG(DBG_M_PD_NET_ERR, "expect[%d,%d], but receive[%d,%d].\r\n", NET_START, NET_END, pkt[0], pkt[NET_FIX_LEN + datalen - 1]); return E_ERROR; } pcheck = (uint8_t *)(pkt + NET_HEADER_LEN + datalen); checksum = net_calc_checksum(pkt, datalen); if (*pcheck != checksum) { DBG(DBG_M_PD_NET_ERR, "checksum err %d %d\r\n", *pcheck, checksum); return E_ERROR; } printf("cmd=0x%02x\n", head->cmd); return E_NONE; } void _net_send_contact() { char *pkt = net.buf_send; net_ver_t *pinfo = (net_ver_t *)(pkt + NET_HEADER_LEN); pinfo->major = 0x03; pinfo->minor = 0; _net_send_data(pkt, sizeof(net_ver_t), CMD_CONTACT); } void _net_send_time_adjust() { char *pkt = net.buf_send; _net_send_data(pkt, 0, CMD_TIME_ADJ); } void _net_send_heartbeat() { char *pkt = net.buf_send; net_time_t now; net_heartbeat_t *pinfo = (net_heartbeat_t *)(pkt + NET_HEADER_LEN); _net_get_system_time(&now); pinfo->signal = 88; pinfo->vol = 68; pinfo->time = now; _net_send_data(pkt, sizeof(net_heartbeat_t), CMD_HEARTBEAT); } int _net_send_gis_data() { char *pkt = net.buf_send; pd_trend_t *ptrend = &pd_data.trend; pd_trend_data_t *pPort = NULL; net_gis_head_t *pHead = (net_gis_head_t *)(pkt + NET_HEADER_LEN); net_gis_data_t *pData = NULL; uint8_t unit = 0; uint8_t port = 0; dau_t *dau_node = NULL; int data_len = 0; struct timespec ts; uint8_t err_cnt = 0; DBG(DBG_M_PD_NET_ERR, "fifo send\r\n"); pHead->verify[0] = net.config.verify[0]; pHead->verify[1] = net.config.verify[1]; pHead->verify[2] = net.config.verify[2]; pHead->verify[3] = net.config.verify[3]; pHead->unit = 0x46; data_len = sizeof(net_gis_head_t); for (unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } pHead->pack_num = dau[unit]->port_num; port = 0; while (port < dau[unit]->port_num) { char *ppkt = NULL; pHead->index = port; net.trend_snd_idx = port; if (pHead->index == 0) { net_time_t timer; ppkt = pkt + NET_HEADER_LEN + data_len; _net_long_to_time(ptrend->col.utc, &timer); memcpy(ppkt, &timer, sizeof(net_time_t)); data_len += sizeof(net_time_t); } else { ppkt = pkt + NET_HEADER_LEN + data_len; ppkt[0] = 0; ppkt[1] = 0; data_len += 2; } pPort = &ptrend->col.data[unit][port]; pData = (net_gis_data_t *)(pkt + NET_HEADER_LEN + data_len); pData->discharge_type = 0; pData->capacity = htons(0); pData->noise = htons(pPort->noise * 1.25 * 10); // 1mv = 1.25pc pData->avg = htons(pPort->avg * 1.25 * 10); pData->max = htons(pPort->max * 1.25 * 10); pData->cnt = htons(pPort->cnt); pData->relation50 = htons(0); pData->relation100 = htons(0); data_len += sizeof(net_gis_data_t); _net_send_data(pkt, data_len, CMD_GIS_DATA); DBG(DBG_M_PD_NET_ERR, "pack_num=%d,index=%d\r\n", pHead->pack_num, pHead->index); clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += NET_SEND_TIMEOUT; // 设置 3 秒超时 if (sem_timedwait(&net.trend_sem, &ts) != 0) { err_cnt++; if (err_cnt >= NET_SEND_ERR_CNT) { //_csg_disconnect_set(__FUNCTION__); return E_TIMEOUT; } DBG(DBG_M_PD_NET_ERR, "trend sem error:%s\n", strerror(errno)); continue; } port++; data_len = sizeof(net_gis_head_t); } } return E_NONE; } void _net_handle_contact(char *pkt) { net_pkt_head_t *head = (net_pkt_head_t*)pkt; if (head->length == 0) { _net_send_contact(); } else { net.is_connect = TRUE; log_warn(LOG_NET, "NET connection OK!\n"); } } void _net_handle_time_adjust(char *pkt) { net_time_t *pinfo = (net_time_t *)(pkt + NET_HEADER_LEN); time_t now = time(NULL); long diff; net.is_time_adjust = TRUE; diff = now - _net_time_to_long(pinfo); DBG(DBG_M_PD_NET_ERR, "diff=%ld now=%ld gettime=%ld\n", diff, now, _net_time_to_long(pinfo)); if (abs(now - _net_time_to_long(pinfo)) > NET_ADJUST_TIMEOUT) { _net_set_system_time(pinfo); } _net_sync_time_set(); _net_send_data_ex(pkt); } void _net_handle_set_passwd(char *pkt) { net_passwd_t *pinfo = (net_passwd_t *)(pkt + NET_HEADER_LEN); if (0 == memcmp(pinfo->old, net.config.passwd, 4)) { memcpy(net.config.passwd, pinfo->new, 4); _net_send_data_ex(pkt); vtysh_config_save(); } else { uint16_t *err_code = (uint16_t *)(pkt + NET_HEADER_LEN); *err_code = 0xFFFF; _net_send_data(pkt, 2, CMD_SET_PW); } } void _net_handle_set_param(char *pkt) { net_config_t *pinfo = (net_config_t *)(pkt + NET_HEADER_LEN); if (memcmp(pinfo->passwd, net.config.passwd, sizeof(pinfo->passwd)) == 0) { net.config.heartbeat_interval = pinfo->heartbeat_interval; net.config.collect_interval = ntohs(pinfo->collect_interval); net.config.sleep_time = ntohs(pinfo->sleep_time); net.config.online_time = ntohs(pinfo->online_time); memcpy(&net.config.reset_time, &pinfo->reset_time, 3); memcpy(net.config.verify, pinfo->verify, 4); _net_send_data_ex(pkt); vtysh_config_save(); } else { uint16_t *err_code = (uint16_t *)(pkt + NET_HEADER_LEN); *err_code = 0xFFFF; _net_send_data(pkt, 2, CMD_SET_PARMA); } } void _net_handle_heartbeat(char *pkt) { // do nothing } void _net_handle_reset(char *pkt) { char *pinfo = pkt + NET_HEADER_LEN; if (memcmp(pinfo, net.config.passwd, 4) == 0) { _net_send_data_ex(pkt); sleep(3); reboot_system(LOG_NET, REBOOT_REMOTE_RESET); } else { uint16_t *err_code = (uint16_t *)(pkt + NET_HEADER_LEN); *err_code = 0xFFFF; _net_send_data(pkt, 2, CMD_RESET); } } void _net_handle_gis_data(char *pkt) { net_pkt_head_t *head = (net_pkt_head_t*)pkt; net_gis_reply_t *preply = (net_gis_reply_t *)(pkt + NET_HEADER_LEN); if (head->length != 0) { if (ntohs(head->length) != sizeof(net_gis_reply_t)) { return ; } if (ntohs(preply->fix) != 0xAA55) { return ; } if (net.trend_snd_idx == preply->index) { sem_post(&net.trend_sem); } } else { // 平台主动请求,无数据 _net_send_data_ex(pkt); } } #if 0 void _net_handle_gis_data(char *pkt) { net_pkt_head_t *head = (net_pkt_head_t*)pkt; pd_trend_t *ptrend = &pd_data.trend; pd_trend_data_t *pPort = NULL; net_gis_head_t *pHead = (net_gis_head_t *)(pkt + NET_HEADER_LEN); net_gis_data_t *pData = NULL; uint8_t unit = 0; uint8_t port = 0; dau_t *dau_node = NULL; int send_len = 0; if (head->length != 0) { if (ntohs(head->length) != sizeof(net_gis_reply_t)) { return ; } } pHead->verify[0] = net.config.verify[0]; pHead->verify[1] = net.config.verify[1]; pHead->verify[2] = net.config.verify[2]; pHead->verify[3] = net.config.verify[3]; pHead->identify = 0; pHead->pack_num = 1; pHead->unit = 0x46; _net_long_to_time(ptrend->col.utc, &pHead->time); for (unit = 0; unit < PD_DAU_SUM; unit++) { dau_node = dau[unit]; if (!dau_is_valid(dau_node)) { continue; } for(port = 0; port < dau[unit]->port_num; port++) { send_len = sizeof(net_gis_head_t); pPort = &ptrend->col.data[unit][port]; pData = (net_gis_data_t *)(pkt + NET_HEADER_LEN + send_len); pData->discharge_type = 0; pData->capacity = htons(0); pData->noise = htons(pPort->noise * 1.25 * 10); // 1mv = 1.25pc pData->avg = htons(pPort->avg * 1.25 * 10); pData->max = htons(pPort->max * 1.25 * 10); pData->cnt = htons(pPort->cnt); pData->relation50 = htons(0); pData->relation100 = htons(0); send_len += sizeof(net_gis_data_t); _net_send_data(pkt, send_len, CMD_GIS_DATA); } } } #endif // 命令映射表 static command_entry command_table[] = { {CMD_CONTACT, _net_handle_contact}, {CMD_TIME_ADJ, _net_handle_time_adjust}, {CMD_SET_PW, _net_handle_set_passwd}, {CMD_SET_PARMA, _net_handle_set_param}, {CMD_HEARTBEAT, _net_handle_heartbeat}, {CMD_RESET, _net_handle_reset}, {CMD_GIS_DATA, _net_handle_gis_data}, {CMD_INVALID, NULL} }; command_handler _net_get_table_handle(command_entry *ptable, command_type cmd) { if (NULL == ptable) { return NULL; } for (;CMD_INVALID != ptable->cmd; ptable++) { if (cmd == ptable->cmd) { return ptable->handler; } } return ptable->handler; } int32_t _net_recv_process(char *pkt, uint32_t len) { net_pkt_head_t *head = (net_pkt_head_t *)pkt; command_handler handle = NULL; /* 报文头和 CRC 校验. */ LD_E_RETURN(DBG_M_PD_NET_ERR, _net_pkt_check(pkt)); net.heartbeat_timeout = time(NULL); net.heartbeat_timeout_cnt = 0; handle = _net_get_table_handle(command_table, head->cmd); if (handle) { handle(pkt); } return E_NONE; } /* 平台连接处理函数. */ void *_net_recv_handle(void *arg) { struct sockaddr_in server; socklen_t server_len; int32_t addr = 0; uint16_t data_len = 0; net.heartbeat_timeout = time(NULL); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } prctl(PR_SET_NAME, "NET_RCVE", 0, 0, 0); while(1) { /* 读取数据. */ printf("recv:\n"); _print_sockaddr_in(&server); data_len = recvfrom(net.skfd, net.buf_recv, NET_PKT_LEN, 0, (struct sockaddr*)&server, &server_len); if (data_len <= 0) { DBG(DBG_M_PD_NET_ERR, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno)); continue; } _print_sockaddr_in(&server); addr = server.sin_addr.s_addr; if (addr != net.server_ip) { continue; } _net_recv_process(net.buf_recv, data_len); } return NULL; } void _net_sync_time_set() { time_t now; struct tm *local_time; // 获取当前时间戳 time(&now); // 转换为本地时间结构体 local_time = localtime(&now); net.last_sync_day = local_time->tm_yday; net.last_sync_mon = local_time->tm_mon; DBG(DBG_M_PD_NET_ERR, "last_sync_day=%d tm_yday=%d \n", net.last_sync_day, local_time->tm_yday); } int _net_sync_time_check() { time_t now; struct tm *local_time; int res; // 获取当前时间戳 time(&now); // 转换为本地时间结构体 local_time = localtime(&now); if (net.config.reset_time.mday == 0) { res = (local_time->tm_min == net.config.reset_time.min && local_time->tm_hour == net.config.reset_time.hour && local_time->tm_yday != net.last_sync_day); } else { res = (local_time->tm_min == net.config.reset_time.min && local_time->tm_hour == net.config.reset_time.hour && local_time->tm_mday == net.config.reset_time.mday && local_time->tm_mon != net.last_sync_mon); } #if 0 printf("res=%d\n", res); printf("day hour min\n"); printf("%d %d %d\n", local_time->tm_mday, local_time->tm_hour, local_time->tm_min); printf("%d %d %d\n", net.config.reset_time.mday, net.config.reset_time.hour, net.config.reset_time.min); printf("tm_yday=%d last_sync_day=%d tm_mon=%d last_sync_mon=%d\n", local_time->tm_yday, net.last_sync_day, local_time->tm_mon, net.last_sync_mon); #endif return res; } void _net_restart_4g() { } /* 心跳和连接处理函数. */ void *_net_heartbeat_handle(void *arg) { time_t now = 0; time_t t_connect = 0; time_t t_adjust = 0; time_t t_heartbeat = 0; int connect_cnt = 0; prctl(PR_SET_NAME, "NET_HEARTBEAT", 0, 0, 0); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while(1) { usleep(1000000); now = time(NULL); /* 发送连接报文. */ if (!pd_state.is_4G_connect) continue; if (!net.is_connect) { if (now - t_connect >= NET_CONTACT_TIME) { _net_send_contact(); t_connect = now; connect_cnt++; if (connect_cnt >= NET_CONNECT_TIME_CNT) { reboot_system(LOG_NET, REBOOT_NET_ERROR); } } continue; } connect_cnt = 0; if (!net.is_time_adjust) { if (now - t_adjust >= NET_ADJUST_TIME) { _net_send_time_adjust(); t_adjust = now; } } if (_net_sync_time_check()) { net.is_time_adjust = FALSE; } /* 发送心跳包. */ if (now - t_heartbeat >= pd_config.config.heartbeat_period * 60) { _net_send_heartbeat(); t_heartbeat = now; net.heartbeat_timeout_cnt++; if (net.heartbeat_timeout_cnt > 3) { net.heartbeat_timeout_cnt = 0; net.is_connect = FALSE; } } } return NULL; } void *_net_trend_handle(void *arg) { pd_csg_msg_t *recv_msg = NULL; prctl(PR_SET_NAME, "NET_TREND", 0, 0, 0); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while (1) { if (fifo_read(net.fifo_trend_id, (void**)&recv_msg) != 0) { DBG(DBG_M_PD_NET_ERR, "ERROR at fifo %d read!\r\n", net.fifo_trend_id); continue; } if (net.is_connect) { _net_send_gis_data(); } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); fifo_push(net.fifo_trend_id); } return NULL; } void *_net_event_handle(void *arg) { pd_csg_msg_t *recv_msg = NULL; prctl(PR_SET_NAME, "NET_EVENT", 0, 0, 0); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while (1) { if (fifo_read(net.fifo_event_id, (void**)&recv_msg) != 0) { DBG(DBG_M_PD_NET_ERR, "ERROR at fifo %d read!\r\n", net.fifo_event_id); continue; } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); fifo_push(net.fifo_event_id); } return NULL; } void *_net_realtime_prps_handle(void *arg) { pd_csg_msg_t *recv_msg = NULL; prctl(PR_SET_NAME, "NET_RT_PRPS", 0, 0, 0); /* 等待初始化完成 */ while(!is_system_init) { usleep(100000); } while (1) { if (fifo_read(net.fifo_prps_id, (void**)&recv_msg) != 0) { DBG(DBG_M_PD_NET_ERR, "ERROR at fifo %d read!\r\n", net.fifo_prps_id); continue; } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); fifo_push(net.fifo_prps_id); usleep(10000); } return NULL; } /* 后台通讯公共部分初始化. */ int32_t _net_handle_init_common(void) { struct sockaddr_in server; int fd = 0; thread_param_t param = {0}; /* 创建协议 socket. */ if (0 == net.skfd) { /* 创建socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_NET, "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_NET, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } /* 保存数据. */ net.skfd = fd; } net.fifo_prps_id = fifo_create(NET_FIFO_PRPS, PRPS_FIFO_NUM); if (net.fifo_prps_id < 0) { log_err(LOG_NET, "Open fifo " NET_FIFO_PRPS " error!"); return E_ERROR; } net.fifo_event_id = fifo_create(NET_FIFO_EVENT, EVENT_FIFO_NUM); if (net.fifo_event_id < 0) { log_err(LOG_NET, "Open fifo " NET_FIFO_EVENT " error!"); return E_ERROR; } net.fifo_trend_id = fifo_create(NET_FIFO_TREND, TREND_FIFO_NUM); if (net.fifo_trend_id < 0) { log_err(LOG_NET, "Open fifo " NET_FIFO_TREND " error!"); return E_ERROR; } sem_init(&net.trend_sem, 0, 0); param.arg = NULL; param.log_module = LOG_NET; param.priority = 70; param.thread_name = "NET_RCVE"; create_thread(_net_recv_handle, ¶m); param.priority = 70; param.thread_name = "NET_HEARTBEAT"; create_thread(_net_heartbeat_handle, ¶m); param.priority = 40; param.thread_name = "NET_RT_PRPS"; create_thread(_net_realtime_prps_handle, ¶m); param.priority = 35; param.thread_name = "NET_EVENT"; create_thread(_net_event_handle, ¶m); param.priority = 30; param.thread_name = "NET_TREND"; create_thread(_net_trend_handle, ¶m); return E_NONE; } /* Interface functions -------------------------------------------------------*/ /* 后台通讯模块预初始化. */ int32_t net_handle_init(void) { int32_t rv = 0; memset(&net, 0, sizeof(net)); net.fifo_prps_id = E_MEM; net.fifo_event_id = E_MEM; net.fifo_trend_id = E_MEM; /* 发送数据. */ net.server_ip = inet_addr("192.168.1.161"); net.server_port = 1885; bzero(&net.server, sizeof(net.server)); net.server.sin_family = AF_INET; net.server.sin_addr.s_addr = net.server_ip; net.server.sin_port = htons(net.server_port); memcpy(net.config.passwd, "1234", 4); memcpy(net.config.verify, "1234", 4); net.config.heartbeat_interval = 1; net.config.collect_interval = 20; net.config.sleep_time = 0; net.config.online_time = 0; net.config.reset_time.mday = 0; net.config.reset_time.hour = 23; net.config.reset_time.min = 59; cmd_install_element(CONFIG_NODE, &net_server_set_cmd); cmd_install_element(CONFIG_NODE, &net_passwd_cmd); cmd_install_element(CONFIG_NODE, &net_verify_cmd); cmd_install_element(COMMON_NODE, &net_test_day_cmd); cmd_install_element(COMMON_NODE, &net_test_month_cmd); cmd_install_element(COMMON_NODE, &show_net_cmd); /* 注册配置保存函数 */ rv = cmd_config_node_config_register(CONFIG_PRI_NET, _net_config_save); if (rv != E_NONE) { log_err(LOG_NET, "Command save register ERROR %d!", rv); return rv; } return E_NONE; } /* 南网后台通讯模块初始化. */ int32_t net_handle_init_after(void) { /* 初始化模块. */ if (pd_config.config.protocol_type == PD_PROTOCOL_CSG) { LD_E_RETURN(DBG_M_PD_NET_ERR, _net_handle_init_common()); } return E_NONE; } #endif