基于Linux的智能家居(工厂模式)

目录

1.项目概述

2.程序框架

3.函数准备

3.1需要函数知识点

3.2编码提醒

4.代码

5.注意事项


1.项目概述

控制端有两个,语音串口UART和Tcp通讯。

执行端有IO输出和IO输入。

2.程序框架

程序分为3部分-------------1.输入控制 2.输出设备 3.主函数-多线程

输入控制的模块----实现指令的收集,并将数据放在一个定义的<cmd.h>头文件种。

输出设备模块----实现设备初始化、设备启动、设备关闭的函数封装放在<device.h>种。

主函数-----实现UART和Tcp两个接收线程,不断接收指令并解析指令调用不同的设备函数封装

亮点,在<.h>封装了一个类,调用<.h>可以编码一个对象,然后用链表将一类对象串起来。

将对象的功能实现都封装成了函数,放在对象的结构体中,使用时直接调用。

3.函数准备

3.1需要函数知识点

main中

  • 线程创建、线程退出、线程等待、wiringPi库、链表增加、链表查找

<cmd.h><device.h>中

  • 链表创建、函数指针

设备控制、输入控制中

  • wiringPi库、结构体赋值、链表增加

3.2编码提醒

出现不能用NULL指针,包含头文件<stdlib.h>

香橙派编译wiringpi库时用gcc buzzer.c -o test -lwiringPi -lwiringPiDev -lpthread -Im -Icrypt -Irt

C语言函数没有return语句时,会返回最后一次赋值的变量的值

函数指针是定义一个指针指向函数,调用时直接用P()或者(*p)()都行,函数名和函数地址一样

指针有点神奇,指针是一个地址,但是同时也可以直接用指针使用地址里的值

没办法:这里的代码在结构体实现里用了函数的递归。错错错。第575课,添加声音识别模块,形参和实参不一样的。形参只是形式,需要函数调用时赋予实参。

炫技:这里的代码用了链表串联设备

堆栈的存储:在函数体前面的变量,后面的函数可以直接用

Orangepi的引脚图

4.代码

main中

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "contrldevice.h"  
#include "inputcmd.h"
#include <string.h>
#include <wiringPi.h>
#include <pthread.h>
#include<unistd.h>

struct OutputDevice * pdevicehead=NULL; /*device head */
struct InputDevice  *  pInputhead=NULL;  /*Input head */
struct InputDevice  *  tmp=NULL;

struct OutputDevice *find_cmd_device(char *name,struct OutputDevice * pdevicehead)
{
	struct OutputDevice *tmp=pdevicehead;
	
	if(tmp==NULL ){   /* compare is correct*/
		return NULL;
	}else{
		while(tmp!=NULL){
			if(0==strcmp(tmp->device_name,name)){
				return tmp;
			}
			tmp=tmp->next;
		}
		return NULL;
	}
}

struct InputDevice *find_input_device(char *name,struct InputDevice * pdevicehead)
{
	struct InputDevice *tmp=pdevicehead;
	
	if(tmp==NULL ){   /* compare is correct*/
		return NULL;
	}else{
		while(tmp!=NULL){
			if(0==strcmp(tmp->cmddevice_name,name)){
				return tmp;
			}
			tmp=tmp->next;
		}
		return NULL;
	}
}

void * voice_thread(void *data)  /* voice_thread */
{   
	int nread;
	struct InputDevice * tmp=find_input_device("voice",pInputhead);
	if(tmp==NULL){
		printf("no find voice phead!\r\n");
		pthread_exit(NULL);
		
	}else{
		if(tmp->init(tmp)==-1){
			printf("voice init faild!\r\n");
			pthread_exit(NULL);
		}
	}
	
	while(1){
		memset(tmp->cmd,0,sizeof(tmp->cmd));  
		nread=tmp->getcmd(tmp);            /* when uart no data come cmd while get uart overtime */
		if(nread==0){
			printf("voice cmd no data arival!\r\n");
		}else{
			printf("voice recive %d data:%s\r\n",nread,tmp->cmd);
		}
	}	

}

void * sockread_thread(void *data) 
{
	int nread;
	while(1){
		memset(tmp->cmd,'\0',sizeof(tmp->cmd));
		nread=read(tmp->ss_fd,&tmp->cmd,sizeof(tmp->cmd));
		if(nread==0){                 /* cannot recv cmd */ 
			printf("connect is cutdon! \r\n");
			pthread_exit(NULL);
		}else{                         /*can recive cmd */ 
			printf("server  receved %d cmd:%s \r\n",nread,tmp->cmd); 	
		}
	}
			
}


void * socket_thread(void *data) 
{
	int nread;
	pthread_t socketreadthread;
	tmp=find_input_device("socket",pInputhead);
	if(tmp==NULL){
		printf("no find socket phead!\r\n");
		pthread_exit(NULL);
		
	}else{
		if(tmp->init(tmp)==-1){
			printf("socket init faild!\r\n");
			pthread_exit(NULL);
		}
	}
		
	while(1){
		
		if(tmp->getcmd(tmp)==-1){
			perror("error");  /* get ss_fd error  */
		}
		/*socket  read线程*/
		pthread_create(&socketreadthread,NULL,sockread_thread,NULL);
		pthread_join(socketreadthread,NULL);   /* 等读线程退出在进行  */
	}
}



int main(void)
{
	char device_name[32];

	pthread_t voicethread; 
	pthread_t socketthread; 
	

	
	if(-1==wiringPiSetup()){
		printf("wiringpi init fail!\r\n");
		return 0;
	}
	/*1.指令工厂初始化  加入设备 */
	pInputhead=add_input_voice(pInputhead);
	pInputhead=add_input_socket(pInputhead);
	
	/*2.设备工厂初始化   加入设备 */
	pdevicehead=add_device_dingnerlight(pdevicehead);
	pdevicehead=add_device_restlight(pdevicehead);
	pdevicehead=add_device_firedetect(pdevicehead);
	
	/*2.1找设备 */
	/*struct OutputDevice * tmp=find_cmd_device(device_name,pdevicehead);
	while(1){
		printf("input device name:");
		scanf("%s",device_name);
		tmp=find_cmd_device(device_name,pdevicehead);
		printf("input cmd name 1/2:");
		scanf("%d",&cmd);
		switch(cmd){
			case 1:
				tmp->init();
				tmp->open();
				break;
			case 2:
				tmp->init();
				tmp->close();
				break;
			default:
				printf("no this cmd");
				break;
		}
	}*/
	
	
/*3. 线程池建立*/
	/*3.1 语音线程*/
	pthread_create(&voicethread,NULL,voice_thread,NULL);
	
	/*3.2socket线程*/
	pthread_create(&socketthread,NULL,socket_thread,NULL);
	
	
	
	/*3.3摄像头线程*/
	/*3.4 火灾线程*/
	
	pthread_join(voicethread,NULL);  /*线程等待不让主程序退出*/
	pthread_join(socketthread,NULL);  /*线程等待不让主程序退出*/
	return 0; 
}

contrldevice.h

cpp 复制代码
#include <stdio.h>

struct OutputDevice{
	char device_name[32];
	int status;
	
	int (*init)();
	int (*open)();
	int (*close)();
	
	int (*read)();
	int (*changeStatus)();
	
	struct OutputDevice *next;
	
};
struct OutputDevice * add_device_dingnerlight(struct OutputDevice *phead);
struct OutputDevice * add_device_restlight(struct OutputDevice *phead);
struct OutputDevice * add_device_firedetect(struct OutputDevice *phead);

inputcmd.h

cpp 复制代码
#include <stdio.h> 


struct InputDevice{
	
	char cmddevice_name[32];
	char  cmd[32];
	int  fd;
	int  ss_fd;
	
	int (*init)();
	int (*getcmd)();
	
	struct InputDevice *next;
	
};

struct InputDevice * add_input_voice(struct InputDevice *phead);
struct InputDevice * add_input_socket(struct InputDevice *phead); 

dingnerlight.c

cpp 复制代码
#include <stdio.h> 
#include "contrldevice.h"  //include i can use struct
#include <wiringPi.h>

#define dingnerlightPin 2
/*struct OutputDevive{
	char device_name[32];
	int status;
	
	int (*init)();
	int (*open)();
	int (*close)();
	
	int (*read)();
	int (*changeStatus)();
	
	sturct OutputDevive *next;
	
} */

int dingnerlight_init(void)
{
	pinMode(dingnerlightPin,OUTPUT);
	digitalWrite(dingnerlightPin,HIGH);
	
	return 0;
	
}
int dingnerlight_open(void)
{
	digitalWrite(dingnerlightPin,LOW);
	return 0;
}

int dingnerlight_close(void)
{
	digitalWrite(dingnerlightPin,HIGH);
	return 0;
}

struct OutputDevice dingnerlight={      /*"this give valve not init"*/
	.device_name="dingnerlight",
	.init=dingnerlight_init,
	.open=dingnerlight_open,
	.close=dingnerlight_close
};

struct OutputDevice * add_device_dingnerlight(struct OutputDevice *phead)
{
	if(phead==NULL){
		return &dingnerlight;	
	}else{
		dingnerlight.next=phead;
		phead=&dingnerlight;
		return phead;
			
	}
}

firedetect.c

cpp 复制代码
#include <stdio.h> 
#include "contrldevice.h"  //include i can use struct
#include <wiringPi.h>

#define firedetectPin 6
/*struct OutputDevice{
	char device_name[32];
	int status;
	
	int (*init)();
	int (*open)();
	int (*close)();
	
	int (*read)();
	int (*changeStatus)();
	
	sturct OutputDevive *next;
	
} */

int firedetect_init(void)
{
	pinMode(firedetectPin,INPUT);
	
	
	return 0;	
}

int firedetect_read(void)
{
	return digitalRead(firedetectPin);
}


struct OutputDevice firedetect={      /*"this give valve not init"*/
	.device_name="firedetect",
	.init=firedetect_init,
	.read=firedetect_read
};

struct OutputDevice * add_device_firedetect(struct OutputDevice *phead)
{
	if(phead==NULL){
		return &firedetect;	
	}else{
		firedetect.next=phead;
		phead=&firedetect;
		return phead;
			
	}
}

restlight.c

cpp 复制代码
#include <stdio.h> 
#include "contrldevice.h"  //include i can use struct
#include <wiringPi.h>

#define restlightPin 8
/*struct OutputDevice{
	char device_name[32];
	int status;
	
	int (*init)();
	int (*open)();
	int (*close)();
	
	int (*read)();
	int (*changeStatus)();
	
	sturct OutputDevice *next;
	
} */

int restlight_init(void)
{
	pinMode(restlightPin,OUTPUT);
	digitalWrite(restlightPin,HIGH);
	
	return 0;
	
}
int restlight_open(void)
{
	digitalWrite(restlightPin,LOW);
	return 0;
}

int restlight_close(void)
{
	digitalWrite(restlightPin,HIGH);
	return 0;
}

struct OutputDevice restlight={      /*"this give valve not init"*/
	.device_name="restlight",
	.init=restlight_init,
	.open=restlight_open,
	.close=restlight_close
};

struct OutputDevice * add_device_restlight(struct OutputDevice *phead)
{
	if(phead==NULL){
		return &restlight;	
	}else{
		restlight.next=phead;
		return &restlight;		
	}
}

socketcmd.c

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include "inputcmd.h"/*include i can use struct*/ 

/*struct InputDevice{
	
	char cmddevice_name[32];
	char  cmd[32];
	int  fd;
	int  ss_fd;
	
	int (*init)();
	int (*getcmd)();
	
	struct InputDevice *next;
	
}; */

int socket_getcmd(struct InputDevice *phead)
{
	int len;
	
	struct sockaddr_in c_ddr;  /*save clinet msg*/ 
	
	/*4.accept come and connect for once*/ 
	len=sizeof(c_ddr);

	
	phead->ss_fd=accept(phead->fd,(struct sockaddr *)&c_ddr,&len);
	if(phead->ss_fd == -1){
		perror("accept:");
	}
	/*5.read from connect ss_fd*/ 
	/*5.2 read*/ 
	
	
	printf("conect succese!==========\r\n");
		

				
	return phead->ss_fd;
}

int socket_init(struct InputDevice *phead)
{
	
	int s_fd;
 
	struct sockaddr_in s_ddr;  /*build server msg*/ 
 
	s_fd= socket(AF_INET, SOCK_STREAM, 0);/*1.build a soket specified*/ 
	if(s_fd==-1){
		perror("error is");
	}
	/*2.build all bind*/ 
	s_ddr.sin_family=AF_INET;
	s_ddr.sin_port=htons(8880);
	s_ddr.sin_addr.s_addr=htonl(INADDR_ANY);
	/*give the bind*/ 
	bind(s_fd,(struct sockaddr *)&s_ddr,sizeof(s_ddr));
	/*3.waite for client*/ 
	listen(s_fd,8);
	
	phead->fd=s_fd;

	return s_fd;
}

struct InputDevice struc_socket={
	.cmd={0},
	.cmddevice_name="socket",
	.init=socket_init,
	.getcmd=socket_getcmd
	
};

struct InputDevice * add_input_socket(struct InputDevice *phead)
{
	if(phead==NULL){
		return &struc_socket;	
	}else{
		struc_socket.next=phead;
		phead=&struc_socket;
		return phead;		
	}
}

voicecmd.c

cpp 复制代码
  //include i can use struct
#include <wiringPi.h>
#include <wiringSerial.h>
#include <stdlib.h>
#include <unistd.h>
#include "inputcmd.h"

/*struct InputDevice{
	
	char cmddevice_name[32];
	char  cmd[32];
	int fd;
	
	int (*init)();
	int (*getcmd)();
	
	sturct InputDevice *next;
	
} */

int voice_getcmd(struct InputDevice *phead)
{
	int nread;
	nread=read(phead->fd,phead->cmd,sizeof(phead->cmd));
	
	return nread;
	

}

int voice_init(struct InputDevice *phead)
{
	int fd1;
	if((fd1=serialOpen("/dev/ttyS5",115200))<0){
		printf("uart init fail!\r\n");
		exit(-1);
	}
	phead->fd=fd1;
	return fd1;
}

struct InputDevice voice={
	.cmd={0},
	.cmddevice_name="voice",
	.init=voice_init,
	.getcmd=voice_getcmd
	
};

struct InputDevice * add_input_voice(struct InputDevice *phead)
{
	if(phead==NULL){
		return &voice;	
	}else{
		voice.next=phead;
		phead=&voice;
		return phead;		
	}
}

5.注意事项

相关推荐
tokepson4 小时前
Mysql下载部署方法备份(Windows/Linux)
linux·服务器·windows·mysql
zz_nj6 小时前
工作的环境
linux·运维·服务器
极客先躯6 小时前
如何自动提取Git指定时间段的修改文件?Win/Linux双平台解决方案
linux·git·elasticsearch
suijishengchengde7 小时前
****LINUX时间同步配置*****
linux·运维
qiuqyue7 小时前
基于虹软Linux Pro SDK的多路RTSP流并发接入、解码与帧级处理实践
linux·运维·网络
切糕师学AI7 小时前
Linux 操作系统简介
linux
南烟斋..8 小时前
GDB调试核心指南
linux·服务器
爱跑马的程序员8 小时前
Linux 如何查看文件夹的大小(du、df、ls、find)
linux·运维·ubuntu
oMcLin10 小时前
如何在 Ubuntu 22.04 LTS 上部署并优化 Magento 电商平台,提升高并发请求的响应速度与稳定性?
linux·运维·ubuntu
Qinti_mm11 小时前
Linux io_uring:高性能异步I/O革命
linux·i/o·io_uring