/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_PD /* 标准C库头文件. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* 用户代码头文件. */ #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, ¶m); } return E_NONE; } #endif