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

news2025/1/14 18:24:38

目录

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中

#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

#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

#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

#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

#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

#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

#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

  //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.注意事项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/998630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【文末送书】Matlab科学计算

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

《Python入门到精通》time模块详解,Python time标准库,time库函数大全

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:小白零基础《Python入门到精通》 time模块详解 1、获取操作time.time() 获取时间戳(float)time.time_ns() 获取时间戳(int)time.thread_time()…

03JVM_类加载

一、类加载与字节码技术 1.类文件结构 2.字节码指令 3.编译期处理 4.类加载阶段 5.类加载器 6.运行期优化 1.类文件结构 类文件结构 1.1 魔数magic 介绍 每个java class文件的前4个字节是魔数&#xff1a;0x CAFEBABE。魔数作用在于分辨出java class文件和非java clas…

开学了,运营校园跑腿怎么样?

校园跑腿项目是当今市场上备受关注和追捧的一种新兴服务业。随着人们生活节奏的加快和需求多样化&#xff0c;校园跑腿项目在满足大众日常生活需求的同时也为创业者提供了巨大的商机。下面将从市场需求、竞争环境和发展前景三个方面&#xff0c;对校园跑腿项目的现状进行分析&a…

Unity实现2D游戏跟随摄像机(平滑移动)

文章目录 玩家角色脚本字段跟随逻辑 完整代码其他相关文章连接 玩家角色 首先创建一个可用的玩家角色&#xff0c;写好移动逻辑&#xff0c;如果要使用在Unity商店中购买的资源&#xff0c;可以点击Window菜单栏> Package Manager选项&#xff0c;来打开Package Manager窗口…

OSCP系列靶场-Esay-SunsetDecoy保姆级

OSCP系列靶场-Esay-SunsetDecoy保姆级 目录 OSCP系列靶场-Esay-SunsetDecoy保姆级总结准备工作信息收集-端口扫描目标开放端口收集目标端口对应服务探测 信息收集-端口测试22-SSH端口的信息收集22-SSH端口版本信息与MSF利用22-SSH协议支持的登录方式22-SSH手动登录尝试(无)22-S…

离子风蛇是什么?

离子风蛇是一种坐立式静电消除器&#xff0c;可手动将蛇管变形使风蛇指向目标方向&#xff0c;让离子气流直流吹向目标表面&#xff0c;方便移动&#xff0c;适用于工厂车间、电子行业、半导体行业、薄膜、卷料、分切等行业。可安放于各种工作区域&#xff0c;除静电除尘效果好…

【大虾送书第九期】速学Linux:系统应用从入门到精通

目录 &#x1f36d;写在前面 &#x1f36d;为什么学习Linux系统 &#x1f36d;Linux系统的应用领域 &#x1f36c;&#xff11;.Linux在服务器的应用 &#x1f36c;&#xff12;.嵌入式Linux的应用 &#x1f36c;&#xff13;.桌面Linux的应用 &#x1f36d;Linux的版本选择 &a…

你不能不了解的Java23中设计模式之【抽象工厂模式】

目录 一.介绍抽象工厂模式 1.概念 2.结构&#xff1a; 抽象工厂模式包含以下角色&#xff1a; 3.工作原理&#xff1a; 4.应用场景&#xff1a; 抽象工厂模式适用于以下情况&#xff1a; 5.使用方法&#xff1a; 二.具体实例通过抽象工厂模式实现计算器 1.创建Maven工程…

【C++--类和对象】构造函数析构函数

先来介绍一下类和对象中的六个默认成员函数&#xff1a;构造函数&#xff0c;析构函数&#xff0c;拷贝构造&#xff0c;赋值重载&#xff0c;普通对象取地址重载&#xff0c;const修饰对象取地址重载 这六类函数都是在我们没有显示定义的时候&#xff0c;编译器会自己生成的函…

有什么好用的电容笔?apple pencil替代品推荐

近年来&#xff0c;电容笔越来越成为人们日常生活中常见的数码产品之一。电容笔的便捷性得到了消费者的认可。它逐渐取代无纸化书写。那么到底电容笔哪个品牌好呢&#xff0c;电容笔哪一款最好用呢&#xff0c;今天小编给大家总结几款市面好用的电容笔&#xff0c;让我们一起来…

什么是SPA单页面,优缺点是什么?如何实现?

目录 一、SPA的优点 二、SPA的缺点 三、SPA和MPA的区别 四、如何实现SPA应用 单页面应用程序&#xff08;SPA&#xff09;是一种基于Web的软件架构&#xff0c;其中只有一个页面&#xff0c;通过不同的路由和组件来展示不同的内容。SPA的应用非常广泛&#xff0c;例如在网页…

PCB layout在布线上的设计规范有哪些?

PCB Layout是一项技术活&#xff0c;也是经验活&#xff0c;良好的PCB Layout布线可帮助工程师确保最终的电路板性能、可靠性和制造质量&#xff0c;因此是很多电子工程师的学习重点&#xff0c;下面我们来盘点下PCB Layout关于布线的规范有哪些。 1、地管的引脚接地越短越好&a…

YOLO目标检测——路标数据集+已标注voc和yolo格式标签下载分享

实际项目应用&#xff1a;自动驾驶、视频监控和安防、物体识别和分类、城市规划和地理信息系统等等数据集说明&#xff1a;YOLO路标目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;图片格式为jpg&#xff0c;共900张图片&#xff0c;…

DPText-DETR: 基于动态点query的场景文本检测,更高更快更鲁棒 | 京东探索研究院

针对场景文本检测任务&#xff0c;近期基于DEtection TRansformer (DETR) 框架预测控制点的研究工作较为活跃。在基于DETR的检测器中&#xff0c;query的构建方式至关重要&#xff0c;现有方法中较为粗糙的位置先验信息构建导致了较低的训练效率以及性能。除此之外&#xff0c;…

Tomcat源码:CoyoteAdapter、Valve#invoke、ApplicationFilterChain

前文&#xff1a; 《Tomcat源码&#xff1a;启动类Bootstrap与Catalina的加载》 《Tomcat源码&#xff1a;容器的生命周期管理与事件监听》 《Tomcat源码&#xff1a;StandardServer与StandardService》 《Tomcat源码&#xff1a;Container接口》 《Tomcat源码&#xff1a…

在32位Windows中,DLL是如何导出的?

32 位 Windows 的设计者不必担心将所有内容压缩到 256KB 的内存中。由于 Win32 中的模块基于需求分页&#xff0c;因此你所要做的就是将整个映像映射到内存中&#xff0c;然后运行访问所需的部分。 DLL中的常驻名(resident name)和非常驻名(non-resident name)之间没有区别&am…

5.4 【MySQL】页目录

记录在页中按照主键值由小到大顺序串联成一个单链表&#xff0c;如果我们想根据主键值查找页中的某条记录&#xff0c;可以这样查询&#xff1a; SELECT * FROM page_demo WHERE c1 3; 我们平常想从一本书中查找某个内容的时候&#xff0c;一般会先看目录&#xff0c;找到需…

Docker配置阿里云镜像加速器

Docker配置阿里云镜像加速器 《Docker安装详细步骤》&#xff1a;Docker安装详细步骤_周十一.的博客-CSDN博客、 在前面博文已经介绍了docker 的安装&#xff0c;因为某些原因&#xff0c;我们下载镜像比较慢&#xff0c;今天给大家介绍一下&#xff0c;如何配置阿里云的镜像加…

解决Ubuntu无法安装pycairo和PyGObject

环境&#xff1a;虚拟机Ubuntu20.04&#xff0c;vscode无法安装pycairo和PyGObject 虚拟机Ubuntu20.04&#xff0c;vscode中运行Anaconda搭建的vens 的Python3.8.10 首先在vscode中点击ctrlshiftp&#xff0c;选择Python3.8.10的环境&#xff0c;自动激活Python 最近在搞无人…