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.

745 lines
18 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 --------------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//dau_t dau;
pthread_mutex_t board_mutex = PTHREAD_MUTEX_INITIALIZER;
int udp_socket;
dau_t daus[PD_SLOTS_MAX];
// 上传平台回调函数类型
typedef void (*UploadCallback)(int slot, const void *data, size_t len);
/* Private function prototypes -----------------------------------------------*/
int _dau_insert(int slot, DauType type);
void _dau_remove(int slot);
extern void _print_sockaddr_in(const struct sockaddr_in *addr);
/* Internal functions --------------------------------------------------------*/
CMD(dau_add,
dau_add_cmd,
"dau <1-6>",
"DAU\n"
"Dau number\n")
{
uint8_t unit = 0;
unit = strtol(argv[0], NULL, 10) - 1;
_dau_insert(unit, DAU_TYPE_UDP);
return CMD_SUCCESS;
}
CMD(no_dau_add,
no_dau_add_cmd,
"no dau <1-6>",
"DAU\n"
"Dau number\n")
{
uint8_t unit = 0;
unit = strtol(argv[0], NULL, 10) - 1;
_dau_remove(unit);
return CMD_SUCCESS;
}
#if 0
// ================== UDP 操作函数 ==================
static int _dau_udp_init(dau_private_data_t *data, const char *config)
{
// 解析配置: "ip:port:board_id"
char ip[32], board_id[32];
int port;
struct sockaddr_in server_addr;
int sockfd;
if (sscanf(config, "%[^:]:%d:%s", ip, &port, board_id) != 3)
{
return -1;
}
// 创建socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
log_err(LOG_DAU, "ERROR at socket create return %s!", safe_strerror(errno));
return E_SYS_CALL;
}
// 设置地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//inet_pton(AF_INET, ip, &server_addr.sin_addr);
// 绑定套接字
if (bind(sockfd, (const struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
log_err(LOG_DAU, "ERROR at socket create return %s!", safe_strerror(errno));
close(sockfd);
return E_SYS_CALL;
}
strncpy(data->board_id, board_id, sizeof(data->board_id));
// 配置缓冲区 (示例)
data->buffer_size = 4096;
data->rx_buffer = malloc(data->buffer_size);
if (!data->rx_buffer)
{
close(sockfd);
return E_SYS_CALL;;
}
//data->comm.udp.addr = server_addr;
data->comm.udp.sockfd = sockfd;
printf("UDP board %s initialized at %s:%d\n",
board_id, ip, port);
return 0;
}
static int _dau_udp_receive(dau_private_data_t *data, void *buf, size_t len)
{
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int data_len = 0;
do
{
data_len = recvfrom(data->comm.udp.sockfd, buf, len, 0,
(struct sockaddr*)&client_addr, &addr_len);
if (data_len <= 0)
{
DBG(DBG_M_PD_DAU_ERR, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno));
continue;
}
// 获取客户端IP和端口
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
int client_port = ntohs(client_addr.sin_port);
//memcpy(&data->comm.add, &client_addr, sizeof(client_addr));
data->comm.udp.addr = client_addr;
printf("Received from %s:%d:\n", client_ip, client_port);
} while(0);
return data_len;
}
static int _dau_udp_transmit(dau_private_data_t *data, const void *buf, size_t len)
{
printf("sockfd=%d\n", data->comm.udp.sockfd);
_print_sockaddr_in(&data->comm.udp.addr);
return sendto(data->comm.udp.sockfd, buf, len, 0,
(struct sockaddr*)&data->comm.udp.addr,
sizeof(data->comm.udp.addr));
}
static void _dau_udp_cleanup(dau_private_data_t *data)
{
if (data->comm.udp.sockfd >= 0)
{
close(data->comm.udp.sockfd);
data->comm.udp.sockfd = -1;
}
if (data->rx_buffer)
{
free(data->rx_buffer);
data->rx_buffer = NULL;
}
printf("UDP board %s cleaned up\n", data->board_id);
}
#endif
#if 0
// ================== RS485 操作函数 ==================
static int _dau_rs485_init(dau_private_data_t *data, const char *config)
{
// 解析配置: "port:baudrate:board_id"
char port[32], board_id[32];
int baudrate;
if (sscanf(config, "%[^:]:%d:%s", port, &baudrate, board_id) != 3) {
return -1;
}
// 打开串口
data->comm.rs485.fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
if (data->comm.rs485.fd < 0)
{
perror("RS485 open failed");
return -1;
}
// 获取当前串口设置
tcgetattr(data->comm.rs485.fd, &data->comm.rs485.options);
// 设置波特率
cfsetispeed(&data->comm.rs485.options, baudrate);
cfsetospeed(&data->comm.rs485.options, baudrate);
// 设置8N1
data->comm.rs485.options.c_cflag &= ~PARENB;
data->comm.rs485.options.c_cflag &= ~CSTOPB;
data->comm.rs485.options.c_cflag &= ~CSIZE;
data->comm.rs485.options.c_cflag |= CS8;
// 应用设置
tcsetattr(data->comm.rs485.fd, TCSANOW, &data->comm.rs485.options);
strncpy(data->board_id, board_id, sizeof(data->board_id));
strncpy(data->comm.rs485.port, port, sizeof(data->comm.rs485.port));
// 配置缓冲区
data->buffer_size = 1024;
data->rx_buffer = malloc(data->buffer_size);
if (!data->rx_buffer) {
close(data->comm.rs485.fd);
return -1;
}
printf("RS485 board %s initialized on %s@%d\n",
board_id, port, baudrate);
return 0;
}
static int _dau_rs485_receive(dau_private_data_t *data, void *buf, size_t len)
{
return read(data->comm.rs485.fd, buf, len);
}
static int _dau_rs485_transmit(dau_private_data_t *data, const void *buf, size_t len)
{
return write(data->comm.rs485.fd, buf, len);
}
static void _dau_rs485_cleanup(dau_private_data_t *data)
{
if (data->comm.rs485.fd >= 0)
{
close(data->comm.rs485.fd);
data->comm.rs485.fd = -1;
}
if (data->rx_buffer)
{
free(data->rx_buffer);
data->rx_buffer = NULL;
}
printf("RS485 board %s cleaned up\n", data->board_id);
}
// ================== 板卡管理函数 ==================
static void _dau_seek_proper_function(int slot, dau_private_data_t *data)
{
if (strncmp(data->board_id, UHF, strlen(UHF)) == 0)
{
}
else if (strncmp(data->board_id, HF, strlen(HF)) == 0)
{
_hf_recv_process(slot, data->rx_buffer);
}
else if (strncmp(data->board_id, ULTRASONIC, strlen(ULTRASONIC)) == 0)
{
}
else if (strncmp(data->board_id, IRONCORE, strlen(IRONCORE)) == 0)
{
}
}
#endif
static int32_t _dau_find_proper_function(char *pkt)
{
int flag = 0;
csg_pkt_head_t *head = (csg_pkt_head_t *)pkt;
for (int i = 0; i < PD_SLOTS_MAX; i++)
{
if (daus[i].slot != head->slot)
continue;
if (daus[i].state == DAU_STATE_REGISTERED)
{
flag = 1;
}
}
if (!flag)
return E_NONE;
if (head->dev_type_m == 0x03)
{
if (head->dev_type_s == 0x01)
{
_hf_recv_process(head->slot, pkt);
}
else if (head->dev_type_s == 0x02)
{}
else if (head->dev_type_s == 0x03)
{}
}
return E_NONE;
}
// 申请板卡私有数据
void* _dau_alloc_private_data(DauType type, int slot)
{
if (type == DAU_TYPE_UDP)
{
udp_client_data *data = malloc(sizeof(udp_client_data));
memset(data, 0, sizeof(udp_client_data));
return data;
}
else if (type == DAU_TYPE_RS485)
{
rs485_device_data *data = malloc(sizeof(rs485_device_data));
memset(data, 0, sizeof(rs485_device_data));
// 根据槽位分配串口设备
//const char *device = (slot == 4) ? "/dev/ttyS0" : "/dev/ttyS1";
//data->fd = init_rs485(device);
data->address = (slot == 4) ? 0x01 : 0x02;
if (data->fd < 0)
{
free(data);
return NULL;
}
return data;
}
return NULL;
}
// 释放板卡私有数据
void _dau_free_private_data(DauType type, void *data)
{
if (!data)
{
return;
}
if (type == DAU_TYPE_UDP)
{
free(data);
}
else if (type == DAU_TYPE_RS485)
{
rs485_device_data *dev = (rs485_device_data*)data;
if (dev->fd >= 0)
{
close(dev->fd);
}
free(data);
}
}
// ================== 板卡管理函数 ==================
#if 0
static void *_dau_thread_func(void *arg)
{
dau_manager_t *manager = (dau_manager_t *)arg;
dau_private_data_t *data = manager->private_data;
prctl(PR_SET_NAME, (unsigned long)data->board_id, 0, 0, 0);
printf("Board thread started for slot %d (%s)\n",
manager->slot, data->board_id);
while (manager->occupied)
{
// 接收数据
ssize_t bytes = manager->ops.receive(data, data->rx_buffer, data->buffer_size);
if (bytes > 0)
{
// 处理数据
printf("Slot %d received %zd bytes\n", manager->slot, bytes);
_dau_seek_proper_function(manager->slot, data);
}
else if (bytes < 0)
{
perror("Receive error");
usleep(100000); // 100ms 延迟后重试
}
}
printf("Board thread exiting for slot %d\n", manager->slot);
return NULL;
}
int _dau_insert(int slot, DauType type, const char *config)
{
if (slot < 0 || slot >= MAX_SLOTS) return -1;
pthread_mutex_lock(&dau.mutex);
if (dau.mgr[slot].occupied)
{
pthread_mutex_unlock(&dau.mutex);
return -2; // 槽位已被占用
}
// 创建私有数据
dau_private_data_t *data = malloc(sizeof(dau_private_data_t));
if (!data)
{
pthread_mutex_unlock(&dau.mutex);
return -3;
}
memset(data, 0, sizeof(dau_private_data_t));
data->type = type;
// 设置操作函数
dau_operations_t ops;
switch (type)
{
case DAU_UDP:
ops.init = _dau_udp_init;
ops.receive = _dau_udp_receive;
ops.transmit = _dau_udp_transmit;
ops.cleanup = _dau_udp_cleanup;
break;
case DAU_RS485:
ops.init = _dau_rs485_init;
ops.receive = _dau_rs485_receive;
ops.transmit = _dau_rs485_transmit;
ops.cleanup = _dau_rs485_cleanup;
break;
default:
free(data);
pthread_mutex_unlock(&dau.mutex);
return -4;
}
// 初始化板卡
if (ops.init(data, config) != 0)
{
free(data);
pthread_mutex_unlock(&dau.mutex);
return -5;
}
// 配置管理器
dau.mgr[slot].private_data = data;
dau.mgr[slot].ops = ops;
dau.mgr[slot].slot = slot + 1;
dau.mgr[slot].occupied = TRUE;
// 创建线程
if (pthread_create(&dau.mgr[slot].thread_id, NULL,
_dau_thread_func, &dau.mgr[slot]) != 0)
{
ops.cleanup(data);
free(data);
memset(&dau.mgr[slot], 0, sizeof(dau_manager_t));
pthread_mutex_unlock(&dau.mutex);
return -6;
}
pthread_mutex_unlock(&dau.mutex);
return 0;
}
int _dau_remove(int slot)
{
if (slot < 0 || slot >= MAX_SLOTS) return -1;
pthread_mutex_lock(&dau.mutex);
if (!dau.mgr[slot].occupied)
{
pthread_mutex_unlock(&dau.mutex);
return -2; // 槽位空闲
}
// 设置停止标志
dau.mgr[slot].occupied = FALSE;
// 等待线程结束
pthread_join(dau.mgr[slot].thread_id, NULL);
// 清理资源
dau.mgr[slot].ops.cleanup(dau.mgr[slot].private_data);
free(dau.mgr[slot].private_data);
memset(&dau.mgr[slot], 0, sizeof(dau_manager_t));
pthread_mutex_unlock(&dau.mutex);
return 0;
}
#endif
int _dau_insert(int slot, DauType type)
{
if (slot < 0 || slot >= PD_SLOTS_MAX)
{
return E_BAD_PARAM;
}
pthread_mutex_lock(&board_mutex);
if (daus[slot].state != DAU_STATE_DISCONNECTED)
{
pthread_mutex_unlock(&board_mutex);
return E_ERROR;
}
// 分配私有数据
void *priv_data = _dau_alloc_private_data(type, slot);
if (!priv_data)
{
pthread_mutex_unlock(&board_mutex);
return E_ERROR;
}
// 更新板卡信息
daus[slot].type = type;
daus[slot].state = DAU_STATE_CONNECTED;
daus[slot].private_data = priv_data;
daus[slot].slot = slot;
pthread_mutex_unlock(&board_mutex);
printf("Board inserted in slot %d (Type: %s)\n",
slot, (type == DAU_TYPE_UDP) ? "UDP" : "RS485");
return E_NONE;
}
void _dau_remove(int slot)
{
pthread_mutex_lock(&board_mutex);
if (daus[slot].state == DAU_STATE_DISCONNECTED)
{
pthread_mutex_unlock(&board_mutex);
return;
}
// 释放资源
_dau_free_private_data(daus[slot].type, daus[slot].private_data);
// 重置板卡信息
daus[slot].type = DAU_TYPE_NONE;
daus[slot].state = DAU_STATE_DISCONNECTED;
daus[slot].private_data = NULL;
pthread_mutex_unlock(&board_mutex);
printf("Board removed from slot %d\n", slot);
}
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);
}
}
}
#if 0
int main() {
_board_init_system();
register_upload_callback(example_upload_callback);
// 插入UDP板卡
_board_insert(0, BOARD_UDP, "192.168.1.100:5000:UDP_CARD_1");
_board_insert(1, BOARD_UDP, "192.168.1.101:5000:UDP_CARD_2");
_board_insert(2, BOARD_UDP, "192.168.1.102:5000:UDP_CARD_3");
_board_insert(3, BOARD_UDP, "192.168.1.103:5000:UDP_CARD_4");
// 插入RS485板卡
_board_insert(4, BOARD_RS485, "/dev/ttyS0:115200:RS485_CARD_1");
_board_insert(5, BOARD_RS485, "/dev/ttyS1:115200:RS485_CARD_2");
// 模拟运行
sleep(5);
// 拔出板卡示例
_board_remove(2);
sleep(2);
// 重新插入板卡
_board_insert(2, BOARD_UDP, "192.168.1.104:5000:UDP_CARD_NEW");
sleep(5);
_board_shutdown_system();
return 0;
}
#endif
// 初始化UDP服务器
int _dau_init_udp_server()
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
{
perror("UDP socket creation failed");
return -1;
}
struct sockaddr_in server_addr =
{
.sin_family = AF_INET,
.sin_port = htons(UDP_PORT),
.sin_addr.s_addr = INADDR_ANY
};
if (bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)))
{
perror("UDP bind failed");
close(sock);
return -1;
}
return sock;
}
void *_dau_manager_handle(void *arg)
{
prctl(PR_SET_NAME, "CSG_RCVE", 0, 0, 0);
while(1)
{
sleep(1);
}
return NULL;
}
void *_dau_udp_receive_handle(void *arg)
{
prctl(PR_SET_NAME, "DAU_RCVE", 0, 0, 0);
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
char buffer[2048];
while(1)
{
ssize_t len = recvfrom(udp_socket, buffer, sizeof(buffer), 0,
(struct sockaddr*)&client_addr, &addr_len);
if (len <= 0) continue;
buffer[len] = '\0';
_print_sockaddr_in(&client_addr);
// 查找匹配的UDP板卡
pthread_mutex_lock(&board_mutex);
for (int i = 0; i < DAU_ETH_SLOTS_SUM; i++)
{
//printf("state=%d\n", daus[i].state);
if (daus[i].state == DAU_STATE_DISCONNECTED)
continue;
udp_client_data *client = (udp_client_data *)daus[i].private_data;
if (memcmp(&client->addr, &client_addr, sizeof(client_addr)) == 0)
{
break;
}
// 如果是新连接
if (daus[i].state == DAU_STATE_CONNECTED &&
client->addr.sin_port == 0)
{
memcpy(&client->addr, &client_addr, sizeof(client_addr));
daus[i].state = DAU_STATE_REGISTERED;
break;
}
}
pthread_mutex_unlock(&board_mutex);
// 处理数据
if (!csg.is_connect)
continue;
_dau_find_proper_function(buffer);
usleep(1000);
}
return NULL;
}
/* dau 预初始化 */
int32_t dau_handle_init(void)
{
memset(&daus, 0, sizeof(dau_t) * PD_SLOTS_MAX);
cmd_install_element(COMMON_NODE, &dau_add_cmd);
cmd_install_element(COMMON_NODE, &no_dau_add_cmd);
return E_NONE;
}
/* dau 初始化 */
int32_t dau_handle_init_after(void)
{
thread_param_t param = {0};
uint8_t i = 0;
if (0 == udp_socket)
{
udp_socket = _dau_init_udp_server();
}
printf("udp_socket=%d\n", udp_socket);
/* 初始化模块. */
for (i = 0; i < DAU_ETH_SLOTS_SUM; i++)
{
param.priority = 80;
snprintf(param.thread_name, THREAD_NAME_LEN, "DAU_RECV_%d", i);
create_thread(_dau_manager_handle, &param);
}
return E_NONE;
}
#endif