智能家居 (7) ——整合篇
????1、前序文章:【智能家居 (1) ——工厂模式继电器控制灯】【智能家居 (2) ——工厂模式火焰报警器】【智能家居 (3) ——语音识别控制端线程】【智能家居 (4) ——网络控制端线程】【智能家居 (5) ——前四章内容整合】【基于 Libcurl 通过 https 访问翔云 OCR 实现人脸识别】【树莓派安装mjpg-streamer使用摄像头】【智能家居 (6) ——人脸识别控制开关
·
🔺1、前序文章:
【基于 Libcurl 通过 https 访问翔云 OCR 实现人脸识别】
🔺1、main.c 文件(主函数):
#include <stdio.h>
#include <string.h>
#include "equipment.h"
#include "command.h"
#include <pthread.h>
#include <unistd.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
char buf[1024] = {'\0'}; //用于存放翔云返回的数据
struct Equipment *findEquipByName(char *name,struct Equipment *phead); //一些函数声明
struct Command *findCommandByName(char *name,struct Command *phead);
char *getPicBase64FromFile(char *filePath);
size_t readData(void *ptr, size_t size, size_t nmemb, void *stream);
unsigned int postUrl();
void *voiceControlThread(void *data);
void *socketControlThread(void *data);
void *socketReadThread(void *data);
void *fireAlarmThread(void *data);
struct Equipment *equiphead = NULL; //设备工厂链表头节点
struct Command *cmdhead = NULL; //指令控制工厂链表节点头
struct Command *socketHandler = NULL; //“网络控制线程”执行的函数使用到的全局变量
int main()
{
if(wiringPiSetup() == -1){ //使用wiringPi库需要初始化
printf("wiringPiSetup failed!\n");
return -1;
}
equiphead = addBathroomLightToLink(equiphead); //各设备加入设备工厂
equiphead = addSecondfloorLightToLink(equiphead);
equiphead = addLivingroomLightToLink(equiphead);
equiphead = addRestaurantLightToLink(equiphead);
equiphead = addFireDetectionToLink(equiphead);
equiphead = addBuzzerToLink(equiphead);
equiphead = addEleLockToLink(equiphead);
cmdhead = addVoiceControlToLink(cmdhead); //各指令控制加入指令控制工厂
cmdhead = addSocketControlToLink(cmdhead);
struct Equipment *tmpequiphead = equiphead;
while(tmpequiphead != NULL){ //设备工厂所有设备初始化
tmpequiphead->Init(tmpequiphead->pinNum);
tmpequiphead = tmpequiphead->next;
}
pthread_t voiceControl_thread;
pthread_t socketControl_thread;
pthread_t fireAlarm_thread;
pthread_create(&voiceControl_thread,NULL,voiceControlThread,NULL); //创建线程:语音控制
pthread_create(&socketControl_thread,NULL,socketControlThread,NULL); //创建线程:网络控制
pthread_create(&fireAlarm_thread,NULL,fireAlarmThread,NULL); //创建线程:火灾报警系统
pthread_join(voiceControl_thread, NULL); //主函数等待线程退出
pthread_join(socketControl_thread, NULL); //主函数等待线程退出
pthread_join(fireAlarm_thread, NULL); //主函数等待线程退出
return 0;
}
void *voiceControlThread(void *data) //“语音控制线程”执行的函数
{
int nread;
char *temName = NULL;
struct Command *voiceHandler = NULL;
struct Equipment *linkHandler;
voiceHandler = findCommandByName("voiceControl",cmdhead); //寻找“语音控制”所在节点,返回给voiceHandler
if(voiceHandler == NULL){
printf("find voiceHandler error\n");
pthread_exit(NULL);
}
if(voiceHandler->Init(voiceHandler) < 0){ //“语音控制”功能初始化
printf("voiceControl init error\n");
pthread_exit(NULL);
}
while(1){
nread = voiceHandler->getCommand(voiceHandler); //获取指令
if(nread == 0){ //没有获取到指令
printf("No command received\n");
}else{ //获取到指令
printf("Get voice command:%s\n",voiceHandler->command);
//以下为根据不同指令执行相应操作
if(strstr("OpBaLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClBaLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpSeLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClSeLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpLiLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClLiLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpReLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClReLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpAlLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClAlLi\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpLock\r\n",voiceHandler->command) != NULL){
linkHandler = findEquipByName("eleLock",equiphead);
system("raspistill -o image.jpg"); //拍摄照片命名为 image.jpg
system("convert -resize 400 image.jpg face2.jpg"); //降低拍摄的照片的大小,命名为 face2.jpg
system("rm image.jpg"); //删除 image.jpg 临时照片
// face1.jpg 为对比人脸照片,face2.jpg 为即拍人脸照片
postUrl();
system("rm face2.jpg");
if(strstr(buf,"是") != NULL){ //如果返回对比数据是同一个人
linkHandler->open(linkHandler->pinNum); //开锁
delay(10000); //延时10000毫秒=10秒
linkHandler->close(linkHandler->pinNum); //关锁
}
}
}
}
}
void *socketControlThread(void *data) //“网络控制线程”执行的函数
{
int c_fd;
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(struct sockaddr_in));
socklen_t clen = sizeof(struct sockaddr_in);
pthread_t socketRead_thread;
socketHandler = findCommandByName("socketControl",cmdhead); //寻找“网络控制”所在节点,返回给socketHandler
if(socketHandler == NULL){
printf("find socketHandler error\n");
pthread_exit(NULL);
}
if(socketHandler->Init(socketHandler) < 0){ //“网络控制”功能初始化
printf("socketControl init error\n");
pthread_exit(NULL);
}
while(1){
c_fd = accept(socketHandler->s_fd,(struct sockaddr*)&c_addr,&clen); //接收连接请求,阻塞至有客户端完成三次握手
socketHandler->fd = c_fd; //将套接字描述符返回给“网络控制”链表节点
pthread_create(&socketRead_thread,NULL,socketReadThread,NULL); //创建新线程:用于读取TCP端口指令
}
}
void *socketReadThread(void *data) //“读取tcp端口指令线程”执行的函数
{
int nread;
struct Equipment *linkHandler;
memset(socketHandler->command,'\0',sizeof(socketHandler->command)); //将指令存放的空间置空
nread = read(socketHandler->fd,socketHandler->command,sizeof(socketHandler->command)); //读取指令
if(nread == 0){
printf("No command received\n"); //没有读取到指令
}else{
printf("Get net command:%s\n",socketHandler->command); //读取到指令
//以下为根据不用指令执行相应操作
if(strstr("OpBaLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClBaLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpSeLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClSeLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpLiLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClLiLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpReLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClReLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpAlLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->open(linkHandler->pinNum);
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->open(linkHandler->pinNum);
}
if(strstr("ClAlLi\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("bathroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("secondfloorLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("livingroomLight",equiphead);
linkHandler->close(linkHandler->pinNum);
linkHandler = findEquipByName("restaurantLight",equiphead);
linkHandler->close(linkHandler->pinNum);
}
if(strstr("OpLock\r\n",socketHandler->command) != NULL){
linkHandler = findEquipByName("eleLock",equiphead);
system("raspistill -o image.jpg"); //拍摄照片命名为 image.jpg
system("convert -resize 400 image.jpg face2.jpg"); //降低拍摄的照片的大小,命名为 face2.jpg
system("rm image.jpg"); //删除 image.jpg 临时照片
// face1.jpg 为对比人脸照片,face2.jpg 为即拍人脸照片
postUrl();
system("rm face2.jpg");
if(strstr(buf,"是") != NULL){ //如果返回对比数据是同一个人
linkHandler->open(linkHandler->pinNum); //开锁
delay(10000); //延时10000毫秒=10秒
linkHandler->close(linkHandler->pinNum); //关锁
}
}
}
}
void *fireAlarmThread(void *data) //“火灾报警器线程”执行的函数
{
int status;
struct Equipment *firetmp = NULL;
struct Equipment *buztmp = NULL;
firetmp = findEquipByName("fireDetection",equiphead); //寻找“火焰传感器”链表节点,返回给firetmp
buztmp = findEquipByName("buzzer",equiphead); //寻找“蜂鸣器”链表节点,返回给buztmp
while(1){
status = firetmp->readStatus(firetmp->pinNum); //读取“火焰传感器”状态
if(status == 0){ //检测到火焰或强光源
buztmp->open(buztmp->pinNum); //打开蜂鸣器
delay(1000); //延时1000毫秒=1秒
}
if(status == 1){ //未检测到火焰、强光源或解除警报
buztmp->close(buztmp->pinNum); //关闭蜂鸣器
}
}
}
unsigned int postUrl()
{
CURL *curl;
CURLcode res;
char *key = "xxxxxxxxxxxxxxxxxxxxxxxx"; //用户 OCR Key 值
char *secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //用户 OCR Secret 值
int typeId = 21; //识别类型 21
char *format = "xml"; //设置返回格式 "xml"
char *postString;
char *bufPic1 = getPicBase64FromFile("./face1.jpg"); //获取图片 1 的 base64流
char *bufPic2 = getPicBase64FromFile("./face2.jpg"); //获取图片 2 的 base64流
int len = strlen(key)+strlen(secret)+strlen(bufPic1)+strlen(bufPic2)+124; //计算所需传参字符串大小
postString = (char *)malloc(len); //为传参字符串创建空间
memset(postString,'\0',len); //初始化传参字符串空间
sprintf(postString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",
bufPic1,bufPic2,key,secret,typeId,format); //拼接平台要求的传参字符串
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString); //指定 post 内容
curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do"); //指定 url
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, readData); //接收到数据,调用回调函数
res = curl_easy_perform(curl);
curl_easy_cleanup(curl); //清除 curl
}
return 1;
}
char *getPicBase64FromFile(char *filePath)
{
int fd;
int filelen;
char cmd[128];
char *bufPic;
sprintf(cmd,"base64 %s > tmpFile",filePath); //拼接系统调用字符串
system(cmd); //系统调用获取图片 base64流
fd = open("./tmpFile",O_RDWR); //存放图片 base64 流的临时文件
filelen = lseek(fd,0,SEEK_END); //计算文件字符数
lseek(fd,0,SEEK_SET); //指针回到文件头部
bufPic = (char *)malloc(filelen+2); //创建空间存放图片 base64流
memset(bufPic,'\0',filelen+2); //初始化空间
read(fd,bufPic,filelen); //文件内容读取到空间
close(fd); //关闭文件描述符
system("rm -f tmpFile"); //忽略提示关闭临时文件
return bufPic; //返回图片 base64流
}
size_t readData(void *ptr, size_t size, size_t nmemb, void *stream) //回调函数
{
strncpy(buf,ptr,1024);
}
struct Equipment *findEquipByName(char *name,struct Equipment *phead) //根据名字寻找设备工厂链表链节函数,并返回链节
{
struct Equipment *tmp = phead;
if(phead == NULL){
return NULL;
}
while(tmp != NULL){
if(strcmp(name,tmp->equipName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
struct Command *findCommandByName(char *name,struct Command *phead) //根据名字寻找指令控制工厂链表链节函数,并返回链节
{
struct Command *tmp = phead;
if(phead == NULL){
return NULL;
}
while(tmp != NULL){
if(strcmp(name,tmp->commandName) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
🔺2、分文件:
(1) equipment.h 文件(设备类头文件):
#include <wiringPi.h> //wiringPi库
#include <stdio.h>
#include <stdlib.h>
struct Equipment //设备工厂链表节点定义
{
char equipName[128]; //设备名
int pinNum; //引脚号
int status; //“初始化设备”函数指针
int (*Init)(int pinNum); //“打开设备”函数指针
int (*open)(int pinNum); //“关闭设备”函数指针
int (*close)(int pinNum);
int (*readStatus)(int pinNum); //“读取设备状态”函数指针
int (*changeStatus)(int status); //“改变设备状态函数指针”
struct Equipment *next;
};
struct Equipment *addBathroomLightToLink(struct Equipment *phead); //“浴室灯”设备节点加入设备工厂链表函数声明
struct Equipment *addSecondfloorLightToLink(struct Equipment *phead); //“二楼灯”设备节点加入设备工厂链表函数声明
struct Equipment *addLivingroomLightToLink(struct Equipment *phead); //“客厅灯”设备节点加入设备工厂链表函数声明
struct Equipment *addRestaurantLightToLink(struct Equipment *phead); //“餐厅灯”设备节点加入设备工厂链表函数声明
struct Equipment *addFireDetectionToLink(struct Equipment *phead); //“火焰传感器”设备节点加入设备工厂链表函数声明
struct Equipment *addBuzzerToLink(struct Equipment *phead); //“蜂鸣器”设备节点加入设备工厂链表函数声明
struct Equipment *addEleLockToLink(struct Equipment *phead); //“电磁锁”设备节点加入设备工厂链表函数声明
(2) bathroomLight.c 文件(浴室灯):
#include "equipment.h"
int bathroomLightInit(int pinNum); //一些函数声明
int bathroomLightOpen(int pinNum);
int bathroomLightClose(int pinNum);
struct Equipment *addBathroomLightToLink(struct Equipment *phead);
struct Equipment bathroomLight = { //“浴室灯”设备链表节点
.equipName = "bathroomLight",
.pinNum = 21, //树莓派gpio引脚21
.Init = bathroomLightInit,
.open = bathroomLightOpen,
.close = bathroomLightClose,
};
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 Equipment *addBathroomLightToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &bathroomLight;
}else{
bathroomLight.next = phead;
phead = &bathroomLight;
return phead;
}
}
(3) secondfloorLight.c 文件(二楼灯):
#include "equipment.h"
int secondfloorLightInit(int pinNum); //一些函数声明
int secondfloorLightOpen(int pinNum);
int secondfloorLightClose(int pinNum);
struct Equipment *addSecondfloorLightToLink(struct Equipment *phead);
struct Equipment secondfloorLight = { //“二楼灯”设备链表节点
.equipName = "secondfloorLight",
.pinNum = 22, //树莓派gpio引脚22
.Init = secondfloorLightInit,
.open = secondfloorLightOpen,
.close = secondfloorLightClose,
.changeStatus = secondfloorLightChangeStatus,
};
int secondfloorLightInit(int pinNum) //初始化函数
{
pinMode(pinNum,OUTPUT); //配置引脚为输出引脚
digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
}
int secondfloorLightOpen(int pinNum) //打开函数
{
digitalWrite(pinNum,LOW);
}
int secondfloorLightClose(int pinNum) //关闭函数
{
digitalWrite(pinNum,HIGH);
}
struct Equipment *addSecondfloorLightToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &secondfloorLight;
}else{
secondfloorLight.next = phead;
phead = &secondfloorLight;
return phead;
}
}
(4) livingroomLight.c 文件(客厅灯):
#include "equipment.h"
int livingroomLightInit(int pinNum); //一些函数声明
int livingroomLightOpen(int pinNum);
int livingroomLightClose(int pinNum);
struct Equipment *addLivingroomLightToLink(struct Equipment *phead);
struct Equipment livingroomLight = { //“客厅灯”设备链表节点
.equipName = "livingroomLight",
.pinNum = 23, //树莓派gpio引脚23
.Init = livingroomLightInit,
.open = livingroomLightOpen,
.close = livingroomLightClose,
};
int livingroomLightInit(int pinNum) //初始化函数
{
pinMode(pinNum,OUTPUT); //配置引脚为输出引脚
digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
}
int livingroomLightOpen(int pinNum) //打开函数
{
digitalWrite(pinNum,LOW);
}
int livingroomLightClose(int pinNum) //关闭函数
{
digitalWrite(pinNum,HIGH);
}
struct Equipment *addLivingroomLightToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &livingroomLight;
}else{
livingroomLight.next = phead;
phead = &livingroomLight;
return phead;
}
}
(5) restaurantLight.c 文件(餐厅灯):
#include "equipment.h"
int restaurantLightInit(int pinNum); //一些函数声明
int restaurantLightOpen(int pinNum);
int restaurantLightClose(int pinNum);
struct Equipment *addRestaurantLightToLink(struct Equipment *phead);
struct Equipment restaurantLight = { //“餐厅灯”设备链表节点
.equipName = "restaurantLight",
.pinNum = 24, //树莓派gpio引脚24
.Init = restaurantLightInit,
.open = restaurantLightOpen,
.close = restaurantLightClose,
};
int restaurantLightInit(int pinNum) //初始化函数
{
pinMode(pinNum,OUTPUT); //配置引脚为输出引脚
digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
}
int restaurantLightOpen(int pinNum) //打开函数
{
digitalWrite(pinNum,LOW);
}
int restaurantLightClose(int pinNum) //关闭函数
{
digitalWrite(pinNum,HIGH);
}
struct Equipment *addRestaurantLightToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &restaurantLight;
}else{
restaurantLight.next = phead;
phead = &restaurantLight;
return phead;
}
}
(6) fireDetection.c 文件(火焰传感器):
#include "equipment.h"
int fireDetectionInit(int pinNum); //一些函数声明
int readFireDetectionStatus(int pinNum);
struct Equipment *addFireDetectionToLink(struct Equipment *phead);
struct Equipment fireDetection = { //“火焰传感器”设备链表节点
.equipName = "fireDetection",
.pinNum = 25, //树莓派gpio引脚25
.Init = fireDetectionInit,
.readStatus = readFireDetectionStatus,
};
int fireDetectionInit(int pinNum) //初始化函数
{
pinMode(pinNum,INPUT); //配置引脚为输入引脚
digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
}
int readFireDetectionStatus(int pinNum) //读取“火焰传感器”状态函数
{
return digitalRead(pinNum);
}
struct Equipment *addFireDetectionToLink(struct Equipment *phead)
{
if(phead == NULL){
return &fireDetection;
}else{
fireDetection.next = phead;
phead = &fireDetection;
return phead;
}
}
(7) buzzer.c 文件(蜂鸣器):
#include "equipment.h"
int buzzerInit(int pinNum); //一些函数声明
int buzzerOpen(int pinNum);
int buzzerClose(int pinNum);
struct Equipment *addBuzzerToLink(struct Equipment *phead);
struct Equipment buzzer = { //“蜂鸣器”设备链表节点
.equipName = "buzzer",
.pinNum = 29, //树莓派gpio引脚29
.Init = buzzerInit,
.open = buzzerOpen,
.close = buzzerClose,
};
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 Equipment *addBuzzerToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &buzzer;
}else{
buzzer.next = phead;
phead = &buzzer;
return phead;
}
}
(8) electromagneticLock.c 文件(电磁锁):
#include "equipment.h"
int eleLockInit(int pinNum); //一些函数声明
int eleLockOpen(int pinNum);
int eleLockClose(int pinNum);
struct Equipment *addEleLockToLink(struct Equipment *phead);
struct Equipment eleLock = { //“电磁锁”设备链表节点
.equipName = "eleLock",
.pinNum = 1, //树莓派gpio引脚 1
.Init = eleLockInit,
.open = eleLockOpen,
.close = eleLockClose,
};
int eleLockInit(int pinNum) //初始化函数
{
pinMode(pinNum,OUTPUT); //配置引脚为输出引脚
digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
}
int eleLockOpen(int pinNum) //打开函数
{
digitalWrite(pinNum,LOW);
}
int eleLockClose(int pinNum) //关闭函数
{
digitalWrite(pinNum,HIGH);
}
struct Equipment *addEleLockToLink(struct Equipment *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &eleLock;
}else{
eleLock.next = phead;
phead = &eleLock;
return phead;
}
}
(9) command.h 文件(指令控制类头文件):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
struct Command //指令控制工厂链表节点定义
{
char commandName[128]; //“控制方式”名字
char deviceFilesName[128]; //存放初始化功能需要打开的文件的路径
char command[32]; //存放指令
int fd; //存放文件描述符
int (*Init)(struct Command *file); //“初始化”函数指针
int s_fd; //存放套接字描述符
char ipAdress[32]; //存放IP地址
char port[12]; //存放端口号
int (*getCommand)(struct Command *cmd); //“获取指令”函数指针
char log[1024]; //日志(暂未使用)
struct Command *next;
};
struct Command *addVoiceControlToLink(struct Command *phead); //“语音控制”加入指令控制工厂链表函数声明
struct Command *addSocketControlToLink(struct Command *phead); //“网络控制”加入指令控制工厂链表函数声明
(10) voiceControl.c 文件(语音控制):
#include "command.h"
#include <unistd.h>
int voiceControlInit(struct Command *file); //“语音控制”功能初始化函数声明
int voiceControlGetCommand(struct Command *cmd); //“获取指令”函数声明
struct Command *addVoiceControlToLink(struct Command *phead); //“语音控制”加入指令控制工厂链表函数声明
struct Command voiceControl = { //“语音控制”链表节点
.commandName = "voiceControl",
.deviceFilesName = "/dev/ttyAMA0",
.command = {'\0'},
.Init = voiceControlInit,
.getCommand = voiceControlGetCommand,
.log = {'\0'},
};
int voiceControlInit(struct Command *file)
{
int fd;
if((fd = serialOpen(file->deviceFilesName,9600)) == -1){ //打开树莓派串口,波特率为9600
exit(-1);
}
file->fd = fd; //打开串口文件成功,返回“文件描述符”到“语音控制”链表节点中
}
int voiceControlGetCommand(struct Command *cmd) //“获取指令”函数
{
int nread = 0;
memset(cmd->command,'\0',sizeof(cmd->command)); //读取串口
nread = read(cmd->fd,cmd->command,sizeof(cmd->command)); //返回读取到数据的字节数
return nread;
}
struct Command *addVoiceControlToLink(struct Command *phead) //头插法将“语音控制”链表节点加入指令控制工厂链表函数
{
if(phead == NULL){
return &voiceControl;
}else{
voiceControl.next = phead;
phead = &voiceControl;
return phead;
}
}
(11) socketControl.c(网络端口控制):
#include "command.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int socketControlInit(struct Command *file); //“网络控制”功能初始化函数声明
struct Command *addSocketControlToLink(struct Command *phead); //“网络控制”加入指令控制工厂链表函数声明
struct Command socketControl = { //“网络控制”链表节点
.commandName = "socketControl",
.command = {'\0'},
.Init = socketControlInit,
.ipAdress = "192.168.43.97", //树莓派连接网络时的IP地址
.port = "8888", //树莓派打开待外界连接的端口号
.log = {'\0'},
};
int socketControlInit(struct Command *file)
{
int s_fd; //套接字描述符
struct sockaddr_in s_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
s_fd = socket(AF_INET,SOCK_STREAM,0); //创建套接字
if(s_fd == -1){ //创建套接字失败时
perror("socketControl error");
exit(-1);
}
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(file->port));
inet_aton(file->ipAdress,&s_addr.sin_addr);
if(bind(s_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in)) == -1){ //套接字与端口号绑定
perror("bind error");
exit(-1);
}
if(listen(s_fd,10) == -1){ //打开监听
perror("listen error");
exit(-1);
}
file->s_fd = s_fd; //套接字描述符返回到“网络控制”链表节点
}
struct Command *addSocketControlToLink(struct Command *phead) //头插法将设备节点加入设备工厂链表函数
{
if(phead == NULL){
return &socketControl;
}else{
socketControl.next = phead;
phead = &socketControl;
return phead;
}
}
更多推荐
已为社区贡献4条内容
所有评论(0)