You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1095 lines
28 KiB
C

2 days ago
/* Includes ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef CFG_DEV_TYPE_LAND_PD
/* 标准C库头文件. */
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/prctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#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, &param);
param.priority = 70;
param.thread_name = "NET_HEARTBEAT";
create_thread(_net_heartbeat_handle, &param);
param.priority = 40;
param.thread_name = "NET_RT_PRPS";
create_thread(_net_realtime_prps_handle, &param);
param.priority = 35;
param.thread_name = "NET_EVENT";
create_thread(_net_event_handle, &param);
param.priority = 30;
param.thread_name = "NET_TREND";
create_thread(_net_trend_handle, &param);
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