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.
263 lines
6.7 KiB
C
263 lines
6.7 KiB
C
/* Includes ------------------------------------------------------------------*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef CFG_DEV_TYPE_LAND_PD
|
|
/* 标准C库头文件. */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/prctl.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <termios.h>
|
|
#include <fcntl.h>
|
|
|
|
/* 用户代码头文件. */
|
|
#include "main.h"
|
|
#include "cmd.h"
|
|
#include "pd_dau.h"
|
|
#include "pd_hf.h"
|
|
#include "pd_csg.h"
|
|
|
|
/* Define --------------------------------------------------------------------*/
|
|
#define DUA_UDP_PORT 23760
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* 上传平台回调函数类型 */
|
|
typedef void (*UploadCallback)(int slot, const void *data, size_t len);
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
pthread_mutex_t board_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
int udp_socket;
|
|
dau_t daus[PD_SLOTS_MAX];
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
|
|
/* Internal functions --------------------------------------------------------*/
|
|
|
|
/* 包头填充 */
|
|
void _dau_head_init(dau_t *dau, dau_head_init_t *head_data)
|
|
{
|
|
dau_pkt_head_t *head = (dau_pkt_head_t*)head_data->pkt;
|
|
|
|
/* 封装报文头. */
|
|
head->len = head_data->len;
|
|
head->dev_type_m = dau->info.type_m;
|
|
head->dev_type_s= dau->info.type_s;
|
|
head->dev_id = dau->info.dev_id;
|
|
head->cmd_type = head_data->cmd_type;
|
|
head->cmd = head_data->cmd;
|
|
head->version = 1;
|
|
head->pkt_id = head_data->pkt_id;
|
|
}
|
|
|
|
void _dau_response(int slot, char *buf, int len)
|
|
{
|
|
printf("_dau_response: slot=%d len=%d\n", slot, len);
|
|
|
|
|
|
if (slot >= 0 && slot < PD_SLOTS_MAX)
|
|
{
|
|
if (daus[slot].type == DAU_TYPE_UDP)
|
|
{
|
|
udp_client_data *client = (udp_client_data*)daus[slot].private_data;
|
|
sendto(udp_socket, buf, len, 0,
|
|
(struct sockaddr*)&client->addr, sizeof(client->addr));
|
|
}
|
|
else if (daus[slot].type == DAU_TYPE_RS485)
|
|
{
|
|
rs485_device_data *dev = (rs485_device_data*)daus[slot].private_data;
|
|
write(dev->fd, buf, len);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* dau 插入处理 */
|
|
int _dau_insert(dau_t *dau)
|
|
{
|
|
if (3 == dau->info.type_m && 1 == dau->info.type_s)
|
|
{
|
|
dau->recv_cb = hf_recv_process;
|
|
}
|
|
else
|
|
{
|
|
return E_NOT_FOUND;
|
|
}
|
|
|
|
dau->state.is_connect = TRUE;
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* 初始化UDP服务器 */
|
|
int32_t _dau_udp_server_init(dau_t *dau)
|
|
{
|
|
struct sockaddr_in server = {0};
|
|
int fd = -1;
|
|
|
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (fd < 0)
|
|
{
|
|
log_err(LOG_DAU, "ERROR at socket creating 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(DUA_UDP_PORT + dau->slot);
|
|
if (bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0)
|
|
{
|
|
log_err(LOG_DAU, "ERROR at socket bind return %s!", safe_strerror(errno));
|
|
close(fd);
|
|
return E_SYS_CALL;
|
|
}
|
|
|
|
dau->fd = fd;
|
|
return E_NONE;
|
|
}
|
|
|
|
/* dau 开机联络处理函数 */
|
|
void _dau_recv_connect(dau_t *dau, uint16_t recv_len)
|
|
{
|
|
dau_head_init_t head_data;
|
|
dau_pkt_head_t *head = (dau_pkt_head_t*)dau->buf_recv;
|
|
dau_contact_t *pnet = (dau_contact_t*)(dau->buf_recv + sizeof(dau_pkt_head_t));
|
|
dau_ack_t *ack = (dau_ack_t*)(dau->buf_recv + sizeof(dau_pkt_head_t));
|
|
|
|
/* 复制设备信息 */
|
|
memcpy(&dau->info, pnet, sizeof(dau_contact_t));
|
|
|
|
/* 添加 dau */
|
|
LD_N_RETURN_N(_dau_insert(dau));
|
|
|
|
/* 回复报文 */
|
|
ack->result = 0;
|
|
head_data.cmd_type = DAU_REQUEST;
|
|
head_data.cmd = DAU_C_CONTACT;
|
|
head_data.pkt_id = head->pkt_id;
|
|
head_data.pkt = dau->buf_recv;
|
|
head_data.len = sizeof(dau_pkt_head_t) + sizeof(dau_ack_t);
|
|
dau_send_data(dau, &head_data);
|
|
|
|
return;
|
|
}
|
|
|
|
/* dau 数据包处理函数 */
|
|
void _dau_recv_data_process(dau_t *dau, uint16_t recv_len, struct sockaddr_in *server)
|
|
{
|
|
dau_pkt_head_t *head = (dau_pkt_head_t*)dau->buf_recv;
|
|
|
|
if (DAU_REPLY == head->cmd_type && DAU_C_CONTACT == head->cmd)
|
|
{
|
|
/* 响应连接报文 */
|
|
if (head->len > DAU_BUF_SIZE)
|
|
{
|
|
DBG(DBG_M_PD_DAU_ERR, "Recvfrom len %d ERROR!\r\n", head->len);
|
|
return;
|
|
}
|
|
|
|
memcpy(&dau->server, server, sizeof(struct sockaddr_in));
|
|
_dau_recv_connect(dau, recv_len);
|
|
}
|
|
else
|
|
{
|
|
/* 响应其他报文 */
|
|
if (dau->recv_cb)
|
|
{
|
|
dau->recv_cb(dau->slot, dau->buf_recv, recv_len);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* dau 收包线程 */
|
|
void *_dau_recv_handle(void *arg)
|
|
{
|
|
dau_t *dau = (dau_t*)arg;
|
|
struct sockaddr_in server;
|
|
socklen_t server_len = sizeof(struct sockaddr_in);
|
|
uint16_t data_len = 0;
|
|
|
|
/* 初始化 socket */
|
|
if (_dau_udp_server_init(dau) != E_NONE)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
/* 读取数据. */
|
|
data_len = recvfrom(dau->fd, dau->buf_recv, DAU_BUF_SIZE, 0, (struct sockaddr*)&server, &server_len);
|
|
if (data_len <= 0)
|
|
{
|
|
DBG(DBG_M_PD_DAU_ERR, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno));
|
|
continue;
|
|
}
|
|
|
|
_dau_recv_data_process(dau, data_len, &server);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* dau 预初始化 */
|
|
int32_t dau_handle_init(void)
|
|
{
|
|
uint8_t i = 0;
|
|
|
|
memset(&daus, 0, sizeof(dau_t) * PD_SLOTS_MAX);
|
|
|
|
for (i = 0; i < PD_SLOTS_MAX; i++)
|
|
{
|
|
daus[i].slot = i;
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* dau 初始化 */
|
|
int32_t dau_handle_init_after(void)
|
|
{
|
|
thread_param_t param = {0};
|
|
uint8_t i = 0;
|
|
|
|
/* 初始收包线程 */
|
|
for (i = 0; i < DAU_ETH_SLOTS_SUM; i++)
|
|
{
|
|
param.arg = (void*)(&daus[i]);
|
|
param.priority = 80;
|
|
param.log_module = LOG_DAU;
|
|
snprintf(param.thread_name, THREAD_NAME_LEN, "DAU_RECV_%d", i);
|
|
create_thread(_dau_recv_handle, ¶m);
|
|
}
|
|
|
|
return E_NONE;
|
|
}
|
|
|
|
/* 数据发送 */
|
|
void dau_send_data(dau_t *dau, dau_head_init_t *head_data)
|
|
{
|
|
int32_t rv = 0;
|
|
|
|
/* 封装报文头. */
|
|
_dau_head_init(dau, head_data);
|
|
|
|
rv = sendto(dau->fd, head_data->pkt, head_data->len, 0, (struct sockaddr*)&dau->server, sizeof(dau->server));
|
|
if (rv < 0)
|
|
{
|
|
DBG(DBG_M_PD_CSG_ERR, "Sendto return %s!\r\n", safe_strerror(errno));
|
|
}
|
|
}
|
|
|
|
#endif
|