需要毕业论文私信有偿获取
截止目前mainPro.c代码
cpp
#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)指令工厂初始化
cpp
/*指令工厂初始化*/
pinputCmdHead=addVoiceToInputCmdLink(pinputCmdHead);
pinputCmdHead=addSocketToInputCmdLink(pinputCmdHead);
(2)设备控制工厂初始化
cpp
/*设备工厂初始化*/
pdevicesHead=addbathroomLightToDevicesLink(pdevicesHead);
pdevicesHead=addupstairLightToDevicesLink(pdevicesHead);
pdevicesHead=addlivingroomLightToDevicesLink(pdevicesHead);
pdevicesHead=addrestaurantLightToDevicesLink(pdevicesHead);
pdevicesHead=addFireToDevicesLink(pdevicesHead);
2、查找指令名称函数
cpp
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)语音线程
cpp
/*语音线程*/
pthread_create(&voice_thread,NULL,voice_thread,NULL);
1)线程标识符(线程ID存储位置)
pthread_creat参数一
2)线程入口函数
pthread_creat参数三
cpp
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线程
cpp
/*Socket线程*/
pthread_create(&socket_thread,NULL,socket_thread,NULL);
1)线程标识符(线程ID存储位置)
pthread_creat参数一
2)线程入口函数
pthread_creat参数三
cpp
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线程参数三
cpp
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
cpp
#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,权限不足
解决办法
cpp
sudo chmod 666 /dev/ttyAMA0 (修改权限)
sudo ./sh (管理员方式运行,sh是编译后生成的可执行文件)