概述
- 为编程方便,使用WiringPi库函数对gpio引脚控制,通过语音模块和socket来接收命令,每一个设备放在一个单独的文件里,通过头文件提供的api供主函数调用,语音和socket同理。把若干设备和指令分别用链表连接起来,方便查找。
- 设备链表:pdevHead > light1 > light2 > light3 > light4 > fire > beep > dh11 > NULL
- 指令链表:pcmdHead > voice > socket > NULL
设备文件
#ifndef DEVICES_H
#define DEVICES_H
#include <stdio.h>
#include <string.h>
#include <wiringPi.h>
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
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;
}
}
#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;
}
}
#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));
while(!digitalRead(pin));
delayMicroseconds(50);
(*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);
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;
}
}
指令文件
#ifndef COMMAND_H
#define COMMAND_H
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wiringPi.h>
#include <wiringSerial.h>
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
#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;
}
}
#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 <pthread.h>
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);
pthread_join(th_dh11, NULL);
}
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
加入的模块并不算多,但是使用这个模板最大的好处就是添加或者删除模块只需要加文件,操作一下链表就行,如果模块用到的引脚比较多,在结构体里多加几个引脚和函数或者连单片机操作都可以,代码框架基本不用动。??
|