基于全志H616的智能家居系统
本文介绍了一个基于Linux系统(ARM架构)的智能家居控制系统设计。系统采用OrangePi Zero2开发板,集成了语音控制、人脸识别、烟雾报警、远程监控等功能模块。通过语音指令或手机APP可以控制灯光、风扇等家电设备;人脸识别实现门锁智能开关;烟雾传感器实时监测火灾隐患并联动蜂鸣器报警。系统采用模块化设计,包括设备控制工厂类、指令工厂类和多线程处理架构,实现了语音交互、远程控制和智能安防等核
项目的需求,思考
随着越来越多物联网单品的出现,接下来的一步就是实现不同单品之间的互联。不同品牌、不同品类产品之间会在数据上做更多的融合和交互,但这样的跨产品的数据互通和互动大多可能还是没办法自发地进行,只能人为去干涉,比如通过手环读取智能秤的数据,通过温控器读取手环的数据等。等做到跨产品数据互通和互动之后再进一步的结果,不同产品之间不仅可以进行数据互通,并且将这其转化为主动的行为,不需要用户再去认为干涉。
设计一个小型智能家居,达到设备联动交互的效果。设计时需要考虑到项目的便捷,智能性,突出智能家居的特点。
在架构系统与平台的设计中,需要重点考虑以下几个方面:
目标平台为Linux系统,而架构选择ARM架构,例如可以适用于蜂巢快递柜和配送机器人等应用场景。这些应用若以单片机如C51和STM32为基础,无法满足其功能需求。同时,第三方库的局限性也是一个重要考虑因素。例如,刷脸支付和公交车收费设备需要集成支付宝SDK,但提供的libalipay.so库是为Linux系统构建的,因此设备必须运行Linux系统。
在图像识别、音频和视频处理等技术领域,Linux系统也是不可或缺的。尤其是人工智能型设备,通常需要更高的运算能力与更完善的系统支持,因此选择Linux作为操作系统显得尤为重要。能够支持Linux的架构一般包括X86、ARM、MIPS和PowerPC等,但在这些架构中,ARM的市场占有率最高。
总体设计
开发板:OrangePi Zero 2
开发语言:C、Python
编程工具:VS Code
SSH远程登录树莓派:MobaXterm
硬件准备: USB充电(当前实测可用:5V/2.5A)x1、USB转TYPE-Cx1、SU-03Tx1、烟雾报警模块x1、4路继电器x1、 OLEDx1、 电磁锁x1(5V 吸合开锁)、 蜂鸣器x1、小风扇+电机x1、面包板x1、 5号1.5V电池x6 、 2节电池盒x1、4节电池盒x1、带3路led灯、小房子模型(3.3V可驱动)
设计架构

语音接入控制各类家电,如客厅灯、卧室灯、风扇 应用Socket网络编程,实现Socket发送指令远程控制各类家电 烟雾警报监测, 实时检查是否存在煤气泄漏或者火灾警情,当存在警情时及时触发蜂鸣器报警及语音播报 控制人脸识别打开房门功能,并语音播报识别成功或者失败 局域网实时视频监控 OLED屏实话显示当前主板温度、警情信息及控制指令信息 人脸识别调用的接口是人工智能接口,阿里云识别模型是通过训练后的模型,精准度取决于训练程度,人工智能范畴在常规嵌入式设备负责执行居多, 总体思路是嵌入式设备负责数据采集,然后转发给人工智能识别后,拿到结果进行执行器动作。
程序运行结果测试与分析
在完成orangepi与各种硬件的引脚接线后,可以开始实现各类功能。

查看usb摄像头模块是否成功挂载到设备上(用于后续人脸识别)

使用MJPG-Streamer视频流,通过开发板的ip与端口号来捕捉实时视频

在阿里云平台将人脸识别SDK权限配置到开发板中,下载所需要的库包

由于阿里云人脸识别接口使用的是Python语言,需要用到C调用Python接口
封装一个C联调Python的函数;官方提供了读取环境变量中的代码,直接使用
|
# -*- coding: utf-8 -*- # 引入依赖包 # 最低SDK版本要求:facebody20191230的SDK版本需大于等于4.0.8 # pip install alibabacloud_facebody20191230 import os import io from urllib.request import urlopen from alibabacloud_facebody20191230.client import Client from alibabacloud_facebody20191230.models import CompareFaceAdvanceRequest from alibabacloud_tea_openapi.models import Config from alibabacloud_tea_util.models import RuntimeOptions def face_detect(): #定义成一个函数,方便调用! config = Config( # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。 # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html。 # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。 access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'), access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), # 访问的域名 endpoint='facebody.cn-shanghai.aliyuncs.com', # 访问的域名对应的region region_id='cn-shanghai' ) runtime_option = RuntimeOptions() compare_face_request = CompareFaceAdvanceRequest() #场景一:文件在本地 streamA = open(r'/home/orangepi/tmp/shiyahao.jpg', 'rb') #预存的照片 compare_face_request.image_urlaobject = streamA
streamB = open(r'/home/orangepi/tmp/raonaibao.jpg', 'rb') #待测试的照片 compare_face_request.image_urlbobject = streamB try: # 初始化Client client = Client(config) response = client.compare_face_advance(compare_face_request, runtime_option) # 获取整体结果 #print(response.body) # 获取单个字段 confidence = response.body.to_map()['Data']['Confidence'] #to_map()函数很重要,不要忘记 score = int(confidence) print("相似度分数为:", score) return score except Exception as error: # 获取整体报错信息 print(error) # 获取单个字段 print(error.code) # tips: 可通过error.__dict__查看属性名称 # 关闭流 streamA.close() streamB.close() |
|
#include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <Python.h> void face_init(void) //初始化python环境 { Py_Initialize(); PyObject *sys = PyImport_ImportModule("sys"); PyObject *path = PyObject_GetAttrString(sys, "path"); PyList_Append(path, PyUnicode_FromString(".")); } void face_final(void) //释放python环境 { Py_Finalize(); } int face_score(void) { PyObject *pModule = PyImport_ImportModule("face"); //加载python文件 if (!pModule) { PyErr_Print(); printf("Error: failed to load module\n"); goto FAILED_MODULE; //goto的意思就是如果运行到这里就直接跳转到FAILED_MODULE } PyObject *pFunc = PyObject_GetAttrString(pModule, "face_detect"); //加载python文件中的对应函数 if (!pFunc) { PyErr_Print(); printf("Error: failed to load function\n"); goto FAILED_FUNC; } PyObject *pValue = PyObject_CallObject(pFunc, NULL); if (!pValue) { PyErr_Print(); printf("Error: function call failed\n"); goto FAILED_VALUE; } int result = 0; if (!PyArg_Parse(pValue, "i", &result)) //ace_detect函数返回的是已经经过提取和取证过的置信度score { PyErr_Print(); printf("Error: parse failed"); goto FAILED_RESULT; }
category = (char *)malloc(sizeof(char) * (strlen(result) + 1) ); //开辟一个新的字符串常量。+1是为了留出空间给\0 memset(category, 0, (strlen(result) + 1)); //初始化字符串 strncpy(category, result, (strlen(result) + 1)); //将result的结果复制给新的字符串 FAILED_RESULT: Py_DECREF(pValue); FAILED_VALUE: Py_DECREF(pFunc); FAILED_FUNC: Py_DECREF(pModule); FAILED_MODULE: return result; } |
阿里云人脸识别1:N的api中,在后台数据库上传人脸数据后,摄像头捕捉到的人脸会与数据库中的数据进行比对,通过判断置信度的值来查看结果是否准确。
若大于0.6一般相似度较高。
接下来配置语音模块SU-03T,在官网配置完后会生成文件;烧录到模块中使用串口助手进行测试,发送对应的指令查看返回的结果是否正确
工厂类中发送接收指令;
|
/* InputCommand.h */ #ifndef __INPUTCOMMAND_H__ #define __INPUTCOMMAND_H__ #include <stdio.h> // 包含标准输入输出头文件 #include <sys/types.h> // 包含系统数据类型头文件 #include <sys/socket.h> // 包含系统套接字库的头文件 #include <stdlib.h> // 包含标准库头文件 #include <arpa/inet.h> // 包含网络地址转换头文件 #include <netinet/in.h> // 包含IPv4地址头文件 #include <string.h> // 包含字符串头文件 #include <unistd.h> // 包含unistd.h头文件 #include <wiringSerial.h> // 包含wiringSerial库头文件,用于串口通信 #include <wiringPi.h> // 包含wiringPi库头文件,用于GPIO控制 struct InputCommand { //指令工厂类 char commandName[128]; //设备名称 char deviceName[128]; char command[128]; //指令内容 int (*init)(struct InputCommand *voicer, char *ipAdress, char *port); //初始化函数 int (*getCommand)(struct InputCommand *voicer); //获取指令函数 int (*putOpenCommand)(struct InputCommand *voicer); //发送打开指令函数 int (*putCloseCommand)(struct InputCommand *voicer); //发送关闭指令函数 int fd; //文件描述符 char port[12]; //端口号 char ipAdress[32]; //IP地址 int s_fd; //套接字描述符 char log[1024]; //日志信息 struct InputCommand *next; //链表下一个节点 }; struct InputCommand* addsocketCommandToInputCommandLink(struct InputCommand *phead); //向输入指令链表中添加socket指令 struct InputCommand *addVoiceContrlToInputCommanderLink(struct InputCommand *phead); //向输入指令链表中添加语音模块指令 #endif |
Socket网络编程发送接收信息
|
/* Socket.c */ #include "InputCommand.h" int socketInit(struct InputCommand *socketMes, char *ipAdress, char *port) //初始化socket服务器 { int s_fd; // 套接字文件描述符 struct sockaddr_in server_addr; // 服务器地址结构体 memset(&server_addr, 0, sizeof(server_addr)); // 服务器地址结构体清零 //初始化套接字 s_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建TCP/IP套接字 if(s_fd == -1){ printf("创建套接字失败!\n"); perror("socket"); // 输出错误信息 exit(-1); } server_addr.sin_family = AF_INET; // 设置服务器地址族为IPv4 server_addr.sin_port = htons(atoi(socketMes->port)); // 设置服务器端口号 inet_aton(socketMes->ipAdress, &server_addr.sin_addr); // 设置服务器IP地址 //绑定IP地址和端口 int ret = bind(s_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)); // 绑定套接字到服务器地址 if(ret == -1){ printf("绑定服务器地址失败\n"); perror("bind"); // 输出错误信息 exit(-1); } //开始监听 ret = listen(s_fd, 10); // 监听套接字 if(ret == -1){ printf("监听套接字失败\n"); perror("listen"); // 输出错误信息 exit(-1); } printf("服务器启动成功!\n"); socketMes->s_fd = s_fd; // 保存套接字文件描述符 return s_fd; // 返回套接字文件描述符 } int socketGetCommand(struct InputCommand *socketMes) //获取socket客户端指令 { int c_fd; // 客户端套接字文件描述符 int n_read; // 读取字节数 struct sockaddr_in client_addr; // 客户端地址结构体 memset(&client_addr, 0, sizeof(client_addr)); // 客户端地址结构体清零 int client_addr_len = sizeof(client_addr); // 客户端地址长度 printf("等待客户端连接...\n"); c_fd = accept(socketMes->s_fd, (struct sockaddr *)&client_addr, &client_addr_len); // 接受客户端连接请求 if(c_fd == -1){ printf("接受客户端连接请求失败\n"); } printf("客户端连接成功!\n"); // 输出客户端连接信息 printf("客户端地址:%s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); n_read = read(c_fd, socketMes->command, sizeof(socketMes->command)); // 读取客户端发送的指令 if(n_read == -1){ printf("读取数据失败\n"); perror("read"); // 输出错误信息 }else{ printf("接收字节数:%d\n",n_read); // 输出接收到的数据 printf("接收数据:%s\n", socketMes->command); // 输出接收到的数据 } return n_read; // 返回读取字节数 } struct InputCommand socketCommand = { //socket客户端指令工厂 .commandName = "socketServer", //设备名称 .port = "8848", //端口号 .ipAdress = "192.168.31.249", //IP地址 .command = {'\0'}, //指令内容 .init = socketInit, //初始化指令 .getCommand = socketGetCommand, //获取指令内容 .log = {'\0'}, //日志信息 .next = NULL //链表下一个节点 }; struct InputCommand* addsocketCommandToInputCommandLink(struct InputCommand *phead) //向输入指令链表中添加socket指令 { if(phead == NULL){ phead = &socketCommand; }else{ socketCommand.next = phead; phead = &socketCommand; } return phead; } |
设备工厂类添加代码
|
/* contrlDevices.h */ #ifndef __CONTROL_DEVICES_H__ #define __CONTROL_DEVICES_H__ #include <stdio.h> #include <stdlib.h> #include <wiringPi.h> #include <string.h> #include <unistd.h> struct Devices { // 控制设备类 char devicesName[128]; // 设备名称 int devicesPin; // 设备引脚 int status; // 设备状态 int (*open)(int pin); // 打开设备 int (*close)(int pin); // 关闭设备 int (*devicesInit)(int pin); // 初始化设备 int (*readStatus)(int pin); // 读取设备状态 int (*changeStatus)(int status); // 修改设备状态 struct Devices *next; // 链表下一个节点 }; struct Devices* addChuFangLightToDevicesLink(struct Devices *phead); // 向设备链表中添加厨房灯 struct Devices* addKeTingLightToDevicesLink(struct Devices *phead); // 向设备链表中添加客厅灯 struct Devices* addceSuoLightToDevicesLink(struct Devices *phead); // 向设备链表中添加卫生间灯 struct Devices* addwoShiLightToDevicesLink(struct Devices *phead); // 向设备链表中添加卧室灯 struct Devices* addyongChiLightToDevicesLink(struct Devices *phead); // 向设备链表中添加泳池灯 struct Devices* addfireToDevicesLink(struct Devices *phead); // 向设备链表中添加火焰传感器 struct Devices* addyanWuToDevicesLink(struct Devices *phead); // 向设备链表中添加烟雾传感器 struct Devices* addCameraToDevicesLink(struct Devices *phead); // 向设备链表中添加摄像头 struct Devices* addBeepToDevicesLink(struct Devices *phead); // 向设备链表中添加蜂鸣器设备 struct Devices* addFanToDevicesLink(struct Devices *phead); // 向设备链表中添加风扇设备 struct Devices* addLockToDevicesLink(struct Devices *phead); // 向设备链表中添加电磁锁设备 #endif |
Main-主函数
|
#include "contrlDevices.h" // 包含设备控制头文件 #include "InputCommand.h" // 包含指令头文件 #include <unistd.h> // 包含unistd.h头文件 #include <pthread.h> // 包含pthread.h头文件 #include "peopleFace.h" // 包含人脸识别头文件 pthread_mutex_t mutex; // 互斥锁,用于线程之间的互斥访问 struct Devices *pDevicesHead = NULL; // 设备链表头指针 struct InputCommand *pCommandHead = NULL; // 指令链表头指针 struct InputCommand *SU03THandler; // 语音模块对象 struct InputCommand *socketHandler; // Socket对象 int c_fd; // 客户端套接字文件描述符 struct Devices *cmd = NULL; // 指令对象 struct Devices* getDevicesByName(struct Devices *pDevicesHead, char *name) // 根据设备名称获取设备对象 { struct Devices *p = pDevicesHead; if(pDevicesHead == NULL){ // 设备链表为空 return NULL; }else{ while(p != NULL){ // 遍历设备链表 if(strcmp(p->devicesName, name) == 0){ // 找到设备 return p; // 返回设备对象 } p = p->next; } return NULL; // 没有找到设备 } } struct InputCommand* getCommandByName(struct InputCommand *pDevicesHead, char *name) // 根据指令名称获取指令对象 { struct InputCommand *p = pDevicesHead; if(pDevicesHead == NULL){ // 设备链表为空 return NULL; }else{ while(p != NULL){ // 遍历设备链表 if(strcmp(p->commandName, name) == 0){ // 找到设备 return p; // 返回设备对象 } p = p->next; } return NULL; // 没有找到设备 } } void* SU03T_thread_func(void *arg) // 语音线程函数 { int n_read; int score = 0; // 人脸识别得分 face_init(); // 初始化人脸识别引擎
SU03THandler = getCommandByName(pCommandHead, "voice"); // 获取语音模块对象 if(SU03THandler == NULL){ printf("获取语音模块对象失败\n"); pthread_exit(NULL); // 退出线程 }else{ if(SU03THandler->init(SU03THandler,NULL,NULL) < 0){ // 语音模块初始化 printf("语音模块初始化失败\n"); pthread_exit(NULL); // 退出线程 }else{ printf("语音模块初始化成功\n"); } while(1){ n_read = SU03THandler->getCommand(SU03THandler); // 获取指令 if(n_read == 0){ printf("超时!\n"); } printf("获取指令成功: %s\n", SU03THandler->command); // 打印指令 pthread_mutex_lock(&mutex); // 加互斥锁 if(strstr(SU03THandler->command, "pcf") != NULL){ printf("获取打开厨房灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lcf") != NULL){ printf("获取关闭厨房灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "pkt") != NULL){ printf("获取打开客厅灯指令\n"); cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lkt") != NULL){ printf("获取关闭客厅灯指令\n"); cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "pcs") != NULL){ printf("获取打开卫生间灯指令\n"); cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lcs") != NULL){ printf("获取关闭卫生间灯指令\n"); cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "pws") != NULL){ printf("获取打开卧室灯指令\n"); cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lws") != NULL){ printf("获取关闭卧室灯指令\n"); cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "pyc") != NULL){ printf("获取打开泳池灯指令\n"); cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lyc") != NULL){ printf("获取关闭泳池灯指令\n"); cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "psy") != NULL){ printf("获取打开所有灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "lsy") != NULL){ printf("获取关闭所有灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(SU03THandler->command, "pjs") != NULL){ printf("获取打开加湿器指令\n"); if( SU03THandler->putOpenCommand(SU03THandler) < 0){ printf("发送打开加湿器指令失败!\n"); }else{ printf("发送打开加湿器指令成功!\n"); } }else if(strstr(SU03THandler->command, "ljs") != NULL){ printf("获取关闭加湿器指令\n"); if( SU03THandler->putCloseCommand(SU03THandler) < 0){ printf("发送关闭加湿器指令失败!\n"); }else{ printf("发送关闭加湿器指令成功!\n"); } }else if(strstr(SU03THandler->command, "ace") != NULL){ printf("获取人脸识别指令\n"); cmd = getDevicesByName(pDevicesHead, "camera"); //获取摄像头对象 if(cmd != NULL){ int ret = cmd->open(0); //拍照 if(ret == 1){ score = face_score(); //人脸识别 if(score > 80){ printf("识别成功,得分:%d\n", score); cmd = getDevicesByName(pDevicesHead, "lock"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); printf("门锁打开成功!\n"); sleep(3); //延时3秒 cmd->close(cmd->devicesPin); printf("门锁关闭成功!\n"); } }else{ printf("识别失败,得分:%d\n", score); } cmd->close(0); //清除摄像头照片 }else{ printf("拍照失败!\n"); } score = 0; //清空得分 } } else{ printf("指令不支持!\n"); } pthread_mutex_unlock(&mutex); // 解互斥锁 } } face_final(); //释放人脸识别引擎 pthread_exit(NULL); // 退出线程 } void* read_thread_func(void *arg) // 读线程函数 { int n_read; memset(socketHandler->command, '\0', sizeof(socketHandler->command)); // 清空指令缓冲区 while(1){ pthread_mutex_lock(&mutex); // 加互斥锁 n_read = read(c_fd, socketHandler->command, sizeof(socketHandler->command));// 读取客户端发送的指令 if(n_read == -1){ printf("读取数据失败\n"); perror("read"); // 输出错误信息 }else{ //printf("接收字节数:%d\n",n_read); // 输出接收到的数据 printf("接收数据:%s\n", socketHandler->command); // 输出接收到的数据 if(strstr(socketHandler->command, "opencf") != NULL){ printf("获取打开厨房灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closecf") != NULL){ printf("获取关闭厨房灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "openkt") != NULL){ printf("获取打开客厅灯指令\n"); cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closekt") != NULL){ printf("获取关闭客厅灯指令\n"); cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "opencs") != NULL){ printf("获取打开卫生间灯指令\n"); cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closecs") != NULL){ printf("获取关闭卫生间灯指令\n"); cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "openws") != NULL){ printf("获取打开卧室灯指令\n"); cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closews") != NULL){ printf("获取关闭卧室灯指令\n"); cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "openyc") != NULL){ printf("获取打开泳池灯指令\n"); cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closeyc") != NULL){ printf("获取关闭泳池灯指令\n"); cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "openfs") != NULL){ printf("获取打开排风扇指令\n"); cmd = getDevicesByName(pDevicesHead, "fan"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closefs") != NULL){ printf("获取关闭排风扇指令\n"); cmd = getDevicesByName(pDevicesHead, "fan"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "opensy") != NULL){ printf("获取打开所有灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else if(strstr(socketHandler->command, "closesy") != NULL){ printf("获取关闭所有灯指令\n"); cmd = getDevicesByName(pDevicesHead, "chuFangLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "keTingLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "ceSuoLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "woShiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "yongChiLight"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } }else if(strstr(socketHandler->command, "openjs") != NULL){ printf("获取打开加湿器指令\n"); SU03THandler = getCommandByName(pCommandHead, "voice"); if( SU03THandler->putOpenCommand(SU03THandler) < 0){ printf("发送打开加湿器指令失败!\n"); }else{ printf("发送打开加湿器指令成功!\n"); } }else if(strstr(socketHandler->command, "closejs") != NULL){ printf("获取关闭加湿器指令\n"); SU03THandler = getCommandByName(pCommandHead, "voice"); if( SU03THandler->putCloseCommand(SU03THandler) < 0){ printf("发送关闭加湿器指令失败!\n"); }else{ printf("发送关闭加湿器指令成功!\n"); } }else if(strstr(socketHandler->command, "exit") != NULL){ printf("退出程序指令\n"); pthread_mutex_unlock(&mutex); // 解互斥锁 pthread_exit(NULL); // 退出线程 }else{ printf("请发送正确的指令!\n"); } } pthread_mutex_unlock(&mutex); // 解互斥锁 } pthread_exit(NULL); // 退出线程 } void* socket_thread_func(void *arg) // Socket线程函数 { pthread_t readThread; // 读线程 struct sockaddr_in client_addr; // 客户端地址结构体 memset(&client_addr, 0, sizeof(client_addr)); // 客户端地址结构体清零 int client_addr_len = sizeof(client_addr); // 客户端地址长度 socketHandler = getCommandByName(pCommandHead, "socketServer"); // 获取socket模块对象 if(socketHandler == NULL){ printf("获取Socket对象失败\n"); pthread_exit(NULL); // 退出线程 } socketHandler->init(socketHandler,NULL,NULL); // Socket初始化 printf("等待客户端连接...\n"); while(1){ c_fd = accept(socketHandler->s_fd, (struct sockaddr *)&client_addr, &client_addr_len); // 接受客户端连接请求 if(c_fd == -1){ printf("接受客户端连接请求失败\n"); } printf("客户端连接成功!\n"); // 输出客户端连接信息 printf("客户端地址:%s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); pthread_create(&readThread, NULL, read_thread_func, NULL); // 创建读线程 pthread_join(readThread, NULL); // 等待读线程退出 } pthread_exit(NULL); // 退出线程 } void* fire_thread_func(void *arg) // 火灾检测线程函数 { printf("开始检测火灾...\n"); while(1){ pthread_mutex_lock(&mutex); // 加互斥锁 cmd = getDevicesByName(pDevicesHead, "fire"); // 获取火灾检测器对象 if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); if(cmd->readStatus(cmd->devicesPin) == 1){ printf("火灾发生!\n"); cmd = getDevicesByName(pDevicesHead, "beep"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else{ printf("无火灾发生!\n"); cmd = getDevicesByName(pDevicesHead, "beep"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } } } pthread_mutex_unlock(&mutex); // 解互斥锁 sleep(1); // 睡眠1秒 } pthread_exit(NULL); // 退出线程 } void* MQ5_thread_func(void *arg) // 烟雾传感器线程函数 { printf("开始检测烟雾...\n"); while(1){ pthread_mutex_lock(&mutex); // 加互斥锁 cmd = getDevicesByName(pDevicesHead, "yanWu"); // 获取烟雾报警器对象 if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); if(cmd->readStatus(cmd->devicesPin) == 1){ printf("烟雾报警!\n"); cmd = getDevicesByName(pDevicesHead, "beep"); if(cmd != NULL){ printf("找到厨房灯!\n"); cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "fan"); if(cmd != NULL){ printf("找到风扇!\n"); cmd->devicesInit(cmd->devicesPin); cmd->open(cmd->devicesPin); } }else{ printf("无烟雾报警!\n"); cmd = getDevicesByName(pDevicesHead, "beep"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } cmd = getDevicesByName(pDevicesHead, "fan"); if(cmd != NULL){ cmd->devicesInit(cmd->devicesPin); cmd->close(cmd->devicesPin); } } } pthread_mutex_unlock(&mutex); // 解互斥锁 sleep(1); // 睡眠1秒 } pthread_exit(NULL); // 退出线程 } int main() { pthread_t SU03T_thread; // 语音线程 pthread_t socket_thread; // Socket线程 pthread_t fire_thread; // 火灾检测线程 pthread_t MQ5_thread; // 烟雾传感器线程 if (wiringPiSetup() == -1) { //初始化wiringPi printf("初始化wiringPi失败!\n"); return 1; } face_init(); //初始化人脸识别引擎 pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 // 1.指令工厂初始化 pCommandHead = addsocketCommandToInputCommandLink(pCommandHead); // 添加Socket到指令链表 pCommandHead = addVoiceContrlToInputCommanderLink(pCommandHead); // 添加语音控制到指令链表 // 2.控制设备工厂初始化 pDevicesHead = addChuFangLightToDevicesLink(pDevicesHead); // 添加厨房灯到设备链表 pDevicesHead = addKeTingLightToDevicesLink(pDevicesHead); // 添加客厅灯到设备链表 pDevicesHead = addceSuoLightToDevicesLink(pDevicesHead); // 添加卫生间灯到设备链表 pDevicesHead = addwoShiLightToDevicesLink(pDevicesHead); // 添加卧室灯到设备链表 pDevicesHead = addyongChiLightToDevicesLink(pDevicesHead); // 添加泳池灯到设备链表 pDevicesHead = addfireToDevicesLink(pDevicesHead); // 添加火灾检测器到设备链表 pDevicesHead = addyanWuToDevicesLink(pDevicesHead); // 添加烟雾报警器到设备链表 pDevicesHead = addCameraToDevicesLink(pDevicesHead); // 添加摄像头到设备链表 pDevicesHead = addBeepToDevicesLink(pDevicesHead); // 添加蜂鸣器到设备链表 pDevicesHead = addFanToDevicesLink(pDevicesHead); // 添加风扇到设备链表 pDevicesHead = addLockToDevicesLink(pDevicesHead); // 添加门锁到设备链表 // 3.线程池建立(语音、Socket、火灾、烟雾...) pthread_create(&SU03T_thread, NULL, SU03T_thread_func, NULL); // 创建语音线程 pthread_create(&socket_thread, NULL, socket_thread_func, NULL); // 创建Socket线程 pthread_create(&fire_thread, NULL, fire_thread_func, NULL); // 创建火灾检测线程 pthread_create(&MQ5_thread, NULL, MQ5_thread_func, NULL); // 创建烟雾传感器线程 pthread_join(SU03T_thread, NULL); // 等待语音线程退出 pthread_join(socket_thread, NULL); // 等待Socket线程退出 pthread_join(fire_thread, NULL); // 等待火灾检测线程退出 pthread_join(MQ5_thread, NULL); // 等待烟雾传感器线程退出
while(1){
} pthread_mutex_destroy(&mutex); // 销毁互斥锁 face_final(); //释放人脸识别引擎 return 0; } |
最终效果


火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)