项目的需求,思考

随着越来越多物联网单品的出现,接下来的一步就是实现不同单品之间的互联。不同品牌、不同品类产品之间会在数据上做更多的融合和交互,但这样的跨产品的数据互通和互动大多可能还是没办法自发地进行,只能人为去干涉,比如通过手环读取智能秤的数据,通过温控器读取手环的数据等。等做到跨产品数据互通和互动之后再进一步的结果,不同产品之间不仅可以进行数据互通,并且将这其转化为主动的行为,不需要用户再去认为干涉。

设计一个小型智能家居,达到设备联动交互的效果。设计时需要考虑到项目的便捷,智能性,突出智能家居的特点。

在架构系统与平台的设计中,需要重点考虑以下几个方面:

目标平台为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;

}

最终效果

Logo

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

更多推荐