a)一个指令工厂,一个控制工厂,实际上就是通过链表链起来的数据。具体怎么链接起来,就是基于简单工厂模式的类与对象的概念,上一篇文章有学习记录。
b)主函数语音指令程序和tcp指令程序各起一个线程,然后通过指令找到对应的控制程序,实现对应的模块的功能。
有了思路之后,我们就可以来建立项目文件代码了。
1.我们先再桌面建立一个项目文件:
2.然后打开文件,逐个写好先:
3.然后打开Souce Insight,把文件都导入进去
因为用这个来写,更加的直观和方便。
1.先看主函数mainPro.c
#include
#include"controlDevices.h"
#include
struct Devices *findDeviceByName(char *name,struct Devices *phead)
{
struct Devices *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(tmp->deviceName,name) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
int main()
{
char *name = "bathroomLight";
if(-1 == wiringPiSetup()){
return -1;
}
struct Devices *pdeviceHead = NULL;
pdeviceHead = addBathroomLightInit(pdeviceHead);
struct Devices *tmp = findDeviceByName(name,pdeviceHead);
if(tmp != NULL){
tmp->deviceInit(tmp->pinNum);
tmp->open(tmp->pinNum);
}
return 0;
}
2.外设设备的头文件controlDevices.h
#include
#include
struct Devices
{
char deviceName[128];
int pinNum;
int (*deviceInit)(int pinNum;);
int (*open)(int pinNum;);
int (*close)(int pinNum;);
struct Devices *next;
};
struct Devices *addBathroomLightInit(struct Devices *phead);
3.浴室灯bathroomLight.c
#include"controlDevices.h"
int bathroomLightInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
int bathroomLightOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int bathroomLightClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
struct Devices bathroomLight = {
.deviceName = "bathroomLight",
.pinNum = 28,
.deviceInit = bathroomLightInit,
.open = bathroomLightOpen,
.close = bathroomLightClose
};
struct Devices *addBathroomLightInit(struct Devices *phead)
{
if(phead == NULL){
return &bathroomLight;
}else{
bathroomLight.next = phead;
phead = &bathroomLight;
}
}
4.写完之后,利用FileZilla文件传输软件,将文件smartHouse文件传到树莓派终端:
5.进行代码编译,然后执行:
6.测试结果:
7.继电器其余四盏灯全部实现:
其余三盏灯的代码格式和上面bathroomLight.c的一样,这里就不一一展示,已经实现了。
等所有的模块都测试完,会有整个项目的实现效果和总结。
它们也是io口驱动,跟实现灯代码一样,就是要注意模块的使用说明。
1.火焰传感器fire.c
#include"controlDevices.h"
int fireInit(int pinNum)
{
pinMode(pinNum,INPUT);
digitalWrite(pinNum,HIGH);
}
int fireStatusRead(int pinNum)
{
return digitalRead(pinNum);
}
struct Devices fire = {
.deviceName = "fire",
.pinNum = 0,
.deviceInit = fireInit,
.readStatus = fireStatusRead
};
struct Devices *addFireToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
return &fire;
}else{
fire.next = phead;
phead = &fire;
}
}
2.蜂鸣器buzzer.c
#include"controlDevices.h"
int buzzerInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,HIGH);
}
int buzzerOpen(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int buzzerClose(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
struct Devices buzzer = {
.deviceName = "buzzer",
.pinNum = 7,
.deviceInit = buzzerInit,
.open = buzzerOpen,
.close = buzzerClose
};
struct Devices *addBuzzerToDevicesLink(struct Devices *phead)
{
if(phead == NULL){
return &buzzer;
}else{
buzzer.next = phead;
phead = &buzzer;
}
}
3.外设设备的头文件controlDevices.h
#include
#include
struct Devices
{
char deviceName[128];
int pinNum;
int (*deviceInit)(int pinNum);
int (*open)(int pinNum);
int (*close)(int pinNum);
int (*readStatus)(int pinNum);
struct Devices *next;
};
struct Devices *addBathroomLightToDevicesLink(struct Devices *phead);
struct Devices *addLivingroomLightToDevicesLink(struct Devices *phead);
struct Devices *addSwimmingpoolLightToDevicesLink(struct Devices *phead);
struct Devices *addUpstairLightToDevicesLink(struct Devices *phead);
struct Devices *addFireToDevicesLink(struct Devices *phead);
struct Devices *addBuzzerToDevicesLink(struct Devices *phead);
4.主函数测试代码mainPro.c
#include
#include"controlDevices.h"
#include
struct Devices *findDevicesByName(char *name,struct Devices *phead)
{
struct Devices *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(tmp->deviceName,name) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
int main()
{
int status;
char name[128];
struct Devices *tmp = NULL;
if(-1 == wiringPiSetup()){
return -1;
}
struct Devices *pdeviceHead = NULL;
pdeviceHead = addBathroomLightToDevicesLink(pdeviceHead);
pdeviceHead = addLivingroomLightToDevicesLink(pdeviceHead);
pdeviceHead = addUpstairLightToDevicesLink(pdeviceHead);
pdeviceHead = addSwimmingpoolLightToDevicesLink(pdeviceHead);
pdeviceHead = addFireToDevicesLink(pdeviceHead);
pdeviceHead = addBuzzerToDevicesLink(pdeviceHead);
struct Devices *fireDevicesTmp = NULL;
struct Devices *buzzerDevicesTmp = NULL;
fireDevicesTmp = findDevicesByName("fire",pdeviceHead);//在设备工厂找到火灾模块
buzzerDevicesTmp = findDevicesByName("buzzer",pdeviceHead);//在设备工厂找到蜂鸣器模块
fireDevicesTmp->deviceInit(fireDevicesTmp->pinNum);//火灾模块初始化
buzzerDevicesTmp->deviceInit(buzzerDevicesTmp->pinNum);//蜂鸣器初始化
while(1){
status = fireDevicesTmp->readStatus(fireDevicesTmp->pinNum);//不断获取火灾模块的数据
if(status == 0){
buzzerDevicesTmp->open(buzzerDevicesTmp->pinNum);
}else{
buzzerDevicesTmp->close(buzzerDevicesTmp->pinNum);
}
}
return 0;
}
语音模块之前有学过,这里主要通过主控芯片树莓派的串口跟语音模块连接。
树莓派的T接语音模块的R
树莓派的R接语音模块的T
然后就是供电
我们先把语音模块的代码整合到指令链表链表当中去:
1.语音控制设备voicevoiceContrl.c
#include"inputCommand.h"
#include
#include
#include
int voiceInit(struct InputCommander *voicer,char *ipAdress,char *port)
{
int fd;
if((fd = serialOpen(voicer->deviceName,9600)) == -1){
exit(-1);
}
voicer->fd = fd;
return fd;
}
int voiceGetCommand(struct InputCommander *voicer)
{
int nread = 0;
nread = read(voicer->fd,voicer->command,sizeof(voicer->command));
if(nread == 0){
printf("usart for voice read over time\n");
}else{
return nread;
}
}
struct InputCommander voiceContrl = {
.commandName = "voice",
.deviceName = "/dev/ttyAMA0",
.command = {'\0'},
.Init = voiceInit,
.getCommand = voiceGetCommand
};
struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead)
{
if(phead == NULL){
return &voiceContrl;
}else{
voiceContrl.next = phead;
return &voiceContrl;
}
}
2.控制设备的头文件inputCommand.h
#include
#include
struct InputCommander
{
char commandName[128];
char deviceName[128];
char command[32];
int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);
int (*getCommand)(struct InputCommander *voicer);
char log[1024];
int fd;
struct InputCommander *next;
};
struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead);
这里跟语音模块一样,我们先把socket服务器加到控制链表中去。
这里也基于语音模块代码来写。
1.socket服务器控制socketContrl.c
#include"inputCommand.h"
#include
#include
#include
#include
#include
#include
#include
int socketInit(struct InputCommander *socketMes,char *ipAdress,char *port)
{
int s_fd;
s_fd = socket(AF_INET,SOCK_STREAM,0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
struct sockaddr_in s_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(socketMes->port));
inet_aton(socketMes->ipAdress,&s_addr.sin_addr);
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
listen(s_fd,10);
socketMes->sfd = s_fd;
return s_fd;
}
int socketGetCommand(struct InputCommander *socketMes)
{
int c_fd;
int nread = 0;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
c_fd = accept(socketMes->sfd,(struct sockaddr *)&c_addr,&clen);
nread = read(c_fd,socketMes->command,sizeof(socketMes->command));
return nread;
}
struct InputCommander socketContrl = {
.commandName = "socketServer",
.command = {'\0'},
.port = "8088",
.ipAdress = "192.168.31.80",
.Init = socketInit,
.getCommand = socketGetCommand
};
struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead)
{
if(phead == NULL){
return &socketContrl;
}else{
socketContrl.next = phead;
return &socketContrl;
}
}
2.控制设备的头文件inputCommand.h
#include
#include
#include
struct InputCommander
{
char commandName[128];
char deviceName[128];
char command[32];
int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);
int (*getCommand)(struct InputCommander *voicer);
char log[1024];
int fd;
char port[12];
char ipAdress[32];
int sfd;
struct InputCommander *next;
};
struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead);
struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead);
这里还是主要测试主函数。所有控制实现功能都是在主函数里面进行。
我们来测试一下socket服务器的网络功能和树莓派连接语音的串口功能
1.主函数mainPro.c
#include
#include"controlDevices.h"
#include"inputCommand.h"
#include
#include
#include
#include
#include
#include
#include
#include
struct InputCommander *pcommandHead = NULL;
struct Devices *pdeviceHead = NULL;
struct InputCommander *socketHandler = NULL;
int c_fd;
struct Devices *findDevicesByName(char *name,struct Devices *phead)
{
struct Devices *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(tmp->deviceName,name) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
struct InputCommander *findCommandByName(char *name,struct InputCommander *phead)
{
struct InputCommander *tmp = phead;
if(phead == NULL){
return NULL;
}else{
while(tmp != NULL){
if(strcmp(tmp->commandName,name) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
void *voice_thread(void *datas)
{
struct InputCommander *voiceHandler;
int nread;
voiceHandler = findCommandByName("voice",pcommandHead);
if(voiceHandler == NULL){
printf("find voiceHandler error\n");
pthread_exit(NULL);
}else{
if(voiceHandler->Init(voiceHandler,NULL,NULL) <0){
printf("voiceInit error\n");
pthread_exit(NULL);
}else{
printf("%s Init succcess\n",voiceHandler->commandName);
}
while(1){
nread = voiceHandler->getCommand(voiceHandler);
if(nread == 0){
printf("nodata from voice\n");
}else{
printf("do device contrl:%s\n",voiceHandler->command);
}
}
}
}
void *read_thread(void *datas)
{
int n_read;
printf(
"have user connect\n");
memset(socketHandler->command,'\0',sizeof(socketHandler->command));
n_read = read(c_fd,socketHandler->command,sizeof(socketHandler->command));
if(n_read == -1){
perror("read");
}else if(n_read > 0){
printf("read:%s\n",socketHandler->command);
}else{
printf("clien quit\n");
}
}
void *socket_thread(void *datas)
{
int nread = 0;
pthread_t readThread;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
int clen = sizeof(struct sockaddr_in);
socketHandler = findCommandByName("socketServer",pcommandHead);
if(socketHandler == NULL){
printf("find socketHandler error\n");
pthread_exit(NULL);
}else{
printf("%s Init succcess\n",socketHandler->commandName);
}
socketHandler->Init(socketHandler,NULL,NULL);
while(1){
c_fd = accept(socketHandler->sfd,(struct sockaddr *)&c_addr, &clen);
pthread_create(&readThread,NULL,read_thread,NULL);
}
}
int main()
{
int status;
char name[128];
pthread_t voiceThread;
pthread_t socketThread;
if(-1 == wiringPiSetup()){
return -1;
}
//1.指令工厂的初始化
pcommandHead = addVoiceContrlToInputCommandLink(pcommandHead);
pcommandHead = addSocketContrlToInputCommandLink(pcommandHead);
//2.设备工厂的初始化
pdeviceHead = addBathroomLightToDevicesLink(pdeviceHead);
pdeviceHead = addLivingroomLightToDevicesLink(pdeviceHead);
pdeviceHead = addUpstairLightToDevicesLink(pdeviceHead);
pdeviceHead = addSwimmingpoolLightToDevicesLink(pdeviceHead);
pdeviceHead = addFireToDevicesLink(pdeviceHead);
pdeviceHead = addBuzzerToDevicesLink(pdeviceHead);
//3.线程池的建立
//3.1 语音线程
pthread_create(&voiceThread,NULL,voice_thread,NULL);
//3.2 socket线程
pthread_create(&socketThread,NULL,socket_thread,NULL);
//3.3 摄像头线程
//3.4 火灾线程
pthread_join(voiceThread,NULL);
pthread_join(socketThread,NULL);
return 0;
}
2.编译运行网络测试:
3.串口语音测试:
树莓派连接语音的串口功能。
测试的结果还不是特别完善,语音模块的口令那块源代码还要改下,然后收到串口的语音指令完善下。