#include "ser_server.h"
pthread_t pthid;
void* serial_sever_pthread(void* input_info); //串口服务器 线程函数
int serial_server_fork()
{
int listenfd; //定义监听套接字
struct sockaddr_in servaddr, cliaddr; //定义通用网络地址结构体,用于配置服务器网络地址 和 存储客户端信息
socklen_t peerlen; //保存客户端地址长度
struct pthread_info info_ser_pth; //服务器线程传入参数
struct zigbee_info info_zgb; //zigbee数据读取线程传入参数
char zigbee_recv_buff[36] = {0}; //定义一个内存用于存放串口读出的 zigbee 数据
char *vic_send_buff[16]; //定义一个保存 语音信息存储地址 的内存
int ret; //函数返回值接收变量
/* 串口初始化 以及 语音信息的转码 */
{
/* * 对语音模块的内存进行申请并初始化 * */
#if VIC_SELECT
ret = vic_send_buff_init((void **)vic_send_buff, 12);
if(ret < 0){
printf("serial server : vic_send_buff_init fail\n");
return -1;
}else{
printf("serial server : vic_send_buff_init success\n");
}
#endif
/* 打开串口设备vicoe */
#if VIC_SELECT
ret = vic_serial_init(VIC_PWD);
if(ret < 0){
printf("vic_init fail\n");
return -1;
}else{
printf("vic_init success\n");
info_ser_pth.vicfd = ret; //将 vic 串口的文件描述 符赋值给服务器线程 传入参数
}
#endif
/* 打开串口设备zigbee */
ret = zgb_serial_init(ZGB_PWD);
if(ret < 0){
printf("zgb serial_init fail\n");
return -1;
}else{
printf("zgb serial_init success\n");
info_ser_pth.zgbfd = ret; //将 zgb 串口的文件描述 符赋值给服务器线程 传入参数
}
}
info_ser_pth.zgbid = 0x01; //设置好zigbee设备的ID
info_ser_pth.zgb_buff_head = zigbee_recv_buff; //传递zigbee设备串口数据缓存的首地址
info_ser_pth.vic_buff_head = (char**)vic_send_buff; //将 语音信息存放的地址 传递到 服务器线程函数 当中
info_zgb.zgbfd = info_ser_pth.zgbfd; //将打开的串口描述符 传递到 zigbee数据读取线程
info_zgb.zgb_buff = zigbee_recv_buff; //将 存放zigbee数据的地址 传递到 zigbee数据读取线程
info_zgb.zgbid = &info_ser_pth.zgbid; //将用于存放 zigbee设备ID 的地址 传递到 zigbee数据读取线程中
/* 创建线程,用于 zigbee 设备连续读取数据 */
{
/* 为zigbee串口分配一个线程 */
ret = pthread_create(&pthid, NULL, zigbee_recv_pthread, (void*)&info_zgb);
if(ret){
perror("zigbee_recv_pthread fail:");
}else{
printf("zigbee_recv_pthread success\n");
}
/* 将线程分离出去,便于回收 */
ret = pthread_detach(pthid);
if(ret){
perror("zigbee_recv_pthread detach:");
}else{
fprintf(stdout,"zigbee_recv_pthread detach success\n");
}
}
/* 搭建服务器 */
{
/* 创建一个网络套接字:listenfd */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1){
perror("serial server socket");
return 0;
}
/* 配置服务器的网络信息:IP:192.168.3.93 PORT:8000 */
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(atoi(SERIAL_SERVER_NET_PORT));
servaddr.sin_addr.s_addr = inet_addr(SERIAL_SERVER_NET_IP);
memset(servaddr.sin_zero, 0, 8);
/* 绑定服务器的网络信息 */
ret = bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
if (ret < 0){
perror("serial server bind");
return -1;
}
/* 设置套接字为监听套接字,监听数为:10 */
ret = listen(listenfd, 10);
if (ret == -1){
perror("serial server listen");
return -1;
}
peerlen = sizeof(cliaddr);
}
while (1)
{
/* 服务器等待客户端连接,状态为阻塞态 */
info_ser_pth.connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &peerlen);
if (info_ser_pth.connfd < 0){
perror("serial server accept");
continue;
}
/* *当有客户端连接时
*创建一个线程:serial_sever_pthread
*服务于客户端:info (传入 连接套接字和 对应串口的文件描述符)
* */
ret = pthread_create(&pthid, NULL, serial_sever_pthread, (void*)&info_ser_pth);
if(ret){
perror("serial server to client pthread create fail");
close(info_ser_pth.connfd);
}else{
printf("serial server to client pthread create success\n");
}
/* 将线程分离出去,便于回收 */
ret = pthread_detach(pthid);
if(ret){
perror("serial server to client pthread detach fail:");
close(info_ser_pth.connfd);
}else{
fprintf(stdout,"serial server to client pthread detach success\n");
}
}
close(listenfd);
serial_exit(info_ser_pth.zgbfd);
return 0;
}
void* serial_sever_pthread(void* input_info)
{
int connfd = ((struct pthread_info *)input_info)->connfd; //将线程传入参数中的 与客户端相连的 连接套接字提取出来
int zgbfd = ((struct pthread_info *)input_info)->zgbfd; //将线程传入参数中的 zigbee设备 串口文件描述符提取出来
int vicfd = ((struct pthread_info *)input_info)->vicfd; //从线程传入参数中的 vic语音设备 串口文件描述符提取出来
int *zgbid =&((struct pthread_info *)input_info)->zgbid; //将线程传入参数中的 zigbee设备 的设备ID 存放地址 提取出来
char* zigbee_recv_buff = ((struct pthread_info *)input_info)->zgb_buff_head; //提取传入参数中的 存放zigbee设备的串口数据的 地址
char**vic_send_buff = ((struct pthread_info *)input_info)->vic_buff_head; //提取传入参数中的 存放语音信息的 地址
char client_recv_buff[36] = {0}; //接收客户端的请求数据
char client_back_message[36] = {0}; //回复客户端的数据
unsigned char zigbee_send_cmd[36] = {0xdd,0x01,0x24,0x00,0x00}; //设置 zigbee 控制的命令格式
int ret; //接收函数返回值的变量
int order;//用于存放 客户端请求命令
while(1)
{
/* 接收客户端的请求,状态为阻塞态 */
ret = recv(connfd, client_recv_buff, 2, 0);
puts(client_recv_buff);
if(ret < 0){
printf("serial recv fail\n");
return (void*)0;
}else if(ret == 0){
printf("serial client disconnect\n");
close(connfd);
return (void*)0;
}
/* 转换命令,返回值是 命令对应的 宏值(定义于头文件) */
order = client_order_exc(client_recv_buff);
printf("order = %d %#x\n",order, order);
switch (order)
{
case RCV_MEG: //客户端 请求 环境数据
/* 将 已转换的zigbee串口数据 回传给服务器 */
ret = send(connfd,zigbee_recv_buff,36,0);
if(ret <= 0){
printf("client back fail:00\n");
}
break;
case LED_ON: //客户端 控制 开灯
ZIGBEE_DEVID_EXC(zigbee_send_cmd, (*zgbid)); //利用宏函数修改zigbee发送信息的 设备ID
ZIGBEE_ORDER_EXC(zigbee_send_cmd, LED_ON); //利用宏函数实现zigbee发送信息的 控制命令
ret = serial_send_nbytes(zgbfd, zigbee_send_cmd, 36);
if(ret == sizeof(zigbee_send_cmd)){
/* 播报灯打开成功的语音,利用宏函数 VIC_MESSAGE_FIND 修改 vic_send_buff 中的数据 */
#if VIC_SELECT
ret = write(vicfd, VIC_MESSAGE_FIND(vic_send_buff, LED_ON_SUC), 32);
if(-1 == ret){
perror("write data to vic");
}
#endif
/* 向客户端回复 成功 信息 */
ret = send(connfd, client_back_message, 36, 0);
if(ret <= 0){
printf("client_back_success fail:11\n");
return NULL;
}
}else{
/* 播报灯打开失败的语音,利用宏函数 VIC_MESSAGE_FIND 修改 vic_send_buff 中的数据 */
#if VIC_SELECT