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