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.

1160 lines
31 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/******************************************************************************
* file lib/process/pd_csg.c
* author YuLiang
* version 1.0.0
* date 27-Feb-2023
* brief This file provides all the csg server operation functions.
*
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT(c) 2021 LandPower</center></h2>
*
* 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 <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
/* 用户代码头文件. */
#include "cmd.h"
#include "fifo.h"
#include "pd_main.h"
#include "pd_dau.h"
#include "pd_csg.h"
/* Private define ------------------------------------------------------------*/
#define CSG_LOCK pthread_mutex_lock(&csg.mutex)
#define CSG_UNLOCK pthread_mutex_unlock(&csg.mutex)
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
csg_t csg;
/* Private function prototypes -----------------------------------------------*/
extern void _csg_server_set(int32_t ip, uint16_t port);
/* 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")
{
return CMD_SUCCESS;
_csg_server_set(inet_addr((char*)argv[0]), strtol((char*)argv[1], NULL, 10));
return CMD_SUCCESS;
}
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);
}
}
/* 配置保存函数. */
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++;
return i;
}
/* 校验收到包的包头, 长度, 校验码. */
int32_t _csg_pkt_check(char *pkt, int32_t len)
{
csg_pkt_head_t *head = (csg_pkt_head_t*)pkt;
csg_pkt_tail_t *tail = (csg_pkt_tail_t*)(pkt + len - CSG_TAIL_LEN);
uint16_t checksum = 0;
uint16_t i = 0;
if (head->head != 0x55aa)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt head %x error!\r\n", head->head);
return E_ERROR;
}
if( tail->tail != 0x5a5a)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt tail %x error!\r\n", tail->tail);
return E_ERROR;
}
if (head->len != (len - CSG_TOTLE_LEN))
{
DBG(DBG_M_PD_CSG_ERR, "Pkt len %d(%d) error!\r\n", len - CSG_TOTLE_LEN, head->len);
return E_ERROR;
}
for (i = CSG_HEAD_LEN; i < len - CSG_TAIL_LEN; i++)
{
checksum += (uint8_t)pkt[i];
}
if (checksum != tail->checksum)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt checksum %x(%x) error!\r\n", checksum, tail->checksum);
return E_ERROR;
}
return E_NONE;
}
/* 包头填充. */
void _csg_head_init(char *buf, uint16_t cmd, uint16_t len)
{
csg_pkt_head_t *head = (csg_pkt_head_t*)buf;
memset(buf, 0, len + CSG_HEAD_LEN);
head->head = 0x55AA;
head->cmd = cmd;
snprintf((char*)head->dev_num, PD_DEV_NUM_LEN, "%s", host.name);
head->len = len;
}
void _csg_cheaksum(char *buf, uint16_t len)
{
char *data = buf + CSG_HEAD_LEN;
csg_pkt_tail_t *tail = (csg_pkt_tail_t*)(data + len);
uint16_t i = 0;
uint16_t checksum = 0;
for(i = 0; i < len; i++)
{
checksum += (uint8_t)data[i];
}
tail->checksum = checksum;
tail->tail = 0x5a5a;
}
/* 主动连接请求. */
int32_t _csg_connect_send(void)
{
char *pkt = csg.buf_reply;
uint16_t *data = (uint16_t*)(pkt + CSG_HEAD_LEN);
int32_t rv = 0;
uint16_t len = 8;
_csg_head_init(pkt, CSG_CONNECT_REQ, len);
*data = sofrware_version_get();
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
return E_NONE;
}
/* 心跳包. */
int32_t _csg_heartbeat_send(void)
{
char *pkt = csg.buf_reply;
csg_pkt_heartbeat_t *data = (csg_pkt_heartbeat_t*)(pkt + CSG_HEAD_LEN);
int32_t rv = 0;
uint16_t len = sizeof(csg_pkt_heartbeat_t);
uint16_t i = 0;
_csg_head_init(pkt, CSG_HEARTBEAT_REQ, len);
data->heartbeat = csg.heartbeat;
data->utc = time(NULL) - CSG_SHIQUCHA;
data->freq = 50;
for(i = 0; i < PD_DAU_SUM; i++)
{
if (dau[i])
{
data->dau_state[i] = dau[i]->is_connect;
}
else
{
data->dau_state[i] = 0;
}
}
data->out_sync = 0;
data->pt_sync = 0;
data->in_sync = 0;
if (dau[0])
{
if (pd_state.sync)
{
if (PD_SYNC_PT == pd_config.config.sync_mode)
{
data->pt_sync = 1;
}
else if (PD_SYNC_POWER == pd_config.config.sync_mode)
{
data->in_sync = 1;
}
else if (PD_SYNC_OUTSIDE == pd_config.config.sync_mode)
{
data->out_sync = 1;
}
}
}
for(i = 0; i < PD_PORT_SUM; i++)
{
data->port_link_alarm[i] = 0;
}
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
csg.heartbeat++;
if (csg.heartbeat > 3)
{
csg.is_connect = FALSE;
}
return E_NONE;
}
//反馈设置状态的公共函数 2Byte
int32_t _csg_set_state_send(char *pkt, uint16_t cmd, uint8_t vport, uint16_t state)
{
uint16_t *data = (uint16_t*)(pkt + CSG_HEAD_LEN);
int32_t rv = 0;
uint16_t len = 4;
_csg_head_init(pkt, cmd, len);
*data = state;
data++;
*data = vport;
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
return E_NONE;
}
/* 主动提交实时图谱. */
int32_t _csg_real_image_send(pd_prps_t *data)
{
char *buf = csg.buf_send;
csg_real_image_t *head = (csg_real_image_t*)(buf + CSG_HEAD_LEN);
pd_prps_data_t *data_port = NULL;
int32_t rv = 0;
uint16_t len = sizeof(csg_real_image_t) + 1280;
uint8_t i = 0;
uint8_t unit = 0;
uint8_t port = 0;
_csg_head_init(buf, CSG_REAL_IMAGE_ACK, len);
for(unit = 0; unit < PD_DAU_SUM; unit++)
{
if (!dau[unit])
{
continue;
}
for(port = 0; port < dau[unit]->port_num; port++)
{
if (!pd_config.port_config[unit][port].is_concern
|| !data->data[unit][port].is_valid)
{
continue;
}
data_port = &data->data[unit][port];
head->index = csg.pkt_index++;
head->vport = dau_port_to_vport(unit, port);
head->pkt_sum = 10;
head->max = data_port->max;
head->avg = data_port->avg;
head->cnt = data_port->cnt;
head->is_sub = 0;
head->interval = 0;
head->utc = time(NULL) - CSG_SHIQUCHA - CSG_SHIQUCHA;
for (i = 0; i < 10; i++)
{
head->pkt_index = i;
memcpy(buf + CSG_HEAD_LEN + sizeof(csg_real_image_t), data_port->data + 640 * i, 1280);
_csg_cheaksum(buf, len);
rv = sendto(csg.fd, buf, len + CSG_TOTLE_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));
}
}
}
}
return E_NONE;
}
/* 趋势数据发送. */
int32_t _csg_trend_send(pd_trend_t *data)
{
char *buf = csg.buf_send;
csg_trend_head_t *head = (csg_trend_head_t*)(buf + CSG_HEAD_LEN);
csg_trend_t *trend = NULL;
pd_trend_data_t *data_port = NULL;
int32_t rv = 0;
int32_t vport = 0;
uint16_t len = sizeof(csg_trend_head_t);
uint8_t unit = 0;
uint8_t port = 0;
_csg_head_init(buf, CSG_TREND_ACK, len);
head->idx = data->index;
head->is_sub = 0;
head->interval = pd_config.config.trend_period;
head->utc = data->utc - CSG_SHIQUCHA - CSG_SHIQUCHA;
for(unit = 0; unit < PD_DAU_SUM; unit++)
{
if (!dau[unit])
{
continue;
}
for(port = 0; port < dau[unit]->port_num; port++)
{
vport = dau_port_to_vport(unit, port);
if (vport <= 0)
{
continue;
}
trend = &head->data[vport - 1];
data_port = &data->data[unit][port];
trend->is_valid = 1;
trend->max = data_port->max;
trend->avg = data_port->avg;
trend->noise = data_port->noise;
trend->cnt = data_port->cnt;
trend->phase = data_port->phase;
trend->event_cnt = data_port->event_cnt;
}
}
_csg_cheaksum(buf, len);
rv = sendto(csg.fd, buf, len + CSG_TOTLE_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));
return E_ERROR;
}
return E_NONE;
}
//按通道主动提交事件数据
int32_t _csg_event_send(pd_event_t *data)
{
char *buf = csg.buf_send;
csg_event_head_t *head = (csg_event_head_t*)(buf + CSG_HEAD_LEN);
int32_t rv = 0;
uint16_t len = sizeof(csg_event_head_t) + 1280;
uint8_t i = 0;
_csg_head_init(buf, CSG_EVENT_REQ, len);
head->idx = csg.pkt_index++;
head->vport = data->vport;
head->pkt_sum = 10;
head->type = data->type;
head->max = data->max;
head->level = data->level;
head->pd_Type = data->type;
for(i = 0;i < 8; i++)
{
head->type_per[i] = data->type_per[i];
}
head->PositionDistance = data->PositionDistance;
head->utc = data->utc - CSG_SHIQUCHA - CSG_SHIQUCHA;
head->event_idx = data->index;
head->cnt = data->cnt;
for (i = 0; i < 10; i++)
{
head->pkt_idx = i;
memcpy(buf + CSG_HEAD_LEN + sizeof(csg_event_head_t), data->data + 640 * i, 1280);
_csg_cheaksum(buf, len);
rv = sendto(csg.fd, buf, len + CSG_TOTLE_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));
}
}
return E_NONE;
}
void _csg_connect_recv(void)
{
csg.is_connect = TRUE;
csg.heartbeat = 0;
}
/* 解析心跳报文. */
void _csg_heartbeat_recv(char *pkt)
{
csg.heartbeat = 0;
uint32_t server_time = *(uint32_t*)(pkt + CSG_HEAD_LEN);
server_time += CSG_SHIQUCHA;
if (abs(server_time - time(NULL)) > 10)
{
time_set(server_time + 28800); //北京时间
}
}
/* 主动连接请求. */
int32_t _csg_acitve_connect_recv(char *pkt)
{
uint16_t *data = (uint16_t*)(pkt + CSG_HEAD_LEN);
int32_t rv = 0;
uint16_t len = 8;
_csg_head_init(pkt, CSG_CONNECT_REQ, len);
*data = sofrware_version_get();
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
csg.is_connect = TRUE;
csg.heartbeat = 0;
return E_NONE;
}
/* 设备重启报文. */
void _csg_reboot_recv(char *pkt)
{
reboot_system(DBG_M_PD_CSG, BOOT_REMOTE_RESET);
}
/* 厂家参数设置报文处理.
说明修改本地ip 设备ID 服务器地址时需要重启。
*/
int32_t _csg_factory_set_recv(char *pkt)
{
struct sockaddr_in server;
pd_factory_old_t *factory = &pd_config.factory;
uint8_t unit = 0;
uint8_t port = 0;
int32_t vport = 0;
int need_save = 0;
int change_ip = 0;
BOOT_MSG boottype = BOOT_NONE;
memcpy(factory, pkt + CSG_HEAD_LEN, sizeof(pd_factory_old_t) - 24);
if (strncmp((char *)(factory->dev_num), host.name, sizeof(host.name)))
{
snprintf((char*)host.name, PD_DEV_NUM_LEN, "%s", factory->dev_num);
need_save++;
boottype = BOOT_REMOTE_HOST_NAME_CHANGE;
}
if (0 == strncmp((char*)factory->dev_type, "GOM5010", 7))
{
device_info.id_major = 5010;
}
device_info.factory_date = factory->factory_date;
device_info.deployment_date = factory->deployment_date;
server.sin_addr.s_addr = factory->ipv4;
if (strncmp(device_info.host_ip, inet_ntoa(server.sin_addr), sizeof(device_info.host_ip)))
{
snprintf((char*)device_info.host_ip, INET_ADDRSTRLEN, "%s", inet_ntoa(server.sin_addr));
need_save++;
change_ip++;
boottype = BOOT_REMOTE_IP_CHANGE;
}
memcpy(device_info.mac, factory->mac, MAC_ADDR_LEN);
if (csg.server_ip != factory->server_ipv4)
{
csg.server_ip = factory->server_ipv4;
need_save++;
boottype = BOOT_REMOTE_SERVER_IP_CHANGE;
}
if (csg.server_port != factory->server_port)
{
csg.server_port = factory->server_port;
need_save++;
boottype = BOOT_REMOTE_SERVER_PORT_CHANGE;
}
for(unit = 0; unit < PD_DAU_SUM; unit++)
{
if (!dau[unit])
{
continue;
}
for(port = 0; port < dau[unit]->port_num; port++)
{
vport = dau_port_to_vport(unit, port);
if (vport <= 0)
{
continue;
}
dau_port_type_set(unit, port, factory->port_type[vport - 1]);
dau_reg_port_write(unit, port);
need_save++; // save file
}
}
_csg_set_state_send(pkt, CSG_FACTORY_SET_ACK, 0, 1);
if (need_save)
{
vtysh_config_save();
if (change_ip)
{
uint8_t mac[MAC_ADDR_LEN] = {0};
mac_generate_from_ip(device_info.host_ip, mac);
memcpy(device_info.mac, mac, MAC_ADDR_LEN);
vtysh_device_save();
vtysh_eth0_save();
}
}
if (boottype)
{
reboot_system(DBG_M_PD_CSG, boottype);
}
return 0;
}
/* 厂家参数查询报文处理. */
int32_t _csg_factory_get_recv(char *pkt)
{
pd_factory_old_t *factory = &pd_config.factory;
uint16_t len = sizeof(pd_factory_old_t);
uint8_t unit = 0;
uint8_t port = 0;
int32_t vport = 0;
int32_t rv = 0;
_csg_head_init(pkt, CSG_FACTORY_GET_ACK, len);
snprintf((char*)factory->dev_num, PD_DEV_NUM_LEN, "%s", host.name);
snprintf((char*)factory->dev_type, PD_DEV_TYPE_LEN, "GOM%d", device_info.id_major);
factory->factory_date = device_info.factory_date;
factory->deployment_date = device_info.deployment_date;
factory->ipv4 = inet_addr((char*)device_info.host_ip);
memcpy(factory->mac, device_info.mac, MAC_ADDR_LEN);
factory->server_ipv4 = csg.server_ip;
factory->server_port = csg.server_port;
for(unit = 0; unit < PD_DAU_SUM; unit++)
{
if (!dau[unit])
{
continue;
}
for(port = 0; port < dau[unit]->port_num; port++)
{
vport = dau_port_to_vport(unit, port);
if (vport <= 0)
{
continue;
}
factory->port_type[vport - 1] = (dau[unit]->port_reg[port].CR & DAU_CR_PT_Msk) >> DAU_CR_PT_Pos;
}
}
memcpy(pkt + CSG_HEAD_LEN, factory, len);
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
return E_NONE;
}
/* 配置用户参数报文报文处理. */
int32_t _csg_config_set_recv(char *pkt)
{
int need_save = 0;
int cpld_save = 0;
pd_config_old_t *pnet = (pd_config_old_t *)(pkt + CSG_HEAD_LEN);
if ((pd_config.config.sync_mode != pnet->sync_mode)
|| (pd_config.config.real_period != pnet->real_period)
|| (pd_config.config.trend_period != pnet->trend_period)
|| (pd_config.config.heartbeat_period != pnet->heartbeat_period))
{
need_save++;
}
if (pd_config.config.sync_mode != pnet->sync_mode)
{
cpld_save++;
}
memcpy(&pd_config.config, pkt + CSG_HEAD_LEN, sizeof(pd_config_old_t));
if (need_save)
{
vtysh_config_save();
}
if (cpld_save)
{
pd_sync_mode_set();
}
return _csg_set_state_send(pkt, CSG_CONFIG_SET_ACK, 0, 1);
}
/* 查询用户参数查询报文处理. */
int32_t _csg_config_get_recv(char *pkt)
{
uint16_t len = sizeof(pd_config_old_t);
int32_t rv = 0;
_csg_head_init(pkt, CSG_CONFIG_GET_ACK, len);
memcpy(pkt + CSG_HEAD_LEN, &pd_config.config, len);
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
return E_NONE;
}
/* 通道提交端口参数设置. */
int32_t _csg_port_config_set_recv(char *pkt)
{
uint8_t vport = *(uint8_t*)(pkt + CSG_HEAD_LEN);
uint8_t unit = 0;
uint8_t port = 0;
if (dau_vport_to_port(vport, &unit, &port) != E_NONE)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", vport);
return _csg_set_state_send(pkt, CSG_PORT_CONFIG_SET_ACK, vport, 0);
}
memcpy(&pd_config.port_config[unit][port].config, pkt + CSG_HEAD_LEN, sizeof(pd_port_config_old_t));
pd_config.port_config[unit][port].filter_cfg = pd_config.port_config[unit][port].config.filter;
dau_port_config_set(unit, port);
dau_reg_port_write(unit, port);
vtysh_config_save();
return _csg_set_state_send(pkt, CSG_PORT_CONFIG_SET_ACK, vport, 1);
}
/* 按通道提交端口参数查询结果. */
int32_t _csg_port_config_get_recv(char *pkt)
{
uint8_t vport = *(uint8_t*)(pkt + CSG_HEAD_LEN);
uint16_t len = sizeof(pd_port_config_old_t);
uint8_t unit = 0;
uint8_t port = 0;
int32_t rv = 0;
if (dau_vport_to_port(vport, &unit, &port) != E_NONE)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", vport);
return E_ERROR;
}
_csg_head_init(pkt, CSG_PORT_CONFIG_GET_ACK, len);
memcpy(pkt + CSG_HEAD_LEN, &pd_config.port_config[unit][port].config, len);
_csg_cheaksum(pkt, len);
rv = sendto(csg.fd, pkt, len + CSG_TOTLE_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));
return E_SYS_CALL;
}
return E_NONE;
}
/* 召唤趋势数据. */
int32_t _csg_trend_get_recv(char *pkt)
{
#if 0
uint32_t time_start = *(uint32_t*)pkt;
uint32_t time_end = *(uint32_t*)(pkt+4);
struct tm *lt = localtime(&time_start);
char basePath[256] = {0};
sprintf(basePath,"%s/%s/%d/%02d/",fixedHead,"Trend",lt->tm_year+1900,lt->tm_mon+1);
img_num=0;
if(!readFileList(basePath))LOG_ERR_RETURN
int i = 0,fLen = 0;
for(i = 0;i < img_num;i ++)
{
int fileUtc = getUctByFileName(img_path[i]);
if(fileUtc >= startTime && fileUtc <= stopTime)
{
U8 *pFile = NULL;
fLen = ReadHexFile(img_path[i],&pFile);
if(fLen < sizeof(strTrendData))continue;
csgAutoPostHufTrend((strTrendData *)pFile,true);
}
}
#endif
return E_NONE;
}
/* 解析HUF实时图谱召唤报文. */
void _csg_real_image_recv(char *pkt)
{
csg_real_image_get_t *data = (csg_real_image_get_t*)(pkt + CSG_HEAD_LEN);
uint8_t unit = 0;
uint8_t port = 0;
if (dau_vport_to_port(data->vport, &unit, &port) != E_NONE)
{
DBG(DBG_M_PD_CSG_ERR, "Pkt port %d error!\r\n", data->vport);
return;
}
pd_config.port_config[unit][port].r_noise_reduction = data->r_noise_reduction;
pd_config.port_config[unit][port].auto_noise_reduction = data->auto_noise_reduction;
pd_config.port_config[unit][port].manual_noise_reduction = data->manual_noise_reduction * 10;
pd_config.port_config[unit][port].is_concern = data->is_concern;
if (data->is_concern)
{
BITMAP_SET(pd_config.concern_bitmap, data->vport - 1);
if ((data->filter > 0 && data->filter < 5)
&& data->filter != pd_config.port_config[unit][port].filter_cfg)
{
pd_config.port_config[unit][port].filter_cfg = data->filter;
dau_port_config_set(unit, port);
dau_reg_port_write(unit, port);
}
}
else
{
BITMAP_RESET(pd_config.concern_bitmap, data->vport - 1);
if (pd_config.port_config[unit][port].filter_cfg != pd_config.port_config[unit][port].config.filter)
{
pd_config.port_config[unit][port].filter_cfg = pd_config.port_config[unit][port].config.filter;
dau_port_config_set(unit, port);
dau_reg_port_write(unit, port);
}
}
}
/* DAU 报文发送处理. */
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, len));
/* 共有命令处理. */
switch (head->cmd)
{
case CSG_CONNECT_ACK:
_csg_connect_recv();
break;
case CSG_HEARTBEAT_ACK:
_csg_heartbeat_recv(pkt);
break;
case CSG_ACITVE_CONNECT_REQ:
_csg_acitve_connect_recv(pkt);
break;
case CSG_REBOOT_REQ:
_csg_reboot_recv(pkt);
break;
case CSG_FACTORY_SET_REQ:
_csg_factory_set_recv(pkt);
break;
case CSG_FACTORY_GET_REQ:
_csg_factory_get_recv(pkt);
break;
case CSG_CONFIG_SET_REQ:
_csg_config_set_recv(pkt);
break;
case CSG_CONFIG_GET_REQ:
_csg_config_get_recv(pkt);
break;
case CSG_PORT_CONFIG_SET_REQ:
_csg_port_config_set_recv(pkt);
break;
case CSG_PORT_CONFIG_GET_REQ:
_csg_port_config_get_recv(pkt);
break;
case CSG_TREND_REQ:
_csg_trend_get_recv(pkt);
break;
case CSG_REAL_IMAGE_REQ:
_csg_real_image_recv(pkt);
break;
default:
//DBG(DBG_M_PD_CSG_ERR, "Cmd %d error!\r\n", head->cmd);
break;
}
csg.communication_time = time(NULL);
return E_NONE;
}
/* 心跳和连接处理函数. */
void *_csg_recv_handle(void *arg)
{
struct sockaddr_in server;
socklen_t server_len;
int32_t addr = 0;
uint16_t data_len = 0;
while (!is_system_init)
{
sleep(1);
}
while(1)
{
/* 读取数据. */
data_len = recvfrom(csg.fd, csg.buf_recv, CSG_PKT_LEN, 0, (struct sockaddr*)&server, &server_len);
if (data_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, data_len);
}
return NULL;
}
/* 向后台服务器发送报文处理函数. */
void *_csg_send_handle(void *arg)
{
pd_csg_msg_t *recv_msg = NULL;
while(1)
{
if (fifo_read(csg.data_fifo_id, (void**)&recv_msg) != 0)
{
DBG(DBG_M_PD_CSG_ERR, "ERROR at fifo %d read!\r\n", csg.data_fifo_id);
continue;
}
if (csg.is_connect)
{
/* 数据处理. */
switch(recv_msg->type)
{
case PD_SEND_TYPE_PRPS:
_csg_real_image_send((pd_prps_t*)recv_msg->data);
break;
case PD_SEND_TYPE_TREND:
_csg_trend_send((pd_trend_t*)recv_msg->data);
break;
case PD_SEND_TYPE_EVENT:
_csg_event_send((pd_event_t*)recv_msg->data);
break;
default:
break;
}
}
/* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */
XFREE(MTYPE_CSG, recv_msg->data);
fifo_push(csg.data_fifo_id);
csg.communication_time = time(NULL);
}
return NULL;
}
/* 心跳和连接处理函数. */
void *_csg_heartbeat_handle(void *arg)
{
time_t now = 0;
time_t t_connect = 0;
time_t t_heartbeat = 0;
while (!is_system_init)
{
sleep(1);
}
while(1)
{
sleep(1);
now = time(NULL);
/* 发送连接报文. */
if (!csg.is_connect)
{
if (now - t_connect >= 10)
{
_csg_connect_send();
t_connect = now;
}
continue;
}
/* 发送心跳包. */
if ((now - t_heartbeat) / 60 >= pd_config.config.heartbeat_period)
{
_csg_heartbeat_send();
t_heartbeat = now;
}
}
return NULL;
}
/* 后台通讯公共部分初始化. */
int32_t _csg_handle_init_common(void)
{
struct sockaddr_in server;
struct sched_param param;
pthread_attr_t attr;
pthread_t pid;
int32_t rv = 0;
int fd = 0;
/* 创建协议 socket. */
if (0 == csg.fd)
{
/* 创建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.server_ip = inet_addr("192.168.1.30");
csg.server_port = 10000;
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);
/* 保存数据. */
csg.fd = fd;
}
csg.data_fifo_id = fifo_create(CSG_DATA_FIFO, 128);
if (csg.data_fifo_id < 0)
{
log_err(LOG_CSG, "Open fifo " CSG_DATA_FIFO " error!");
return E_ERROR;
}
pthread_mutex_init(&csg.mutex, NULL);
/* 配置线程RR调度, 优先级70 */
pthread_attr_init(&attr);
param.sched_priority = 70;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _csg_send_handle, NULL);
if (rv != 0)
{
log_err(LOG_CSG, "PD can't create pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("CSG_SEND", pid);
}
pthread_attr_destroy(&attr);
/* 配置线程RR调度, 优先级70 */
pthread_attr_init(&attr);
param.sched_priority = 70;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _csg_heartbeat_handle, NULL);
if (rv != 0)
{
log_err(LOG_CSG, "PD can't create heartbeat pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("CSG_HEARTBEAT", pid);
}
pthread_attr_destroy(&attr);
/* 配置线程RR调度, 优先级70 */
pthread_attr_init(&attr);
param.sched_priority = 70;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _csg_recv_handle, NULL);
if (rv != 0)
{
log_err(LOG_CSG, "PD can't create recv pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("CSG_RCVE", pid);
}
pthread_attr_destroy(&attr);
return E_NONE;
}
/* Interface functions -------------------------------------------------------*/
/* 后台通讯模块初始化. */
int32_t csg_handle_init(void)
{
int32_t rv = 0;
#if 0
/* 初始化模块. */
LD_E_RETURN(DBG_M_PD_CSG_ERR, _csg_handle_init_common());
#endif
cmd_install_element(CONFIG_NODE, &csg_server_set_cmd);
#if 0
/* 注册配置保存函数 */
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;
}
#endif
return E_NONE;
}
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/