基于树莓派的智能家居程序设计

智能家居

  • 概述
  • 设备文件
  • 指令文件
  • 主函数


概述

  • 为编程方便,使用WiringPi库函数对gpio引脚控制,通过语音模块和socket来接收命令,每一个设备放在一个单独的文件里,通过头文件提供的api供主函数调用,语音和socket同理。把若干设备和指令分别用链表连接起来,方便查找。
  • 设备链表:pdevHead > light1 > light2 > light3 > light4 > fire > beep > dh11 > NULL
  • 指令链表:pcmdHead > voice > socket > NULL

设备文件

  • devices.h:
#ifndef DEVICES_H
#define DEVICES_H

#include 
#include 
#include 

struct Devices
{
    char name[128];
    int status;
    int pin;
    unsigned long data;
    int (*open)(int pin);
    int (*close)(int pin);
    int (*read)(int pin);
    unsigned char (*readData)(int pin,unsigned long *data);
    int (*devInit)(int pin);
    int (*changStatus)();
    struct Devices *next;
};

struct Devices *light1ToDevlink(struct Devices *phead);
struct Devices *light2ToDevlink(struct Devices *phead);
struct Devices *light3ToDevlink(struct Devices *phead);
struct Devices *light4ToDevlink(struct Devices *phead);
struct Devices *fireToDevlink(struct Devices *phead);
struct Devices *beepToDevlink(struct Devices *phead);
struct Devices *dh11ToDevlink(struct Devices *phead);

#endif // !DEVICES_H

light1.c

#include "devices.h"

int light1Open(int pin)
{
    digitalWrite(pin,LOW);
}

int light1Close(int pin)
{
    digitalWrite(pin,HIGH);
}

int light1Init(int pin)
{
    pinMode(pin,OUTPUT); 
    digitalWrite(pin,HIGH);
}

int light1changStatus()
{
}

struct Devices light1 = {
    .name = "light1",
    .pin = 22,
    .open = light1Open,
    .close = light1Close,
    .devInit = light1Init,
    .changStatus = light1changStatus,
    .next = NULL
};

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

  • fire.c:
#include "devices.h"

int fireRead(int pin)
{
    return digitalread(pin);
}

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

struct Devices fire = {
    .name = "fire",
    .pin = 21,
    .read = fireRead,
    .devInit = fireInit,
    .next = NULL};

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


  • DH11.c:
#include "devices.h"

unsigned char dh11Read(int pin,unsigned long *data)
{
	unsigned char crc, i;
	
	if (digitalRead(pin) == 0)			//主机接收到从机发送的响应信号(低电平)
	{
		while(!digitalRead(pin));		//主机接收到从机发送的响应信号(高电平)
		
		for (i = 0; i < 32; i++){
			while(digitalRead(pin));	//数据位开始的54us低电平
			while(!digitalRead(pin));	//数据位开始的高电平就开始
			
			delayMicroseconds(50);			//等50us,此时电平高为1,低为0
			
			(*data) *= 2;   //进位
			
			if (digitalRead(pin) == 1)
			{
				(*data)++;
			}
		}
		
		for (i = 0; i < 8; i++){
            while (digitalRead(pin));
            while (!digitalRead(pin));			
            delayMicroseconds(50);			
            crc *= 2;  
            if (digitalRead(pin) == 1)
            {
                crc++;
            }
        }
        
		return crc;
		
	}else{
		return 0;
	}
}


int dh11Init(int pin)
{
    pinMode(pin, OUTPUT); //起始拉高电平
	digitalWrite(pin, 1); 
	delay(1000);			
	
	pinMode(pin, OUTPUT);  //拉低超过18ms
	digitalWrite(pin, 0);
	delay(21);
	
	digitalWrite(pin, 1); //拉高电平,等响应
	pinMode(pin,INPUT);
	delayMicroseconds(28);
}

struct Devices dh11 = {
    .name = "dh11",
    .data = 0,
    .pin = 1,
    .readData = dh11Read,
    .devInit = dh11Init,
    .next = NULL};

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

  • 其余文件代码结构类似

指令文件

  • command.h:
#ifndef COMMAND_H
#define COMMAND_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct InputCommand
{
    char cmdName[128];
    char cmd[32];
    char devName[128];
    int fd;
    int s_fd;
    int c_fd;
    char ipAdress[32];
    char port[16];
    int (*init)(char *name, char *ipAdress, char *port);
    int (*getCmd)(struct InputCommand *cmd);
    char log[1024];
    struct InputCommand *next;
};

struct InputCommand *voiceToCmdlink(struct InputCommand *phead);
struct InputCommand *socketToCmdlink(struct InputCommand *phead);

#endif

  • voice.c:
#include "command.h"

int voiceInit(char *name, char *ipAdress, char *port)
{
    int fd = serialOpen(name, 9600);
    if (fd == -1)
    {
        printf("serial down\n");
        exit(-1);
    }
    return fd;
}

int voiceGetcmd(struct InputCommand *voice)
{
    memset(voice->cmd, 0, strlen(voice->cmd));
    return read(voice->fd, voice->cmd, sizeof(voice->cmd));
}

struct InputCommand voice =
    {
        .cmdName = "voice",
        .cmd = {'\0'},
        .devName = "/dev/ttyAMA0",
        .fd = -1,
        .init = voiceInit,
        .getCmd = voiceGetcmd,
        .log = {'\0'},
        .next = NULL};

struct InputCommand *voiceToCmdlink(struct InputCommand *phead)
{
    if (phead == NULL)
    {
        return &voice;
    }
    else
    {
        voice.next = phead;
        return &voice;
    }
}
  • socket.c:
#include "command.h"

int socketInit(char *name, char *ip, char *port)
{
    int s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1)
    {
        perror("socket error");
        exit(-1);
    }

    struct sockaddr_in s_addr;
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(port));
    inet_aton("ip", &s_addr.sin_addr);
    bind(s_fd, (struct sockaddr *)&s_addr, sizeof(s_addr));

    listen(s_fd, 10);
    return s_fd;
}

int socketGetcmd(struct InputCommand *socket)
{
    memset(socket->cmd, 0, strlen(socket->cmd));
    return read(socket->c_fd, socket->cmd, sizeof(socket->cmd));
}

struct InputCommand Socket =
    {
        .cmdName = "socket",
        .cmd = {'\0'},
        .ipAdress = "192.168.8.103",
        .port = "6666",
        .s_fd = -1,
        .c_fd = -1,
        .init = socketInit,
        .getCmd = socketGetcmd,
        .log = {'\0'},
        .next = NULL};

struct InputCommand *socketToCmdlink(struct InputCommand *phead)
{
    if (phead == NULL)
    {
        return &Socket;
    }
    else
    {
        Socket.next = phead;
        return &Socket;
    }
}

主函数

  • 把上面的设备和指令组织成链表,开启fire线程一直监测火焰;voice线程等待语音命令;socket线程一直等待客户端接入,接入后开启线程读命令或发送数据。
#include "command.h"
#include "devices.h"
#include 

struct Devices *pdevHead = NULL;
struct InputCommand *pcmdHead = NULL;
int fireFlag = 0;

void init()
{
    if (wiringPiSetup() == -1)
    {
        printf("wiring no work\n");
        exit(-1);
    }

    pcmdHead = voiceToCmdlink(pcmdHead);
    pcmdHead = socketToCmdlink(pcmdHead);

    pdevHead = light1ToDevlink(pdevHead);
    pdevHead = light2ToDevlink(pdevHead);
    pdevHead = light3ToDevlink(pdevHead);
    pdevHead = light4ToDevlink(pdevHead);
    pdevHead = fireToDevlink(pdevHead);
    pdevHead = beepToDevlink(pdevHead);
    pdevHead = dh11ToDevlink(pdevHead);

    struct Devices *p = pdevHead;
    while (p)
    {
        p->devInit(p->pin);
        p = p->next;
    }
}

struct Devices *findDev(char *name)
{
    struct Devices *p = pdevHead;
    if (p == NULL)
    {
        return NULL;
    }

    while (p)
    {
        if (!strcmp(p->name, name))
        {
            p->devInit(p->pin);
            return p;
        }
        p = p->next;
    }
    return NULL;
}

struct InputCommand *findCmd(char *name)
{
    struct InputCommand *p = pcmdHead;
    if (p == NULL)
    {
        return NULL;
    }

    while (p)
    {
        if (!strcmp(p->cmdName, name))
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

void dev(char *cmd)
{
    struct Devices *p;
    if (strstr(cmd, "LA1"))
    {
        p = findDev("light1");
        p->open(p->pin);
    }
    else if (strstr(cmd, "LA0"))
    {
        p = findDev("light1");
        p->close(p->pin);
    }
    else if (strstr(cmd, "LB1"))
    {
        p = findDev("light2");
        p->open(p->pin);
    }
    else if (strstr(cmd, "LB0"))
    {
        p = findDev("light2");
        p->close(p->pin);
    }
    else if (strstr(cmd, "LC1"))
    {
        p = findDev("light3");
        p->devInit(p->pin);
        p->open(p->pin);
    }
    else if (strstr(cmd, "LC0"))
    {
        p = findDev("light3");
        p->close(p->pin);
    }
    else if (strstr(cmd, "LD1"))
    {
        p = findDev("light4");
        p->open(p->pin);
    }
    else if (strstr(cmd, "LD0"))
    {
        p = findDev("light4");
        p->close(p->pin);
    }
    else if (strstr(cmd, "L1"))
    {
        p = findDev("light1");
        p->open(p->pin);
        p = findDev("light2");
        p->open(p->pin);
        p = findDev("light3");
        p->open(p->pin);
        p = findDev("light4");
        p->open(p->pin);
    }
    else if (strstr(cmd, "L0"))
    {
        p = findDev("light1");
        p->close(p->pin);
        p = findDev("light2");
        p->close(p->pin);
        p = findDev("light3");
        p->close(p->pin);
        p = findDev("light4");
        p->close(p->pin);
    }
    else if (strstr(cmd, "BEEP1"))
    {
        p = findDev("beep");
        p->open(p->pin);
    }
    else if (strstr(cmd, "BEEP0"))
    {
        p = findDev("beep");
        p->close(p->pin);
    }
}

void *start_voice()
{
    int n_read;
    struct InputCommand *pvoice = findCmd("voice");
    if (pvoice == NULL)
    {
        printf("no found voice!\n");
        pthread_exit(NULL);
    }

    pvoice->fd = pvoice->init(pvoice->devName, NULL, NULL);

    while (1)
    {
        n_read = pvoice->getCmd(pvoice);
        if (n_read == 0)
        {
            printf("say cmd...\n");
        }
        else if (n_read > 0)
        {
            printf("cmd:%s\n", pvoice->cmd);
            dev(pvoice->cmd);
        }
        else if (n_read == -1)
        {
            perror("read error");
            exit(-1);
        }
    }
}

void *start_dh11(void *psocket)
{
    struct Devices *p = NULL;
    p = findDev("dh11");
    p->devInit(p->pin);
    if (p->readData(p->pin, &(p->data)))
    {
        if (fireFlag)
        {
            p->data = 0;
            fireFlag = 0;
        }
        printf("RH:%d.%d%\n", (p->data >> 24) & 0xff, (p->data >> 16) & 0xff);
        printf("TMP:%d.%dC\n", (p->data >> 8) & 0xff, p->data & 0xff);
        write(((struct InputCommand *)psocket)->c_fd, (void *)&(p->data), sizeof(p->data));
    }
    else
    {
        printf("Sensor dosent ans!\n");
        p->data = 0;
    }
    pthread_exit(NULL);
}

void *start_socket_read(void *psocket)
{
    int n_read;
    pthread_t th_dh11;
    while (1)
    {
        n_read = ((struct InputCommand *)psocket)->getCmd((struct InputCommand *)psocket);
        if (n_read == -1)
        {
            perror("read error");
            exit(-1);
        }
        else if (n_read > 0)
        {
            if (strstr(((struct InputCommand *)psocket)->cmd, "data"))
            {
                pthread_create(&th_dh11, NULL, start_dh11, (void *)psocket);
            }
            else
            {
                printf("get cmd:%s\n", ((struct InputCommand *)psocket)->cmd);
                dev(((struct InputCommand *)psocket)->cmd);
            }
        }
    }
}

void *start_socket()
{
    int n_read;
    pthread_t th_socket_read;
    struct InputCommand *psocket = findCmd("socket");
    if (psocket == NULL)
    {
        printf("no found socketserver!\n");
        pthread_exit(NULL);
    }

    psocket->s_fd = psocket->init(NULL, psocket->ipAdress, psocket->port);

    struct sockaddr_in c_addr;
    int c_size = sizeof(c_addr);

    while (1)
    {
        psocket->c_fd = accept(psocket->s_fd, (struct sockaddr *)&c_addr, &c_size);
        if (psocket->c_fd == -1)
        {
            perror("accept error");
            exit(-1);
        }
        printf("get connect:%s\n", inet_ntoa(c_addr.sin_addr));
        pthread_create(&th_socket_read, NULL, start_socket_read, (void *)psocket);
    }
}

void *start_fire()
{
    struct Devices *p = NULL;
    int i = 3;
    int ret = 0;
    while (1)
    {
        p = findDev("fire");
        p->devInit(p->pin);
        ret = p->read(p->pin);
        if (ret == 0)
        {
            printf("fire!\n");
            fireFlag = 1;
            p = findDev("beep");
            while (i--)
            {
                p->open(p->pin);
                delay(500);
                p->close(p->pin);
                delay(500);
            }
            ret = 1;
            p->close(p->pin);
        }
    }
}

int main()
{
    init();

    pthread_t th_voice;
    pthread_t th_socket;
    pthread_t th_fire;

    pthread_create(&th_voice, NULL, start_voice, NULL);
    pthread_create(&th_socket, NULL, start_socket, NULL);
    pthread_create(&th_fire, NULL, start_fire, NULL);

    pthread_join(th_voice, NULL);
    pthread_join(th_socket, NULL);
    pthread_join(th_fire, NULL);

    return 0;
}

  • 可以用APP连接socket

加入的模块并不算多,但是使用这个模板最大的好处就是添加或者删除模块只需要加文件,操作一下链表就行,如果模块用到的引脚比较多,在结构体里多加几个引脚和函数或者连单片机操作都可以,代码框架基本不用动。❤️

你可能感兴趣的:(树莓派,物联网,c语言,arm,嵌入式,socket)