需要毕业论文私信有偿获取
截止目前mainPro.c代码
#include <stdio.h>
#include <string.h>#include "controlDevices.h"
#include "inputCmd.h"struct Devices *findDevicesName(char *name,struct Devices *phead){struct Devices *tmp=phead;if(phead==NULL){return NULL;}else{while(tmp!=NULL){if(strcmp(tmp->devicesName,name)==0){return tmp;}tmp=tmp->next;}return NULL;}
}int main(){if(wiringPiSetup()==-1){return -1;}struct Devices *pdevicesHead=NULL;struct InputCmd *pinputCmdHead=NULL;pdevicesHead=addbathroomLightToDevicesLink(pdevicesHead);pdevicesHead=addupstairLightToDevicesLink(pdevicesHead);pdevicesHead=addlivingroomLightToDevicesLink(pdevicesHead);pdevicesHead=addrestaurantLightToDevicesLink(pdevicesHead);pdevicesHead=addFireToDevicesLink(pdevicesHead);pinputCmdHead=addVoiceToInputCmdLink(pinputCmdHead);pinputCmdHead=addSocketToInputCmdLink(pinputCmdHead);char name[128]={'\0'};struct Devices *tmp=NULL;while(1){printf("INPUT:\n");scanf("%s",name);tmp=findDevicesName(name,pdevicesHead);if(tmp!=NULL){tmp->devicesInit(tmp->pinNum);tmp->open(tmp->pinNum); tmp->readStatus(tmp->pinNum);}}return 0;
}
一、编写流程
1、工厂初始化
将指令和设备结构体指针定义为全局变量
(1)指令工厂初始化
/*指令工厂初始化*/pinputCmdHead=addVoiceToInputCmdLink(pinputCmdHead);pinputCmdHead=addSocketToInputCmdLink(pinputCmdHead);
(2)设备控制工厂初始化
/*设备工厂初始化*/
pdevicesHead=addbathroomLightToDevicesLink(pdevicesHead);
pdevicesHead=addupstairLightToDevicesLink(pdevicesHead);
pdevicesHead=addlivingroomLightToDevicesLink(pdevicesHead);
pdevicesHead=addrestaurantLightToDevicesLink(pdevicesHead);
pdevicesHead=addFireToDevicesLink(pdevicesHead);
2、查找指令名称函数
struct InputCmd *findCmdName(char *name,struct InputCmd *phead){struct InputCmd *tmp=phead;if(phead==NULL){return NULL;}else{while(tmp!=NULL){if(strcmp(tmp->cmdName,name)==0){return tmp;}tmp=tmp->next;}return NULL;}
}
3、线程池
pthread_t *thread
:类型为指向 pthread_t
类型的指针,用于存储新创建线程的标识符。当线程成功创建后,函数会将新线程的 ID 值填入这个地址所指向的位置。
const pthread_attr_t *attr
:类型为指向 pthread_attr_t
结构体的常量指针,用来指定线程属性,如线程的调度策略、优先级、栈大小等。如果不需要设置特定属性,可以传入 NULL
,使用默认属性。
void *(*start_routine)(void *)
:类型为指向函数的指针,该函数接收一个 void *
类型的参数,并返回 void *
类型的值。这是新线程开始执行时调用的函数,通常被称为线程入口函数或线程启动例程。
void *arg
:类型为 void *
,这是一个通用指针,作为传递给 start_routine
函数的唯一参数。程序员可以通过这个参数向线程传递任意类型的数据。
函数返回值:
- 如果成功创建线程,返回0。
- 如果失败,则返回一个非零错误码,可以通过宏
pthread_getspecific()
来获取错误信息。
pthread_create()
创建了一个新的线程,并安排它从指定的 start_routine
函数开始执行,同时可以传递一个自定义参数给这个线程函数
(1)语音线程
/*语音线程*/pthread_create(&voice_thread,NULL,voice_thread,NULL);
1)线程标识符(线程ID存储位置)
pthread_creat参数一
2)线程入口函数
pthread_creat参数三
void *voice_thread(void *data){struct InputCmd *voiceHandler;int nread;voiceHandler=findCmdName("voice",pinputCmdHead);if(voiceHandler==NULL){printf("voiceHandler unfound!\n");pthread_exit(NULL);}else{if(voiceHandler->Init(voiceHandler,NULL,NULL)<0){printf("voice init error!\n");pthread_exit(NULL);}while(1){voiceHandler->getCmd(voiceHandler);if(nread==0){printf("voice no data was received!\n");}else{printf("voice received data:%s\n",voiceHandler->cmd);}} }
}
(2)Socket线程
/*Socket线程*/pthread_create(&socket_thread,NULL,socket_thread,NULL);
1)线程标识符(线程ID存储位置)
pthread_creat参数一
2)线程入口函数
pthread_creat参数三
void *socket_thread(void *data){int nread=0;pthread_t readThread;struct sockaddr_in c_addr;memset(&c_addr,0,sizeof(struct sockaddr_in));int len=sizeof(struct sockaddr_in);socketHandler=findCmdName("socket",pinputCmdHead);if(socketHandler==NULL){printf("socketHandler unfound!\n");pthread_exit(NULL);}socketHandler->Init(socketHandler,NULL,NULL);while (1){c_fd=accept(socketHandler->s_fd,(struct sockaddr *)&c_addr,&len);pthread_create(&readThread,NULL,read_thread,NULL);}
}
read线程参数三
void *read_thread(void *data){int n_read;n_read=read(c_fd,socketHandler->cmd,sizeof(socketHandler->cmd));if(n_read==-1){perror("read");}else if(n_read>0){printf("\nget:%d %s\n",n_read,socketHandler->cmd);}else{printf("client quit!\n");}
}
4、mainPro.c
#include <stdio.h>
#include <string.h>
#include "controlDevices.h"
#include "inputCmd.h"
#include <pthread.h>int c_fd;
struct Devices *pdevicesHead=NULL;
struct InputCmd *pinputCmdHead=NULL;
struct InputCmd *socketHandler=NULL;struct Devices *findDevicesName(char *name,struct Devices *phead){struct Devices *tmp=phead;if(phead==NULL){return NULL;}else{while(tmp!=NULL){if(strcmp(tmp->devicesName,name)==0){return tmp;}tmp=tmp->next;}return NULL;}
}struct InputCmd *findCmdName(char *name,struct InputCmd *phead){struct InputCmd *tmp=phead;if(phead==NULL){return NULL;}else{while(tmp!=NULL){if(strcmp(tmp->cmdName,name)==0){return tmp;}tmp=tmp->next;}return NULL;}
}void *voice_thread(void *data){struct InputCmd *voiceHandler;printf("voice_thread\n");int nread;//接收串口字节数voiceHandler=findCmdName("voice",pinputCmdHead);if(voiceHandler==NULL){printf("voiceHandler unfound!\n");pthread_exit(NULL);}else{if(voiceHandler->Init(voiceHandler,NULL,NULL)<0){printf("voice init error!\n");pthread_exit(NULL);}else{/*初始化语音*/printf("%s init success\n",voiceHandler->cmdName);}while(1){nread=voiceHandler->getCmd(voiceHandler);if(nread==0){printf("voice no data was received!\n");}else{printf("voice received data:%s\n",voiceHandler->cmd);}} }
}void *read_thread(void *data){printf("read_thread\n");int n_read;/*清空命令接收区,方便下次检测*/memset(socketHandler->cmd,'\0',sizeof(socketHandler->cmd));n_read=read(c_fd,socketHandler->cmd,sizeof(socketHandler->cmd));if(n_read==-1){perror("read");}else if(n_read>0){printf("\nget:%d %s\n",n_read,socketHandler->cmd);}else{printf("client quit!\n");}
}void *socket_thread(void *data){printf("socket_thread\n");int nread=0;pthread_t readThread;struct sockaddr_in c_addr;memset(&c_addr,0,sizeof(struct sockaddr_in));int len=sizeof(struct sockaddr_in);/*从命令工厂找到网络设备*/socketHandler=findCmdName("socket",pinputCmdHead);if(socketHandler==NULL){printf("socketHandler unfound!\n");pthread_exit(NULL);}else{printf("%s init success\n",socketHandler->cmdName);}/*初始化网络*/socketHandler->Init(socketHandler,NULL,NULL);/*不断监听客户端发送的数据,并创建线程处理*/while (1){c_fd=accept(socketHandler->s_fd,(struct sockaddr *)&c_addr,&len);pthread_create(&readThread,NULL,read_thread,NULL);}
}int main(){char name[128]={'\0'};struct Devices *tmp=NULL;pthread_t voiceThread;pthread_t socketThread;if(wiringPiSetup()==-1){return -1;}printf("main\n");/*指令工厂初始化*/pinputCmdHead=addVoiceToInputCmdLink(pinputCmdHead);pinputCmdHead=addSocketToInputCmdLink(pinputCmdHead);/*设备工厂初始化*/pdevicesHead=addbathroomLightToDevicesLink(pdevicesHead);pdevicesHead=addupstairLightToDevicesLink(pdevicesHead);pdevicesHead=addlivingroomLightToDevicesLink(pdevicesHead);pdevicesHead=addrestaurantLightToDevicesLink(pdevicesHead);pdevicesHead=addFireToDevicesLink(pdevicesHead);/*线程池*///pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(start_routine)(void *),void *arg);/*语音线程*/pthread_create(&voiceThread,NULL,voice_thread,NULL);/*Socket线程*/pthread_create(&socketThread,NULL,socket_thread,NULL);pthread_join(voiceThread,NULL);pthread_join(socketThread,NULL);// while(1){// printf("INPUT:\n");// scanf("%s",name);// tmp=findDevicesName(name,pdevicesHead);// if(tmp!=NULL){// tmp->devicesInit(tmp->pinNum);// tmp->open(tmp->pinNum); // tmp->readStatus(tmp->pinNum);// }// }return 0;
}
二、测试
1、在树莓派上编译成功
2、打印一些信息查看程序运行情况
(1)mainPro.c(语音和网络线程是否创建成功)
(2)Socket.c(网络线程是否进入监听)
(3)编译测试
gcc mainPro.c controlDevices.c bathroomLight.c livingroomLight.c restaurantLight.c upstairLight.c monitor.c socket.c voice.c -L ./ -lwiringPi -lpthread -o sh
在语音初始化中开启串口报错Permission denied,权限不足
解决办法
sudo chmod 666 /dev/ttyAMA0 (修改权限)
sudo ./sh (管理员方式运行,sh是编译后生成的可执行文件)