超声波测距模块,sg90,蜂鸣器,全志H616,SU-03语音模块。
简单工厂模式:分模块思想编程,使代码更易于维护;
设备工厂:控制sg90舵机,超声波测距模块和蜂鸣器;
指令工厂:控制语音和Socket客户端收发指令;
记录工厂:控制文件和数据库的读写。
contrlDevices.h
#include
#include
struct Devices
{
char deviceName[128];
int status;
int pinNum;
char date[32];
int csbOpen;
int csbClose;
int socketOpen;
int socketClose;
int voiceOpen;
int voiceClose;
int (*open)(int pinNum);
int (*close)(int pinNum);
int (*deviceInit)(int pinNum);
int (*readStatus)(int pinNum);
int (*changeStatus)(int pinNum);
struct Devices *next;
struct timeval start;
struct timeval stop;
};
struct Devices * addBeepToDeviceLink(struct Devices *phead);
struct Devices * addCsbToDeviceLink(struct Devices *phead);
struct Devices * addDusbinToDeviceLink(struct Devices *phead);
InputCommand.h
#include
#include
#include
#include
#include
struct InputCommander
{
char commandName[128];//socketServer和voice
char deviceName[128];//打开的设备名称
char command[32];//获取指令
char log[1024];
int baud;//波特率
int fd;
int s_fd;
int c_fd;
char port[12];//端口号
char ipAddress[32];//ip地址
int (*Init)(struct InputCommander *pInputCommand);
int (*getCommand)(struct InputCommander *pInputCommand);
int (*sendStatus)(int fd,char *str);
struct InputCommander *next;
};
struct InputCommander * addSocketContrlToInputCommand(struct InputCommander * phead);
struct InputCommander * addVoiceContrlToInputCommand(struct InputCommander * phead);
record.h
#include
#include
#include
#include
#include
#include
#include
#include
struct Records{
char recordName[32];//fileRecords dataBaseRecords
char recordPathName[32];//文件名或数据库名
sqlite3 *db;
int fd;
int (*Init)(struct Records *pRecord);
int (*writeRecords)(struct Records *pRecord);
struct Records *next;
};
struct Records *addFileToRecordsLink(struct Records *phead);
struct Records * addDataBaseToRecordsLink(struct Records *phead);
csb.c
#include "contrlDevices.h"
#include
#include
#include
#define Trig 5
int csbInit(int pinNum)
{
pinMode(Trig,OUTPUT);
pinMode(pinNum,INPUT);
}
int getDistance(int pinNum)
{
//测量距离:2-400cm;
struct timeval tv1; //timeval是time.h中的预定义结构体 其中包含两个一个是秒,一个是微秒
struct timeval tv2;
long start, stop;
float dis;
digitalWrite(Trig, LOW);
delayMicroseconds(2);
digitalWrite(Trig, HIGH);
delayMicroseconds(10); //发出超声波脉冲
digitalWrite(Trig, LOW);
while(digitalRead(pinNum) != 1);
gettimeofday(&tv1, NULL); //获取当前时间 开始接收到返回信号的时候
while(digitalRead(pinNum) != 0);
gettimeofday(&tv2, NULL); //获取当前时间 最后接收到返回信号的时候
start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间
stop = tv2.tv_sec * 1000000 + tv2.tv_usec;
dis = (float)(stop - start) / 1000000 * 34000 / 2; //计算时间差求出距离
if(dis>30){
return 1;
}else{
return 0;
}
}
struct Devices csb=
{
.deviceName="csb",
.pinNum=7,
.status=1,
.deviceInit=csbInit,
.readStatus=getDistance//大于10cm,返回1,小于10cm 返回0;
};
struct Devices * addCsbToDeviceLink(struct Devices *phead)
{
if(phead == NULL){
return &csb;
}else{
csb.next=phead;
return &csb;
}
}
beep.c
#include "contrlDevices.h"
#include
int beepOpen(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int beepClose(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int beepInit(int pinNum)
{
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,LOW);//高电平触发;
}
struct Devices beep=
{
.deviceName="beep",
.pinNum=8,
.open = beepOpen,
.close =beepClose,
.deviceInit=beepInit,
};
struct Devices * addBeepToDeviceLink(struct Devices *phead)
{
if(phead == NULL){
return &beep;
}else{
beep.next=phead;
return &beep;
}
}
dusbin.c
#include "contrlDevices.h"
#include "InputCommand.h"
#include "record.h"
#include
#include
#include
#include
#include
#include
#include
#define SG90Pin 2
char message[200];
extern struct Devices *beepHandler;
extern struct Devices *dusbinHandler;
extern struct InputCommander *socketHandler;
extern struct InputCommander *voiceHandler;
extern struct Devices *csbHandler;
extern struct Records *fileHandler;
struct Records * sqliteHandler;
static int i = 0;
extern int jd_bak;
extern int jd;
void recordCount()
{
time_t now;
struct tm* tm_now;
char datemessage[12]={'\0'};
time(&now);
tm_now = localtime(&now);
strftime(datemessage,12,"%Y/%m/%d",tm_now);//获取当前时间
if(strcmp(dusbinHandler->date,datemessage)){
memset(dusbinHandler->date,'\0',32);
strcpy(dusbinHandler->date,datemessage);
dusbinHandler->csbOpen=0;
dusbinHandler->csbClose=0;
dusbinHandler->voiceOpen=0;
dusbinHandler->voiceClose=0;
dusbinHandler->socketOpen=0;
dusbinHandler->socketClose=0;
}
if(! csbHandler->status){
dusbinHandler->csbOpen++;
}else if(!strcmp(voiceHandler->command,"open")){
dusbinHandler->voiceOpen++;
}else if(!strcmp(socketHandler->command,"open")){
dusbinHandler->socketOpen++;
}else if(!strcmp(voiceHandler->command,"close")&& csbHandler->status ){
dusbinHandler->voiceClose++;
}else if (!strcmp(socketHandler->command,"close")&& csbHandler->status ){
dusbinHandler->socketClose++;
}else if(csbHandler->status && strcmp(voiceHandler->command,"open") && strcmp(socketHandler->command,"open" )&& strcmp(voiceHandler->command,"close")&&strcmp(socketHandler->command,"close")){
dusbinHandler->csbClose++;
}
memset(voiceHandler->command,'\0',32);
memset(socketHandler->command,'\0',32);
}
int dusbinOpen(int pinNum)
{
jd =3;
gettimeofday(&(beepHandler->stop),NULL);
if(jd_bak!=jd){
recordCount();//记录开关盖次数
fileHandler->writeRecords(fileHandler); //写入文件;
sqliteHandler->writeRecords(sqliteHandler);//写入数据库;
beepHandler->open(beepHandler->pinNum);
usleep(150000);
beepHandler->close(beepHandler->pinNum);
sleep(2);
}
jd_bak=jd;
}
int dusbinClose(int pinNum)
{
jd = 1;
if(jd_bak!=jd){
recordCount();
fileHandler->writeRecords(fileHandler);
sqliteHandler->writeRecords(sqliteHandler);
usleep(150000);
}
jd_bak=jd;
gettimeofday(&(beepHandler->start),NULL);
}
void signal_handler(int signum)
{
if(i <= jd){
digitalWrite(SG90Pin, HIGH);
}else{
digitalWrite(SG90Pin, LOW);
}
if(i == 40){//20ms
i = 0;
}
i++;
}
int dusbinInit(int pinNum)
{
struct itimerval itv;
jd = 1;
jd_bak=1;
i=0;
pinMode(pinNum,OUTPUT);
digitalWrite(pinNum,LOW);
//设定定时时间:500微秒,
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500;
//设定开始生效,启动定时器的时间
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
//设定定时方式
if( -1 == setitimer(ITIMER_REAL, &itv, NULL)){
printf("setitimer error\n");
exit(-1);
}
//信号处理
signal(SIGALRM,signal_handler);
}
struct Devices dusbin=
{
.deviceName="dusbin",
.pinNum=2,
.deviceInit=dusbinInit,
.open=dusbinOpen,
.close=dusbinClose,
.date={'\0'},
.csbOpen=0,
.csbClose=0,
.socketOpen=0,
.socketClose=0,
.voiceOpen=0,
.voiceClose=0,
};
struct Devices * addDusbinToDeviceLink(struct Devices *phead)
{
if(phead == NULL){
return &dusbin;
}else{
dusbin.next=phead;
return &dusbin;
}
}
file.c
#include "record.h"
#include
#include
#include
#include "contrlDevices.h"
extern struct Devices *dusbinHandler;
int fileInit(struct Records *pRecord)
{
int fd;
if((fd=open(pRecord->recordPathName,O_RDWR|O_CREAT,0600))==-1){
perror("file open error");
exit(-1);
}
close(fd);
pRecord->fd=fd;
return fd;
}
int writeToFile(struct Records *pRecord)
{
int nwrite;
char *readBuf;
char message[100]={'\0'};
char info[200]={'\0'};
int j;
sprintf(message,"date=%s;",dusbinHandler->date);
sprintf(info,"date=%s;csbOpen=%d;csbClose=%d;voiceOpen=%d;voiceClose=%d;socketOpen=%d;socketClose=%d;\r\n",dusbinHandler->date,dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose);
pRecord->fd = open(pRecord->recordPathName,O_RDWR,0600);
int fileSize=lseek(pRecord->fd,0,SEEK_END);
readBuf= (char *)malloc(sizeof(char )*(fileSize+strlen(info)+12));
lseek(pRecord->fd,0,SEEK_SET);
memset(readBuf,'\0',sizeof(readBuf));
read(pRecord->fd,readBuf,fileSize);
lseek(pRecord->fd,0,SEEK_SET);
char *p = strstr(readBuf,message);
if(p==NULL&& strlen(dusbinHandler->date)!=0){
strncat(readBuf,info,strlen(info));//在尾部追加;
}else{
for(j=0;jfd,readBuf,strlen(readBuf));
printf("write file success:%s\n",readBuf);
close(pRecord->fd);
return nwrite;
}
struct Records file={
.recordName="fileRecords",
.recordPathName="file1",
.Init=fileInit,
.writeRecords=writeToFile,
};
struct Records *addFileToRecordsLink(struct Records *phead)
{
if(phead == NULL){
return &file;
}else{
file.next=phead;
return &file;
}
}
lite.c
#include "record.h"
#include "contrlDevices.h"
#include
#include
#include
extern struct Devices *dusbinHandler;
int callback1(void *arg, int column_size, char *column_value[], char
*column_name[])
{
int i;
printf("records of dusbin.db:\n");
for(i=0;idate,dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose);
rc=sqlite3_exec(arg, sql, NULL, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "insert error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "insert successfully\n");
}
}
memset(sql,'\0',strlen(sql));
sprintf(sql,"select * from dusbin where date = '%s';",dusbinHandler->date);
rc=sqlite3_exec(arg, sql,callback1, arg, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, " select successfully\n");
}
sqlite3_close(arg);
return 0;
}
int writeToDB(struct Records *pRecord)
{
int rc;
char *zErrMsg = NULL;
char sql[256]={'\0'};
sprintf(sql,"update dusbin set csbOpen = %d, csbClose=%d ,voiceOpen=%d,voiceClose=%d,socketOpen=%d,socketClose=%d where date ='%s' ;select count(*) from dusbin where date='%s';",dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose ,dusbinHandler->date,dusbinHandler->date);
rc = sqlite3_open(pRecord->recordPathName, &(pRecord->db));
if( rc!=SQLITE_OK ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(pRecord->db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
rc=sqlite3_exec(pRecord->db, sql, callback, pRecord->db, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "update database error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "update successfully\n");
}
sqlite3_close(pRecord->db);
}
int DBInit(struct Records *pRecord)
{
int rc;
char *zErrMsg = NULL;
char *sql = "create table dusbin(date char,csbOpen interger, csbClose interger ,voiceOpen interger ,voiceClose interger, socketOpen interger, socketClose interger );";
rc = sqlite3_open(pRecord->recordPathName, &(pRecord->db));
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(pRecord->db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
rc = sqlite3_exec(pRecord->db, sql, NULL, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "table existed: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "created Table successfully\n");
}
sqlite3_close(pRecord->db);
return 0;
}
struct Records dbOfRecords={
.recordName="dataBaseRecords",
.recordPathName="dusbin.db",
.Init=DBInit,
.writeRecords=writeToDB,
};
struct Records * addDataBaseToRecordsLink(struct Records *phead)
{
if(phead == NULL){
return &dbOfRecords;
}else{
dbOfRecords.next=phead;
return &dbOfRecords;
}
}
mainPro.c
#include
#include
#include
#include
#include
#include
#include
#include
#include "contrlDevices.h"
#include "InputCommand.h"
#include
#include
#include "record.h"
struct Devices *pdeviceHead = NULL;
struct InputCommander *pCommandHead=NULL;
struct Records *pRecordsHead=NULL;
struct InputCommander *socketHandler;
struct InputCommander *voiceHandler;
struct Devices *dusbinHandler;
struct Devices *beepHandler;
struct Devices *csbHandler;
struct Records *fileHandler;
struct Records * sqliteHandler;
long diffTime;
int jd_bak=0;
int jd=0;
struct Devices * findDevicesByName(char *str,struct Devices * phead)
{
struct Devices *tmp = phead;
if(tmp == NULL){
printf("find devices error\n");
return NULL;
}else{
while(tmp!=NULL){
if(!strcmp(tmp->deviceName,str)){
return tmp;
}
tmp=tmp->next;
}
}
}
struct InputCommander * findInputCommanderByName(char *str,struct InputCommander * phead)
{
struct InputCommander *tmp = phead;
if(tmp == NULL){
printf("find InputCommander error\n");
return NULL;
}else{
while(tmp!=NULL){
if(!strcmp(tmp->commandName,str)){
return tmp;
}
tmp=tmp->next;
}
}
}
struct Records * findRecordsByName(char *str,struct Records * phead)
{
struct Records *tmp = phead;
if(tmp == NULL){
printf("find records error\n");
return NULL;
}else{
while(tmp!=NULL){
if(!strcmp(tmp->recordName,str)){
return tmp;
}
tmp=tmp->next;
}
}
}
void *read_thread(void *datas)
{
int n_read;
char buffer[32]={'\0'};
while(1){
memset(buffer,'\0',sizeof(buffer));
n_read = read(socketHandler->c_fd,buffer, sizeof(buffer));
if(n_read == -1){
perror("read");
}else if(n_read>0){
memset(socketHandler->command,'\0',sizeof(socketHandler->command));
strcpy(socketHandler->command,buffer);
printf("socket get cmd:%s\n",socketHandler->command);
}else{
printf("client quit\n");
break;
}
}
}
void *socket_thread(void *datas)
{
pthread_t readThread;
struct sockaddr_in c_addr;
int n_read = 0;
int clen = sizeof(struct sockaddr_in);
memset(&c_addr,0,clen);
socketHandler=findInputCommanderByName("socketServer",pCommandHead);
if(socketHandler==NULL){
printf("find socketHandler error\n");
pthread_exit(NULL);
}else{
socketHandler->Init(socketHandler);
printf("%s init success\n",socketHandler->commandName);
while(1){
//不断接收新的客户端的接入,接入新的客户端后创建新的读线程;
socketHandler->c_fd = accept(socketHandler->s_fd,(struct sockaddr *)&c_addr,&clen);
if(socketHandler->c_fd == -1){
perror("accept");
}
printf("c_fd:%d\n",socketHandler->c_fd);
pthread_create(&readThread,NULL,read_thread,NULL);
}
}
}
void *voice_thread(void *datas)
{
int nread;
pthread_t cmdThread;
voiceHandler=findInputCommanderByName("voice",pCommandHead);
if(voiceHandler==NULL){
printf("find voiceHandler error\n");
pthread_exit(NULL);
}else{
if(voiceHandler->Init(voiceHandler)<0){
printf("voice init error\n");
pthread_exit(NULL);
}else{
printf("%s init success\n",voiceHandler->commandName);
}
while(1){
nread=voiceHandler->getCommand(voiceHandler);
if(nread==0){
continue;
}else{
printf("voice get cmd: %s\n",voiceHandler->command);
}
}
}
}
void *dusbin_thread(void *datas)
{
dusbinHandler=findDevicesByName("dusbin",pdeviceHead );
dusbinHandler->deviceInit(dusbinHandler->pinNum);
fileHandler= findRecordsByName("fileRecords",pRecordsHead);
fileHandler->Init(fileHandler);
sqliteHandler = findRecordsByName("dataBaseRecords",pRecordsHead);
sqliteHandler->Init(sqliteHandler);
while(1){
//距离大于30cm,返回1;
if(! csbHandler->status||!strcmp(voiceHandler->command,"open")||!strcmp(socketHandler->command,"open")){
//靠近时,垃圾桶开启2秒,2秒后关闭
dusbinHandler->open(dusbinHandler->pinNum);
}else if( (!strcmp(voiceHandler->command,"close")||!strcmp(socketHandler->command,"close")) && csbHandler->status ){
dusbinHandler->close(dusbinHandler->pinNum);
}else if(csbHandler->status && strcmp(voiceHandler->command,"open") && strcmp(socketHandler->command,"open")&& strcmp(voiceHandler->command,"close")&&strcmp(socketHandler->command,"close")){
dusbinHandler->close(dusbinHandler->pinNum);
}
}
}
void *csb_thread(void *datas)
{
csbHandler=findDevicesByName("csb",pdeviceHead);
beepHandler=findDevicesByName("beep",pdeviceHead);
beepHandler->deviceInit(beepHandler->pinNum);
csbHandler->deviceInit(csbHandler->pinNum);
gettimeofday(&(beepHandler->start),NULL);
while(1){
csbHandler->status=csbHandler->readStatus(csbHandler->pinNum);
diffTime=beepHandler->stop.tv_sec-beepHandler->start.tv_sec;
if(diffTime>10){
beepHandler->open(beepHandler->pinNum);
}else{
beepHandler->close(beepHandler->pinNum);
}
usleep(500000);
}
}
int main()
{
pthread_t voiceThread;
pthread_t socketThread;
pthread_t csbThread;
pthread_t dusbinThread;
if(wiringPiSetup()==-1){
printf("wiringPi init error\n");
exit(-1);
}
//1.指令工厂初始化
pCommandHead= addSocketContrlToInputCommand(pCommandHead);
pCommandHead=addVoiceContrlToInputCommand(pCommandHead);
//2.设备控制工厂初始化
pdeviceHead=addBeepToDeviceLink(pdeviceHead);
pdeviceHead=addCsbToDeviceLink(pdeviceHead);
pdeviceHead=addDusbinToDeviceLink(pdeviceHead);
//文件工厂初始化
pRecordsHead = addFileToRecordsLink(pRecordsHead);
pRecordsHead=addDataBaseToRecordsLink(pRecordsHead);
//3.线程池建立
//超声波测距线程
pthread_create(&csbThread,NULL,csb_thread,NULL);
//3.2语音线程
pthread_create(&voiceThread,NULL, voice_thread,NULL);
//3.3socket 线程
pthread_create(&socketThread,NULL, socket_thread,NULL);
//dusbin线程
pthread_create(&dusbinThread,NULL, dusbin_thread,NULL);
//等待线程退出:
pthread_join(csbThread,NULL);
pthread_join(voiceThread,NULL);
pthread_join(socketThread,NULL);
pthread_join(dusbinThread,NULL);
return 0;
}
编译:
gcc file.c lite.c beep.c dusbin.c mainPro.c socketContrl.c csb.c voiceContrl.c -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt -lsqlite3
执行:
sudo ./a.out
智能垃圾桶