linux项目—基于树莓派的智能家居系统

1、项目简介

        项目采用工厂设计模式。所有控制以及外设的设备都做成一个个对象(java思想),分别将命令控制的连成一个控制链表,外设设备做成一个外设设备的链表,这样做是为了方便以后功能模块的添加。其中为了能分别做好控制,我们采用多线程来实现。

 工厂模式详解:

 最通俗易懂的讲解工厂模式_晴夏。的博客-CSDN博客https://blog.csdn.net/weixin_43757333/article/details/126294625

实现功能:

        树莓派通过摄像头将图像上传到翔云平台进行人脸识别开锁。使用串口连接语音模块,实现语音对浴室灯、卧室灯、餐厅灯、锁、风扇等的控制。通过socket连接全志,将全志作为客户端,通过接收全志发来的指令控制家居,同时将温度、湿度、报警器、红外等检测状态通过socket发送给全志,实时掌握家居情况。

智能家居功能拆分图:

2、代码示例

2.1树莓派代码:

contrlDevices.h(外设头文件)

#include <wiringPi.h>
#include <stdio.h>
#include <curl/curl.h>

typedef unsigned int bool;

struct Devices
{
    char deviceName[128]; //设备名
    int status;           //读取到的数据
    int pinNum;           //引脚号

    int (*open)(int pinNum);       //打开设备函数指针
    int (*close)(int pinNum);      //关闭设备函数指针
    int (*deviceInit)(int pinNum); //设备初始化函数指针

    int (*readStatus)(int pinNum);  //读取数据函数指针
    int (*changStatus)(int status); //改变数据函数指针

    //摄像头相关的
    void (*justDoOnce)();           
    char *(*getFace)();             
    char *(*getPicFromOCRBase64)(); 
    size_t (*readData)();           

    CURL *curl;
    char *key;
    char *secret;
    int typeId;
    char *format;
    bool (*cameraInit)(struct Devices *camera);
    int yesNum;
    int noNum;

    struct Devices *next;
};



inputCommand.h(控制头文件)

#include <wiringPi.h>
#include <stdio.h>

struct InputCommander
{
    char commandName[128]; // socket名
    char deviceName[128];  //串口名
    char comand[32];       //控制命令

    int (*Init)(struct InputCommander *voicer, char *ipAdress, char *port); // socket初始化
    int (*getCommand)(struct InputCommander *voicer);                       //读取数据

    char log[1024];
    int fd;
    char port[12];     //端口号
    char ipAdress[32]; // IP地址
    int sfd;
    int cfd;

    struct InputCommander *next;
};

start_web_video.sh(监控脚本)

cd ../mjpg-streamer/mjpg-streamer-experimental/

./mjpg_streamer -i "./input_raspicam.so" -o "./output_http.so -w ./www"

mainPro(主函数)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "contrlDevices.h"
#include "inputCommand.h"

//控制添加到控制链表的函数声明
struct InputCommander *addVoiceContrlToInputCommanderLink(struct InputCommander *phead);
struct InputCommander *addsocketContrlToInputCommanderLink(struct InputCommander *phead);

//设备加到设备链表函数的声明
struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices *addupStairLightToDeviceLink(struct Devices *phead);
struct Devices *addlivingroomLightToDeviceLink(struct Devices *phead);
struct Devices *addrestaurantLightToDeviceLink(struct Devices *phead);
struct Devices *addDoorLockToDeviceLink(struct Devices *phead);
struct Devices *addFanToDeviceLink(struct Devices *phead);
struct Devices *addFireToDeviceLink(struct Devices *phead);
struct Devices *addInfraredToDeviceLink(struct Devices *phead);
struct Devices *addBuzzerToDeviceLink(struct Devices *phead);
struct Devices *addcameraToDeviceLink(struct Devices *phead);
struct Devices *addVibrateToDeviceLink(struct Devices *phead);
#define HIGH_TIME 32



#define key 6 //拍照按键

pthread_t voiceThread;       //语音识别线程
pthread_t socketThread;      //服务器线程
pthread_t writeThread;       //通知线程:向客服端发送消息
pthread_t fireThread;        //火灾检测线程
pthread_t vibrateThread;       //震动检测线程
pthread_t infraredThread;       //人体红外检测线程
pthread_t remoteThread;      //遥控线程
pthread_t keyThread;         //按键检测线程
pthread_t cameraThread;      //人脸识别线程
pthread_t monitoringThread;  //视频监控线程
pthread_t clientWemosThread; //客服端线程
pthread_t dht11Thread;       //温湿度线程

struct InputCommander *pCommandHead = NULL;
struct Devices *pdeviceHead = NULL;
struct InputCommander *socketHandler = NULL;

pthread_mutex_t mutex; //定义互斥量(锁)

unsigned long databuf;

int c_fd; //注意:涉及到多线程不要轻易的去传参

int beep = 0; //蜂鸣器标志位   0:未被使用   1:被火灾传感器使用    2:被震动传感器使用
//摄像头相关,改变返回值命名,因为C语言中没有这样的返回值
#define true 1
#define false 0
typedef unsigned int bool;
char buf[1024] = {'\0'};

/* [0]:温度   [1]:湿度   [2]:火灾监控   [3]:震动监控   [4]:人体红外监控*/
char Message[5][100] = {"温度未启用!", "湿度未启用!", "火灾未启用!", "震动未启用!", "红外未启用!"};
int write_flag = 0; //标记位,标记通知线程是否打开     1:打开   0:关闭

int infrared_flag = 0; //红外检测标志位     1:打开   0:关闭

struct Devices *findDeviceByName(char *name, struct Devices *phead) //查询设备
{
    if (phead == NULL)
    {
        return NULL;
    }

    while (phead != NULL)
    {
        // printf("phead:%s  name:%s\n", phead->deviceName, name);
        if (strstr(phead->deviceName, name) != NULL)
        {
            return phead;
        }
        phead = phead->next;
    }

    return NULL;
}

struct InputCommander *findCommandByName(char *name, struct InputCommander *phead) //查询控制
{
    if (phead == NULL)
    {
        return NULL;
    }
    while (phead != NULL)
    {
        if (strcmp(phead->commandName, name) == 0)
        {
            return phead;
        }
        phead = phead->next;
    }
    return NULL;
}

void *cameraThread_func(void *data) //起线程的函数有格式要求
{
    struct Devices *cameraTemp;

    cameraTemp = findDeviceByName("camera", pdeviceHead); 

    if (cameraTemp == NULL)
    { 
        printf("find camera error\n");
        pthread_exit(NULL); 
    }

    cameraTemp->justDoOnce(); //调用postUrl函数
}

unsigned char readSensorData(void) //温湿度初始化
{
    char crc;
    char i;

    pinMode(6, OUTPUT);   // 将模式设置为输出
    digitalWrite(6, LOW); // 输出高电平
    delay(25);
    digitalWrite(6, HIGH); // 输出低电平
    pinMode(6, INPUT);     // 将模式设置为输入
    pullUpDnControl(6, PUD_UP);

    delayMicroseconds(27);
    if (digitalRead(6) == 0) 
    {
        while (!digitalRead(6)); 

        for (i = 0; i < 32; i++)
        {
            while (digitalRead(6)); // 数据时钟启动
            while (!digitalRead(6)); //数据开始
            delayMicroseconds(HIGH_TIME);
            databuf *= 2;
            if (digitalRead(6) == 1) // 1
            {
                databuf++;
            }
        }

        for (i = 0; i < 8; i++)
        {
            while (digitalRead(6)); // 数据时钟启动
            while (!digitalRead(6)); // 数据开始
            delayMicroseconds(HIGH_TIME);
            crc *= 2;
            if (digitalRead(6) == 1) // 1
            {
                crc++;
            }
        }
        return 1;
    }
    else
    {
        return 0;
    }
}

void *dht11_thread(void *datas) //温湿度线程
{
    int W = 0, w = 0;
    int S = 0, s = 0;
    // int count = 0;
    int temp = 0;

    if (-1 == wiringPiSetup())
    {
        printf("获取wiringpi库失败!");
    }
	printf("温湿度线程开启\n");
    pinMode(6, OUTPUT);    
    digitalWrite(6, HIGH); 

    printf("温湿度开始读取-------\n");
    while (1)
    {
        pinMode(6, OUTPUT);    
        digitalWrite(6, HIGH); 
        delay(3000);

        if (readSensorData())
        {

            W = (databuf >> 8) & 0xff;
            w = databuf & 0xff;
            S = (databuf >> 24) & 0xff;
            s = (databuf >> 16) & 0xff;
            printf("传感器数据读取正常!\n");
            if (temp == 0)
            {
                w++;
                s++;
                temp++;
            }
            else if (temp == 1)
            {
                if (w >= 1)
                {
                    w--;
                }
                if (s >= 1)
                {
                    w--;
                }
                temp--;
            }

            if ((W >= 15) && (W <= 35) && (S <= 95))
            {
                memset(Message[0], 0, sizeof Message[0]); //清空数组
                memset(Message[1], 0, sizeof Message[1]);
                sprintf(Message[0], "%d.%d C", W, w); //温度
                sprintf(Message[1], "%d.%d", S, s);   //湿度
            }

            databuf = 0;
        }
        else
        {
            printf("温湿度检测失败!\n");
            databuf = 0;
        }

    }
}

void *fire_thread(void *datas) //火灾线程
{
    char msg[100];
    int status;
    struct Devices *fireDeviceTmp = NULL;
    struct Devices *buzzerDeviceTmp = NULL;

    fireDeviceTmp = findDeviceByName("fire", pdeviceHead); //在设备工厂找到火灾模块
    buzzerDeviceTmp = findDeviceByName("buzzser", pdeviceHead);

    fireDeviceTmp->deviceInit(fireDeviceTmp->pinNum); //火灾模块初始化
    buzzerDeviceTmp->deviceInit(buzzerDeviceTmp->pinNum);
    printf("火灾线程初始化成功\n");

    while (1)
    {
        delay(10);
        status = fireDeviceTmp->readStatus(fireDeviceTmp->pinNum); //读取火灾模块实时数据
        if (status == 0)
        {
            beep = 1;                                       //火灾传感器使用蜂鸣器
            buzzerDeviceTmp->open(buzzerDeviceTmp->pinNum); //蜂鸣器报警
            memset(Message[2], 0, sizeof Message[2]);       //清空数组
            sprintf(Message[2], "警报:发生火灾!");       //更新火灾信息
            delay(200);                                     //蜂鸣器报警延时
        }
        else if ((beep != 2) && (beep != 3)) //未被震动传感器和人体红外传感器使用
        {
            buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum); //关闭蜂鸣器
            memset(Message[2], 0, sizeof Message[2]);        //清空数组
            sprintf(Message[2], "正常");                     //更新火灾信息
            beep = 0;                                        //蜂鸣器未被使用
        }
    }
}

void *vibrate_thread(void *datas) //震动线程
{
    char msg[100];
    int status;
    struct Devices *vibrateDeviceTmp = NULL;
    struct Devices *buzzerDeviceTmp = NULL;

    vibrateDeviceTmp = findDeviceByName("vibrate", pdeviceHead); //在设备工厂找到火灾模块
    buzzerDeviceTmp = findDeviceByName("buzzser", pdeviceHead);

    vibrateDeviceTmp->deviceInit(vibrateDeviceTmp->pinNum); //震动模块初始化
    buzzerDeviceTmp->deviceInit(buzzerDeviceTmp->pinNum);
    printf("震动线程初始化成功\n");
    while (1)
    {
        delay(5);
        status = vibrateDeviceTmp->readStatus(vibrateDeviceTmp->pinNum); //读取震动模块实时数据

        if (status == 0)
        {
            beep = 2; //震动传感器使用蜂鸣器
            buzzerDeviceTmp->open(buzzerDeviceTmp->pinNum);
            memset(Message[3], 0, sizeof Message[3]); //清空数组
            sprintf(Message[3], "警报:发生震动!");

            delay(300);
        }
        else if ((beep != 1) && (beep != 3)) //蜂鸣器未被火焰传感器和人体红外传感器使用
        {
            memset(Message[3], 0, sizeof Message[3]); //清空数组
            sprintf(Message[3], "正常");
            buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum);
            beep = 0; //蜂鸣器未被使用
        }
    }
}

void *infrared_thread(void *datas) // 人体红外检测线程
{
    char msg[100];
    int status;
    struct Devices *infraredDeviceTmp = NULL;
    struct Devices *buzzerDeviceTmp = NULL;

    infraredDeviceTmp = findDeviceByName("infrared", pdeviceHead); //在设备工厂找到火灾模块
    buzzerDeviceTmp = findDeviceByName("buzzser", pdeviceHead);

    infraredDeviceTmp->deviceInit(infraredDeviceTmp->pinNum); //红外模块初始化
    buzzerDeviceTmp->deviceInit(buzzerDeviceTmp->pinNum);
    printf("人体红外检测初始化\n");

    while (1)
    {
        delay(10);
        status = infraredDeviceTmp->readStatus(infraredDeviceTmp->pinNum); //读取人体感应模块实时数据

        if (status == 1)
        {
            beep = 3;                                 //人体红外使用蜂鸣器
            memset(Message[4], 0, sizeof Message[4]); //清空数组
            sprintf(Message[4], "警报:有人进入!");
            buzzerDeviceTmp->open(buzzerDeviceTmp->pinNum);
            delay(200);
            buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum);
            delay(100);
        }
        else if ((beep != 1) && (beep != 2)) //未被火焰传感器和震动传感器使用
        {
            memset(Message[4], 0, sizeof Message[4]); //清空数组
            sprintf(Message[4], "正常");
            buzzerDeviceTmp->close(buzzerDeviceTmp->pinNum);
            beep = 0; //蜂鸣器未被使用
        }
    }
}

void *monitoring_thread(void *datas) //视频监控线程
{
    system("./start_web_video.sh"); //执行脚本,打开视频监控
    pthread_exit(NULL);             //退出线程
}

void *voice_thread(void *arg) //语音线程
{
    int i = 0;
    int nread;
    struct InputCommander *voiceHandler = NULL;
    struct Devices *deviceTmp = NULL;

    voiceHandler = findCommandByName("voice", pCommandHead); //在控制工厂找到语音模块

    if (voiceHandler == NULL)
    {
        printf("查找语音处理程序错误\n");
        pthread_exit(NULL);
    }
    else
    {
        if (voiceHandler->Init(voiceHandler, NULL, NULL) < 0)
        { //语音模块初始化
            printf("语音初始化错误\n");
            pthread_exit(NULL); //退出线程
        }
        else
        {
            printf("%s 初始化成功\n", voiceHandler->commandName);
        } //语音初始化完成

        pthread_mutex_lock(&mutex); //加锁
                                    //语音读取一级指令的时候,为了避免其它线程对于 紧接着读取二级指令的干扰
        while (1)
        {
            memset(voiceHandler->comand, '\0', sizeof(voiceHandler->comand));

            nread = voiceHandler->getCommand(voiceHandler); //读取来自语音模块的串口数据
            printf("get voice command:%s\n", voiceHandler->comand);
            if (nread == 0)
            {
                printf("没有来自语音的数据,请再说一遍\n");
            }
            else if (strstr(voiceHandler->comand, "kwsd") != NULL) //打开卧室灯命令
            {
                printf("打开卧室灯光\n");
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead); //查找卧室灯设备
                deviceTmp->deviceInit(deviceTmp->pinNum);          //卧室灯设备初始化
                deviceTmp->open(deviceTmp->pinNum);                //打开卧室灯
            }
            else if (strstr(voiceHandler->comand, "gwsd") != NULL)
            {
                printf("关闭卧室灯光\n");
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "kysd") != NULL)
            {
                printf("打开浴室灯光\n");
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gysd") != NULL)
            {
                printf("关闭浴室灯光\n");
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "kktd") != NULL)
            {
                printf("打开客厅灯光\n");
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gktd") != NULL)
            {
                printf("关闭客厅灯光\n");
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "kctd") != NULL)
            {
                printf("打开餐厅灯光\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gctd") != NULL)
            {
                printf("关闭餐厅灯光\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "kycd") != NULL) //开泳灯指令
            {
                printf("打开泳池灯光\n");
                deviceTmp = findDeviceByName("yong", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gqbd") != NULL) //关闭全部灯指令
            {
                printf("关闭所有灯光\n");
                deviceTmp = findDeviceByName("chu", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum); //关闭餐厅灯
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum); //关闭浴室灯
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum); //关闭客厅灯
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum); //关闭卧室灯
            }
            else if (strstr(voiceHandler->comand, "kqbd") != NULL)
            {
                printf("打开所有灯光\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gycd") != NULL) //关泳池灯指令
            {
                printf("关闭泳池灯光\n");
                deviceTmp = findDeviceByName("yong", pdeviceHead); //搜索泳池灯设备
                deviceTmp->deviceInit(deviceTmp->pinNum);          //泳池灯设备初始化
                deviceTmp->close(deviceTmp->pinNum);               //关泳池灯
            }
            else if (strstr(voiceHandler->comand, "kdfs") != NULL) //开电风扇指令
            {
                printf("打开电风扇\n");
                deviceTmp = findDeviceByName("fan", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "gdfs") != NULL) //关电风扇指令
            {
                printf("关闭电风扇\n");
                deviceTmp = findDeviceByName("fan", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(voiceHandler->comand, "ks") != NULL) //开锁指令
            {
                printf("打开门锁\n");
                deviceTmp = findDeviceByName("lock", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                delay(3000);
                deviceTmp->close(deviceTmp->pinNum);
            }

        }

        pthread_mutex_unlock(&mutex); //解锁
    }
}

void *write_thread(void *datas) //通知线程,向客服端发送消息
{
    while (1)
    {
        delay(500);
        write(c_fd, Message, 500);
    }
}

void *read_thread(void *datas) //通过socket读取客户端发来的数据
{

    int n_read;
    struct Devices *deviceTmp = NULL;

    while (1)
    {
        memset(socketHandler->comand, '\0', sizeof(socketHandler->comand));

        n_read = read(c_fd, socketHandler->comand, sizeof(socketHandler->comand)); //读取客户端发来的数据
        if (n_read == -1)
        {
            perror("read_thread");
        }
        else if (n_read > 0)
        {
            printf("客户端指令:%s\n", socketHandler->comand);
            //处理客户端读到的命令
            if (strstr(socketHandler->comand, "kws") != NULL) //开卧室灯
            {
                printf("开卧室灯\n");
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead); //查找卧室灯设备
                deviceTmp->deviceInit(deviceTmp->pinNum);          //卧室灯设备初始化
                deviceTmp->open(deviceTmp->pinNum);                //打开卧室灯
            }
            else if (strstr(socketHandler->comand, "gws") != NULL) //关卧室灯
            {
                printf("关卧室灯\n");
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "kys") != NULL) //开浴室灯
            {
                printf("开浴室灯\n");
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gys") != NULL) //关浴室灯
            {
                printf("关浴室灯\n");
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "kkt") != NULL) //开客厅灯
            {
                printf("开客厅灯\n");
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gkt") != NULL) //关客厅灯
            {
                printf("关客厅灯\n");
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "kct") != NULL) //开餐厅灯
            {
                printf("开餐厅灯\n");
                deviceTmp = findDeviceByName("chu", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gct") != NULL) //关餐厅灯
            {
                printf("关餐厅灯\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }

            else if (strstr(socketHandler->comand, "kfs") != NULL) //开风扇
            {
                printf("开电风扇\n");
                deviceTmp = findDeviceByName("fan", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gfs") != NULL) //关风扇
            {
                printf("关电风扇\n");
                deviceTmp = findDeviceByName("fan", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "kqb") != NULL) //开室内全部灯
            {
                printf("开室内全部灯\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gqb") != NULL) //关室内全部灯
            {
                printf("关室内全部灯\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "ks") != NULL) //开锁
            {
                printf("开锁\n");
                deviceTmp = findDeviceByName("lock", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gs") != NULL) //关锁
            {
                deviceTmp = findDeviceByName("lock", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "kjk") != NULL) //开监控
            {
                printf("打开监控\n");
                pthread_create(&monitoringThread, NULL, monitoring_thread, NULL); //启动视频监控线程
            }
            else if (strstr(socketHandler->comand, "gjk") != NULL) //关监控
            {
                printf("关闭监控\n");
                // pthread_cancel(monitoringThread);
                system("killall -TERM mjpg_streamer"); //关闭摄像头监控功能
            }
            else if (strstr(socketHandler->comand, "khw") != NULL) //打开人体红外检测
            {
                printf("启动人体红外检测线程\n");
                beep = 3; //人体红外使用蜂鸣器
                deviceTmp = findDeviceByName("buzzser", pdeviceHead);
                deviceTmp->open(deviceTmp->pinNum);
                delay(700);
                deviceTmp->close(deviceTmp->pinNum);
                if (infrared_flag == 0)
                {
                    pthread_create(&infraredThread, NULL, infrared_thread, NULL);
                    infrared_flag = 1;
                }
            }
            else if (strstr(socketHandler->comand, "ghw") != NULL) //关闭人体红外检测
            {
                printf("关闭人体红外检测\n");
                memset(Message[4], 0, sizeof Message[4]); //清空数组
                sprintf(Message[4], "未启用!");

                if (infrared_flag == 1)
                {
                    pthread_cancel(infraredThread); //停止人体红外线程
                    infrared_flag = 0;
                }

                beep = 3; //人体红外使用蜂鸣器
                deviceTmp = findDeviceByName("buzzser", pdeviceHead);
                deviceTmp->open(deviceTmp->pinNum);
                delay(400);
                deviceTmp->close(deviceTmp->pinNum);
                delay(300);
                deviceTmp->open(deviceTmp->pinNum);
                delay(400);
                deviceTmp->close(deviceTmp->pinNum);
            }
            else if (strstr(socketHandler->comand, "gjms") != NULL) //归家模式
            {
                printf("开室内全部灯\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->open(deviceTmp->pinNum);

                printf("关闭人体红外检测\n");
                memset(Message[4], 0, sizeof Message[4]); //清空数组
                sprintf(Message[4], "未启用!");

                if (infrared_flag == 1)
                {
                    pthread_cancel(infraredThread); //停止人体红外线程
                    infrared_flag = 0;
                }

                beep = 3; //人体红外使用蜂鸣器
                deviceTmp = findDeviceByName("buzzser", pdeviceHead);
                deviceTmp->open(deviceTmp->pinNum);
                delay(400);
                deviceTmp->close(deviceTmp->pinNum);
                delay(300);
                deviceTmp->open(deviceTmp->pinNum);
                delay(400);
                deviceTmp->close(deviceTmp->pinNum);
                beep = 0;
            }
            else if (strstr(socketHandler->comand, "ljms") != NULL) //离家模式
            {
                printf("关全部灯\n");
                deviceTmp = findDeviceByName("restaurantLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("bathroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("upstairLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);
                deviceTmp = findDeviceByName("livingroomLight", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);

                printf("关电风扇\n");
                deviceTmp = findDeviceByName("fan", pdeviceHead);
                deviceTmp->deviceInit(deviceTmp->pinNum);
                deviceTmp->close(deviceTmp->pinNum);

                printf("启动人体红外检测线程\n");
                beep = 3; //人体红外使用蜂鸣器
                deviceTmp = findDeviceByName("buzzser", pdeviceHead);
                deviceTmp->open(deviceTmp->pinNum);
                delay(700);
                deviceTmp->close(deviceTmp->pinNum);
                beep = 0;
                if (infrared_flag == 0)
                {
                    pthread_create(&infraredThread, NULL, infrared_thread, NULL);
                    infrared_flag = 1;
                }
            }
            else if (strstr(socketHandler->comand, "face") != NULL)
            {
                //启动人脸识别线程
                printf("进行人脸识别开锁\n");
                pthread_create(&cameraThread, NULL, cameraThread_func, NULL);
            }
        }
        else
        {
            printf("客户端退出\n");
            pthread_cancel(writeThread); //停止通知线程
            write_flag = 0;              //通知线程标志位置0,通知线程关闭
            pthread_exit(NULL);          //退出本线程
        }
    }
}

void *socket_thread(void *datas) //开启socket服务端,并将socket服务端初始化
{

    int n_read = 0;
    pthread_t readPthread;

    struct sockaddr_in c_addr;
    memset(&c_addr, 0, sizeof(struct sockaddr_in));
    int clen = sizeof(struct sockaddr_in);

    socketHandler = findCommandByName("socketServer", pCommandHead); //在控制工厂找到socket
    if (socketHandler == NULL)
    {
        printf("查找套接字处理程序错误\n");
        pthread_exit(NULL);
    }
    else
    {
        printf("%s 初始化成功\n", socketHandler->commandName);
    }

    socketHandler->Init(socketHandler, NULL, NULL); //初始化socket

    while (1)
    {

        c_fd = accept(socketHandler->sfd, (struct sockaddr *)&c_addr, &clen);
        printf("c_fd = %d\n", c_fd);
        if (write_flag == 0) //通知线程处于关闭状态
        {
            write_flag = 1;
            pthread_create(&writeThread, NULL, write_thread, NULL); //打开通知线程
        }
        pthread_create(&readPthread, NULL, read_thread, NULL);
    }
}

//检测按键状态
void *key_thread()
{
    int val;
    while (1)
    {
        val = digitalRead(key);//获取key引脚状态给val
        if (val == 0) //防止重复检测
        {
            delay(500);
            val = digitalRead(key);
            if (val == 1) //按键按下,启动人脸识别线程
            {
                pthread_create(&cameraThread, NULL, cameraThread_func, NULL);
            }
        }
    }
}

int main()
{
    char name[32] = {'\0'};

    //树莓派库初始化
    if (wiringPiSetup() == -1)
    {
        printf("硬件接口初始化失败\n");
        return -1;
    }

    pthread_mutex_init(&mutex, NULL); //初始化互斥量(锁)

    // 1、指令工厂初始化
    pCommandHead = addVoiceContrlToInputCommanderLink(pCommandHead);  //语音识别初始化
    pCommandHead = addsocketContrlToInputCommanderLink(pCommandHead); //服务器初始化

    // 2、设备控制工程初始化
    pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);   //浴室灯光初始化
    pdeviceHead = addupStairLightToDeviceLink(pdeviceHead);    //卧室灯光初始化
    pdeviceHead = addlivingroomLightToDeviceLink(pdeviceHead); //客厅灯光初始化
    pdeviceHead = addrestaurantLightToDeviceLink(pdeviceHead); //餐厅灯光初始化
    pdeviceHead = addDoorLockToDeviceLink(pdeviceHead);        //门锁初始化
    pdeviceHead = addFanToDeviceLink(pdeviceHead);             //电风扇初始化
    pdeviceHead = addBuzzerToDeviceLink(pdeviceHead);          //蜂鸣器初始化
    pdeviceHead = addFireToDeviceLink(pdeviceHead);            //火焰传感器初始化
    pdeviceHead = addVibrateToDeviceLink(pdeviceHead);           //震动传感器初始化
    pdeviceHead = addcameraToDeviceLink(pdeviceHead);          //摄像头模块初始化
    pdeviceHead = addInfraredToDeviceLink(pdeviceHead);           //人体感应传感器初始化

    pthread_create(&voiceThread, NULL, voice_thread, NULL);   // 语音线程启动
    pthread_create(&socketThread, NULL, socket_thread, NULL); // socket服务器线程启动
    pthread_create(&fireThread, NULL, fire_thread, NULL);     //火灾报警线程启动
    pthread_create(&vibrateThread, NULL, vibrate_thread, NULL);   //震动报警线程启动
    pthread_create(&keyThread, NULL, key_thread, NULL);       //按键检测线程启动
    pthread_create(&dht11Thread, NULL, dht11_thread, NULL);   // 温湿度检测线程启动

    pthread_join(voiceThread, NULL);
    pthread_join(socketThread, NULL);
    pthread_join(fireThread, NULL);
    pthread_join(vibrateThread, NULL);
    pthread_join(infraredThread, NULL);
    pthread_join(keyThread, NULL);
    pthread_join(cameraThread, NULL);
    pthread_join(monitoringThread, NULL);
    pthread_join(clientWemosThread, NULL);
    pthread_join(dht11Thread, NULL);
    pthread_join(writeThread, NULL);

    pthread_mutex_destroy(&mutex); //销毁互斥量

    return 0;
}

bathroomLight.c(浴室灯)

#include "contrlDevices.h"

int bathroomLightOpen(int pinNum)
{
    digitalWrite(pinNum, HIGH);
}

int bathroomLightClose(int pinNum)
{
    digitalWrite(pinNum, LOW);
}

int bathroomLightCloseInit(int pinNum)
{
    pinMode(pinNum, OUTPUT);
    digitalWrite(pinNum, LOW);
  //  printf("浴室灯初始化成功\n");
}

int bathroomLightCloseStatus(int status)
{
}

struct Devices bathroomLight = {
    .deviceName = "bathroomLight",
    .pinNum = 24,
    .open = bathroomLightOpen,
    .close = bathroomLightClose,
    .deviceInit = bathroomLightCloseInit,
    .changStatus = bathroomLightCloseStatus};

struct Devices *addBathroomLightToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &bathroomLight;
    }
    else
    {
        bathroomLight.next = phead;
        phead = &bathroomLight;
    }
    return phead;
}

buzzer.c(蜂鸣器)

#include "contrlDevices.h"

int buzzerOpen(int pinNum)
{
    digitalWrite(pinNum, LOW);
}

int buzzerClose(int pinNum)
{
    digitalWrite(pinNum, HIGH);
}

int buzzerInit(int pinNum)
{
    pinMode(pinNum, OUTPUT);
    digitalWrite(pinNum, HIGH);
}

struct Devices buzzer = {
    .deviceName = "buzzser",
    .pinNum = 7,
    .open = buzzerOpen,
    .close = buzzerClose,
    .deviceInit = buzzerInit};

struct Devices *addBuzzerToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &buzzer;
    }
    else
    {
        buzzer.next = phead;
        phead = &buzzer;
    }
    return phead;
}

camera.c(监控)

#include "contrlDevices.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#define door_lock 29 //门锁
void postUrl();
size_t readData1(void *ptr, size_t size, size_t nmemb, void *stream);
char *getFace1();
char *getPicFromOCRBase641(char *Filepath);
struct Devices *addcameraToDeviceLink(struct Devices *phead);

char ocrRetBuf[1024] = {'\0'}; //全局变量,用来接收对比两张照片结果的数据

size_t readData1(void *ptr, size_t size, size_t nmemb, void *stream)
//回调函数,把从后台的数据拷贝给ocrRetBuf
{
    strncpy(ocrRetBuf, ptr, 1024);
}

char *getFace1()
{
    printf("拍照中...\n");
    system("raspistill -q 5 -t 1 -o image.jpg"); //-q 是图片质量,在0~100之间,我们调成5,压缩图片质量,生成的照片名字为imag.jpg
                                                 //-t 是拍照延时,设定1s后拍照

    while (access("./image.jpg", F_OK) != 0);    //判断是否拍照完毕

    printf("拍照完成\n");

    char *base64BufFaceRec = getPicFromOCRBase641("./image.jpg");
    // system("rm image.jpg");

    return base64BufFaceRec; //返回刚才拍照的base64
}

char *getPicFromOCRBase641(char *Filepath)
{
    int fd;
    int filelen;
    char cmd[128] = {'\0'};

    sprintf(cmd, "base64 %s > tmpFile", Filepath);//拼凑字符 执行base64+照片名 结果存放在tmpFile
    system(cmd);                                  //执行
    fd = open("./tmpFile", O_RDWR);               
    filelen = lseek(fd, 0, SEEK_END);             //计算指针偏移量 就是数据大小
    lseek(fd, 0, SEEK_SET);                       //移动光标
    char *bufpic = (char *)malloc(filelen + 2);
    memset(bufpic, '\0', filelen + 2);
    read(fd, bufpic, filelen + 128);              //读到bufpic中
    system("rm -rf tmpFile"); 
    close(fd);

    return bufpic;                                //返回读的内容
}

void postUrl()
{
    CURL *curl;
    CURLcode res;

    struct Devices *deviceTmp = NULL;

    //分开定义,然后字符串拼接
    char *key = "*******************";                  
    char *secret = "********************"; 
    int typeId = 21;
    char *format = "xml";
 
    char *base64BufPic1 = getFace1();                      //摄像头拍的  
    char *base64BufPic2 = getPicFromOCRBase641("nb.jpg");//房主照片

    int len = strlen(key) + strlen(secret) + strlen(base64BufPic1) + strlen(base64BufPic2) + 128; //分配空间不够会导致栈溢出
    char *postString = (char *)malloc(len);
    memset(postString, '\0', len); //因为postString是一个指针,不能用sizeof来计算其指向的大小

    sprintf(postString, "img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s", base64BufPic1, base64BufPic2, 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, readData1);                 //回调函数readDate读取返回值
        res = curl_easy_perform(curl);                                            //类似于状态码
        printf("OK:%d\n", res);

        if (strstr(ocrRetBuf, "是") != NULL)
        { //判断翔云后台返回的字符串中有没有“是”
            printf("是同一个人\n");
            digitalWrite(door_lock, LOW);  //打开门锁
            delay(3000);                   //等待3s
            digitalWrite(door_lock, HIGH); //关闭门锁
        }
        else
        {
            printf("不是同一个人\n");
        }
        curl_easy_cleanup(curl);
    }
}

struct Devices camera = {

    .deviceName = "camera",
    .justDoOnce = postUrl,
    .getFace = getFace1,
    .getPicFromOCRBase64 = getPicFromOCRBase641,
    .readData = readData1

};

struct Devices *addcameraToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &camera;
    }
    else
    {
        camera.next = phead;
        phead = &camera;
    }
}

doorLock.c(门锁)

#include "contrlDevices.h"

int doorLockOpen(int pinNum)
{
    //digitalWrite(pinNum, LOW);
	for(int i=0;i<20;i++)
	{	
		digitalWrite(pinNum,HIGH);
		delay(2);
		digitalWrite(pinNum,LOW);
		delay(18);
	}
	pinMode(pinNum,INPUT);
	pinMode(pinNum,OUTPUT);
}

int doorLockClose(int pinNum)
{
    digitalWrite(pinNum, HIGH);
}

int doorLockCloseInit(int pinNum)
{
    pinMode(pinNum, OUTPUT);
    digitalWrite(pinNum, HIGH);
}

int doorLockCloseStatus(int status)
{
}
//门锁
struct Devices doorLock = {
    .deviceName = "lock",
    .pinNum = 28,
    .open = doorLockOpen,
    .close = doorLockClose,
    .deviceInit = doorLockCloseInit,
    .changStatus = doorLockCloseStatus};

struct Devices *addDoorLockToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &doorLock;
    }
    else
    {
        doorLock.next = phead;
        phead = &doorLock;
    }
    return phead;
}

fan.c(风扇)

#include "contrlDevices.h"

int fanOpen(int pinNum)
{
    pinMode(pinNum, OUTPUT);
}

int fanClose(int pinNum)
{
    pinMode(pinNum, INPUT);
}

int fanCloseInit(int pinNum) //风扇有问题 设为输出就转 输入就停 高低电平影响不了
{
    pinMode(pinNum, INPUT);
    printf("电风扇初始化成功\n");
}

int fanCloseStatus(int status)
{
}

struct Devices fan = {
    .deviceName = "fan",
    .pinNum = 26,
    .open = fanOpen,
    .close = fanClose,
    .deviceInit = fanCloseInit,
    .changStatus = fanCloseStatus
};

struct Devices *addFanToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &fan;
    }
    else
    {
        fan.next = phead;
        phead = &fan;
    }
    return phead;
}

fire.c(火焰传感)

#include "contrlDevices.h"

int fireInit(int pinNum)
{
    pinMode(pinNum, INPUT);
    digitalWrite(pinNum, HIGH);
}

int readFireStatus(int pinNum)
{
    return digitalRead(pinNum);
}

struct Devices fire = {
    .deviceName = "fire",
    .pinNum = 25,
    .deviceInit = fireInit,
    .readStatus = readFireStatus
};

struct Devices *addFireToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &fire;
    }
    else
    {
        fire.next = phead;
        phead = &fire;
    }

    return phead;
}

infrared.c(人体红外)

#include "contrlDevices.h"

int infraredInit(int pinNum)
{
    pinMode(pinNum, INPUT);
    digitalWrite(pinNum, HIGH);
   // printf("人体感应传感器初始化成功\n");
}

int readinfraredStatus(int pinNum)
{
    return digitalRead(pinNum);
}

struct Devices infrared = {
    .deviceName = "infrared",
    .pinNum = 5,
    .deviceInit = infraredInit,
    .readStatus = readinfraredStatus};

struct Devices *addInfraredToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &infrared;
    }
    else
    {
        infrared.next = phead;
        phead = &infrared;
    }
    return phead;
}


livingroomLight.c(卧室灯)

#include "contrlDevices.h"

int livingroomLightOpen(int pinNum)
{
    digitalWrite(pinNum, HIGH);
}

int livingroomLightClose(int pinNum)
{
    digitalWrite(pinNum, LOW);
}

int livingroomLightCloseInit(int pinNum)
{
    pinMode(pinNum, OUTPUT);
    digitalWrite(pinNum, LOW);
}

int livingroomLightCloseStatus(int status)
{
}

struct Devices livingroomLight = {
    .deviceName = "livingroomLight",
    .pinNum = 21,
    .open = livingroomLightOpen,
    .close = livingroomLightClose,
    .deviceInit = livingroomLightCloseInit,
    .changStatus = livingroomLightCloseStatus};

struct Devices *addlivingroomLightToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &livingroomLight;
    }
    else
    {
        livingroomLight.next = phead;
        phead = &livingroomLight;
    }
    return phead;
}

restaurantLight.c(餐厅灯)

#include "contrlDevices.h"

int restaurantLightOpen(int pinNum)
{
    digitalWrite(pinNum, HIGH);
}

int restaurantLightClose(int pinNum)
{
    digitalWrite(pinNum, LOW);
}

int restaurantLightCloseInit(int pinNum)
{
    pinMode(pinNum, OUTPUT);
    digitalWrite(pinNum, LOW);
}

int restaurantLightCloseStatus(int status)
{
}

struct Devices restaurantLight = {
    .deviceName = "restaurantLight",
    .pinNum = 23,
    .open = restaurantLightOpen,
    .close = restaurantLightClose,
    .deviceInit = restaurantLightCloseInit,
    .changStatus = restaurantLightCloseStatus};

struct Devices *addrestaurantLightToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &restaurantLight;
    }
    else
    {
        restaurantLight.next = phead;
        phead = &restaurantLight;
    }
    return phead;
}


socketContrl.c(socket控制)

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <wiringSerial.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "inputCommand.h"

int socketgetCommand(struct InputCommander *socketMes)
{
    int c_fd;
    int n_read;

    struct sockaddr_in c_addr;
    memset(&c_addr, 0, sizeof(struct sockaddr_in));
    int clen = sizeof(struct sockaddr_in);

    // 4.accept
    c_fd = accept(socketMes->sfd, (struct sockaddr *)&c_addr, &clen);

    n_read = read(c_fd, socketMes->comand, sizeof(socketMes->comand));
    if (n_read == -1)
    {
        perror("读");
    }
    else if (n_read > 0)
    {
        printf("\n获取:%d\n", n_read);
    }
    else
    {
        printf("客户端退出\n");
    }


    return n_read;
}

int socketInit(struct InputCommander *socketMes, char *ipAdress, char *port)
{

    int s_fd;
    struct sockaddr_in s_addr;

    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    // 1.socket
    s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1)
    {
        perror("socket");
        exit(-1);
    }

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(socketMes->port));
    inet_aton(socketMes->ipAdress, &s_addr.sin_addr);

    //解决服务器程序结束后端口被占用的情况
    int opt = 1;
    setsockopt(s_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 2.bind
    bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));

    // 3.listen
    listen(s_fd, 10);
    printf("套接字服务器侦听......\n");
    socketMes->sfd = s_fd;

    return s_fd;
}

struct InputCommander socketContrl = {
    .commandName = "socketServer",
    .comand = {'\0'},
    .port = "8088",
    .ipAdress = "192.168.137.167",
    .Init = socketInit,
    .getCommand = socketgetCommand,
    .log = {'\0'},
    .next = NULL};

struct InputCommander *addsocketContrlToInputCommanderLink(struct InputCommander *phead)
{
    if (phead == NULL)
    {
        return &socketContrl;
    }
    else
    {
        socketContrl.next = phead;
        phead = &socketContrl;
    }

    return phead;
}


upstairLight.c(客厅灯)

#include <stdlib.h>
#include <fcntl.h>
#include "contrlDevices.h"

int upstairLightOpen(int pinNum) //打开客厅灯函数
{
    digitalWrite(pinNum, HIGH);
}

int upstairLightClose(int pinNum) //关闭客厅灯函数
{
    digitalWrite(pinNum, LOW);
}

int upstairLightCloseInit(int pinNum) //初始化函数
{
    pinMode(pinNum, OUTPUT);    //配置引脚为输出引脚
    digitalWrite(pinNum, LOW); //引脚输出高电平,即默认为关闭状态
}

int upstairLightCloseStatus(int status)
{
}

struct Devices upstairLight = { //客厅灯设备链表节点
    .deviceName = "upstairLight",
    .pinNum = 22,
    .open = upstairLightOpen,
    .close = upstairLightClose,
    .deviceInit = upstairLightCloseInit,
    .changStatus = upstairLightCloseStatus
};

struct Devices *addupStairLightToDeviceLink(struct Devices *phead) //头插法将设备节点加入设备工厂链表函数
{
    if (phead == NULL)
    {
        return &upstairLight;
    }
    else
    {
        upstairLight.next = phead;
        phead = &upstairLight;
    }
}

vibrate.c(震动传感器)

#include "contrlDevices.h"

int vibrateInit(int pinNum)
{
    pinMode(pinNum, INPUT);
    digitalWrite(pinNum, HIGH);
}

int readvibrateStatus(int pinNum)
{
    return digitalRead(pinNum);
}

struct Devices vibrate = {
    .deviceName = "vibrate",
    .pinNum = 1,
    .deviceInit = vibrateInit,
    .readStatus = readvibrateStatus};

struct Devices *addVibrateToDeviceLink(struct Devices *phead)
{
    if (phead == NULL)
    {
        return &vibrate;
    }
    else
    {
        vibrate.next = phead;
        phead = &vibrate;
    }
    return phead;
}


voiceContrl.c(语音模块)

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <string.h>

#include "inputCommand.h"

int getCommand(struct InputCommander *voicer) //获取语音指令
{
    int nread = 0;
    memset(voicer->comand, '\0', sizeof(voicer->comand));
    nread = read(voicer->fd, voicer->comand, sizeof(voicer->comand));//将语音模块返回的数据存放在缓冲区comand
    return nread;
}
//语音模块初始化
int voiceInit(struct InputCommander *voicer, char *ipAdress, char *port)
{
    int fd;
    if ((fd = serialOpen(voicer->deviceName, 9600)) == -1)
    {
        printf("语音初始化失败\n");
        exit(-1);
    }
    voicer->fd = fd;
    printf("语音初始化结束\n");
    return fd;
}
//语音模块结构体
struct InputCommander voiceContrl = {
    .commandName = "voice",
    .deviceName = "/dev/ttyAMA0",//此文件用于存放语音模块返回的数据
    .comand = {'\0'},
    .Init = voiceInit,
    .getCommand = getCommand,
    .log = {'\0'},
    .next = NULL
};
struct InputCommander *addVoiceContrlToInputCommanderLink(struct InputCommander *phead)
{
    if (phead == NULL)
    {
        return &voiceContrl;
    }
    else
    {
        voiceContrl.next = phead;
        phead = &voiceContrl;
    }
    return phead;
}


2.2全志代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>
int main(int argc, char **argv)
{
	int c_fd;
	int n_read;
	int a = 0;
	char msg[24] = {};
	char readBuf[128];
	struct sockaddr_in c_addr;

	memset(&c_addr,0,sizeof(struct sockaddr_in));

	c_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family = AF_INET;
	c_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&c_addr.sin_addr);

	if(connect(c_fd, (struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
		perror("connect");
		exit(-1);
	}
	while(1)
	{
		if(fork() == 0)
		{
			memset(msg,0,sizeof(msg));

			scanf("%s",msg);

			write(c_fd,msg,strlen(msg));
		}
		n_read = read(c_fd, readBuf, 128);
		if(n_read == -1){
			perror("read");
		}else{
			printf("服务端消息%d,%s\n",n_read,readBuf);
		}
		delay(4000);
	}
	return 0;
}

3、编译运行效果

树莓派端编译

gcc camera.c doorLock.c vibrate.c livingroomLight.c upstairLight.c bathroomLight.c fan.c lock.c restaurantLight.c socketContrl.c voiceContrl.c buzzer.c fire.c mainPro.c infrared.c -lwiringPi -lpthread -lcurl

全志端编译:

gcc client.c -lwiringPi

./a.out 192.168.137.167 8088

运行效果:

 

  • 7
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值