|
|
|
@ -33,572 +33,31 @@
|
|
|
|
|
/* 上传平台回调函数类型 */
|
|
|
|
|
typedef void (*UploadCallback)(int slot, const void *data, size_t len);
|
|
|
|
|
|
|
|
|
|
/* 报文头 */
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint16_t len;
|
|
|
|
|
uint8_t dev_type_m;
|
|
|
|
|
uint8_t dev_type_s;
|
|
|
|
|
uint32_t dev_id;
|
|
|
|
|
uint8_t cmd_type;
|
|
|
|
|
uint8_t cmd;
|
|
|
|
|
uint16_t pkt_id;
|
|
|
|
|
uint8_t version;
|
|
|
|
|
uint8_t reserve[19];
|
|
|
|
|
} dau_pkt_head_t;
|
|
|
|
|
|
|
|
|
|
/* 开机联络 */
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint8_t type_m; // 主设备号
|
|
|
|
|
uint8_t type_s; // 次设备号
|
|
|
|
|
uint8_t reserved1[2]; // 保留
|
|
|
|
|
uint32_t dev_id; // 设备ID
|
|
|
|
|
char hostname[FILE_NAME_LEN]; // 设备名 128byte
|
|
|
|
|
uint32_t factory_date; // 出厂日期.
|
|
|
|
|
uint32_t deployment_date; // 部署日期.
|
|
|
|
|
uint8_t app_version[32]; // 软件版本
|
|
|
|
|
uint8_t app_compile_time[32]; // 软件编译时间
|
|
|
|
|
uint8_t hardware_version[32]; // 硬件版本
|
|
|
|
|
uint8_t FPGA_version[32]; // fpga版本
|
|
|
|
|
uint32_t ip; // 本机 IP.
|
|
|
|
|
uint32_t mask; // 本机 MASK.
|
|
|
|
|
uint32_t gw; // 本机网关
|
|
|
|
|
uint8_t mac[6]; // MAC地址.
|
|
|
|
|
uint16_t server_port; // 服务器端口号.
|
|
|
|
|
uint32_t server_ipv4; // 服务器 IP.
|
|
|
|
|
uint8_t port[8];
|
|
|
|
|
uint8_t port_type[8];
|
|
|
|
|
} dau_contact_t;
|
|
|
|
|
|
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
|
|
|
pthread_mutex_t board_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
int udp_socket;
|
|
|
|
|
dau_t daus[PD_SLOTS_MAX];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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].stat == 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].stat != 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].stat = 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].stat == 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].stat = DAU_STATE_DISCONNECTED;
|
|
|
|
|
daus[slot].private_data = NULL;
|
|
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&board_mutex);
|
|
|
|
|
|
|
|
|
|
printf("Board removed from slot %d\n", slot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 包头填充 */
|
|
|
|
|
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);
|
|
|
|
@ -618,100 +77,24 @@ void _dau_response(int slot, char *buf, int len)
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *_dau_udp_receive_handle(void *arg)
|
|
|
|
|
/* dau 插入处理 */
|
|
|
|
|
int _dau_insert(dau_t *dau)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
if (3 == dau->info.type_m && 1 == dau->info.type_s)
|
|
|
|
|
{
|
|
|
|
|
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].stat == 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].stat == DAU_STATE_CONNECTED &&
|
|
|
|
|
client->addr.sin_port == 0)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&client->addr, &client_addr, sizeof(client_addr));
|
|
|
|
|
daus[i].stat = DAU_STATE_REGISTERED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&board_mutex);
|
|
|
|
|
|
|
|
|
|
// 处理数据
|
|
|
|
|
if (!csg.is_connect)
|
|
|
|
|
continue;
|
|
|
|
|
_dau_find_proper_function(buffer);
|
|
|
|
|
|
|
|
|
|
usleep(1000);
|
|
|
|
|
|
|
|
|
|
dau->recv_cb = hf_recv_process;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return E_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
dau->state.is_connect = TRUE;
|
|
|
|
|
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 初始化UDP服务器 */
|
|
|
|
|
int32_t _dau_udp_server_init(dau_t *dau)
|
|
|
|
@ -730,7 +113,7 @@ int32_t _dau_udp_server_init(dau_t *dau)
|
|
|
|
|
bzero(&server, sizeof(server));
|
|
|
|
|
server.sin_family = AF_INET;
|
|
|
|
|
server.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
|
server.sin_port = htons(DUA_UDP_PORT);
|
|
|
|
|
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));
|
|
|
|
@ -742,37 +125,59 @@ int32_t _dau_udp_server_init(dau_t *dau)
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 校验收到包的包头, 长度, 校验码. */
|
|
|
|
|
int32_t _dau_pkt_check(char *pkt)
|
|
|
|
|
/* dau 开机联络处理函数 */
|
|
|
|
|
void _dau_recv_connect(dau_t *dau, uint16_t recv_len)
|
|
|
|
|
{
|
|
|
|
|
csg_pkt_head_t *head = (csg_pkt_head_t*)pkt;
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
/* 对主次设备号进行识别, 次设备号可以是广播. */
|
|
|
|
|
if (head->dev_type_m != device_info.type_m)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_CSG_ERR, "@1 type_m=%d %d\r\n", head->dev_type_m, device_info.type_m);
|
|
|
|
|
return E_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (head->len > DAU_BUF_SIZE)
|
|
|
|
|
{
|
|
|
|
|
DBG(DBG_M_PD_CSG_ERR, "@2 receive packet len(%d) is out of range\r\n", head->len);
|
|
|
|
|
return E_ERROR;
|
|
|
|
|
}
|
|
|
|
|
/* 复制设备信息 */
|
|
|
|
|
memcpy(&dau->info, pnet, sizeof(dau_contact_t));
|
|
|
|
|
|
|
|
|
|
return E_NONE;
|
|
|
|
|
/* 添加 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)
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dau 开机联络处理函数 */
|
|
|
|
|
void _dau_recv_connect_process(dau_t *dau, uint16_t recv_len)
|
|
|
|
|
{
|
|
|
|
|
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 收包线程 */
|
|
|
|
@ -780,7 +185,7 @@ void *_dau_recv_handle(void *arg)
|
|
|
|
|
{
|
|
|
|
|
dau_t *dau = (dau_t*)arg;
|
|
|
|
|
struct sockaddr_in server;
|
|
|
|
|
socklen_t server_len;
|
|
|
|
|
socklen_t server_len = sizeof(struct sockaddr_in);
|
|
|
|
|
uint16_t data_len = 0;
|
|
|
|
|
|
|
|
|
|
/* 初始化 socket */
|
|
|
|
@ -799,14 +204,7 @@ void *_dau_recv_handle(void *arg)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dau->state.is_connect)
|
|
|
|
|
{
|
|
|
|
|
_dau_recv_data_process(dau, data_len);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_dau_recv_connect_process(dau, data_len);
|
|
|
|
|
}
|
|
|
|
|
_dau_recv_data_process(dau, data_len, &server);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
@ -823,9 +221,6 @@ int32_t dau_handle_init(void)
|
|
|
|
|
{
|
|
|
|
|
daus[i].slot = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd_install_element(COMMON_NODE, &dau_add_cmd);
|
|
|
|
|
cmd_install_element(COMMON_NODE, &no_dau_add_cmd);
|
|
|
|
|
|
|
|
|
|
return E_NONE;
|
|
|
|
|
}
|
|
|
|
@ -848,5 +243,20 @@ int32_t dau_handle_init_after(void)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|