基于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中

#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.mzph.cn/news/75543.shtml

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

相关文章

h5上传图片并裁剪

本文主要实现&#xff0c;h5通过input上传图片后&#xff0c;利用cropperjs进行裁剪&#xff0c;获取指定尺寸 1 安装cropperjs npm install cropperjs 2 具体实现 home.jsx 代码中的result模块用来展示最终的裁剪结果&#xff1b;mask用作页面最上层蒙层&#xff0c;用来裁…

文件上传漏洞案例

目录 1.案例一 1&#xff09;案例源码 2&#xff09;创建web.php文件 3&#xff09;使用抓包软件 2.案例二 1&#xff09;案例代码 2&#xff09; 案例分析 3&#xff09;copy命令生成图片马 4&#xff09;上传图片马到服务器 5&#xff09;解析 文件图片 3.案例三 …

计算机系统的基本概念

计算机系统的基本概念 本文主要以hello.c这个程序的整个生命周期来简单了解一下计算机系统结构的基本概念。 #include <stdio.h>int main() {printf("hello, world\n");return 0; }gcc hello.c -o hello ./hello hello, world此刻&#xff0c;hello.c源程序…

【瑞萨零基础入门】瑞萨MCU零基础入门系列教程(更新连载中)

瑞萨MCU零基础入门系列教程 前言 得益于瑞萨强大的MCU、强大的软件开发工具(e studio)&#xff0c;也得益于瑞萨和RA生态工作室提供的支持&#xff0c;我们团队编写了《ARM嵌入式系统中面向对象的模块编程方法》&#xff0c;全书37章&#xff0c;将近500页: 讲解面向对象编程…

访问局域网内共享文件时报错0x80070043,找不到网络名

我是菜鸡 此篇只为分享一个我遇到的很简单的但是排查了好久的小问题。 我的网络环境是在校园网内&#xff0c; 自己的办公电脑设置了固定IP&#xff1a;10.11.128.236&#xff0c;同事电脑IP为&#xff1a;10.11.128.255 本人需要访问同事在局域网内分享的文件&#xff0c;…

ES索引修改mappings与重建reindex详解之修改字段类型

文章目录 概要一、创建索引1.1、获取mappings 二、新增字段修改mappings三、修改OR删除mappings已有字段3.1、创建新索引&#xff0c;将要改字段加进去3.2、同步数据3.3、删除原索引并对新索引重命名3.4、同步数据的技巧 四、参考文献 概要 elasticsearch一直在使用&#xff0…

【Python爬虫实战】爬虫封你ip就不会了?ip代理池安排上

前言 在进行网络爬取时&#xff0c;使用代理是经常遇到的问题。由于某些网站的限制&#xff0c;我们可能会被封禁或者频繁访问时会遇到访问速度变慢等问题。因此&#xff0c;我们需要使用代理池来避免这些问题。本文将为大家介绍如何使用IP代理池进行爬虫&#xff0c;并带有代…

波奇学C++:多态知识点

多态中函数的重写&#xff08;基类指针访问派生类函数&#xff09;&#xff0c;只重写函数的实现&#xff0c;而不重写声明。 class Person { public:virtual void fun(int i 0){cout << "Person"<<" "<<i;} }; class Student:public …

命令执行漏洞(附例题)

一.原理 应用有时需要调用一些执行系统命令的函数&#xff0c;如PHP中的system、exec、shell_exec、passthru、popen、proc_popen等&#xff0c;当用户能控制这些函数的参数时&#xff0c;就可以将恶意系统命令拼接到正常命令中&#xff0c;从而造成命令执行攻击。 二.利用条…

Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?

技术背景 好多开发者&#xff0c;问我们最多的问题是&#xff0c;为什么要设计轻量级RTSP服务&#xff1f;轻量级RTSP服务&#xff0c;和RTSP服务有什么区别&#xff1f; 针对这个问题&#xff0c;我们的回答是&#xff1a;轻量级RTSP服务解决的核心痛点是避免用户或者开发者…

dll修复精灵,dll修复工具下载方法分享,mfc140u.dll缺失损坏一键修复

今天&#xff0c;我将为大家分享一个关于mfc140u.dll的问题。首先&#xff0c;我想问一下在座的网友们&#xff0c;有多少人知道mfc140u.dll是什么&#xff1f;又有多少人知道它的作用以及如何解决这个问题呢&#xff1f;在接下来的演讲中&#xff0c;我将详细介绍mfc140u.dll的…

transition-group过渡动画

安装lodash库 cnpm install lodash -S 安装lodash-type cnpm install types/lodash -D <template><div><button click"random">random</button><transition-group move-class"mmm" class"wraps" tag"div&qu…

C#使用proto

写多了go代码&#xff0c;被go mod tidy惯坏了&#xff0c;还以为全天下的都很好用呢&#xff0c;结果发现并不是这样。尤其是项目组的proto还是又封了个工具直接就能跑得&#xff0c;导致以为没那么复杂的事情变得复杂了起来。是有两套生成的规则&#xff0c;时间有点晚&#…

vue-router路由守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航分为&#xff1a;全局的&#xff0c;单个路由独享的和组件级的。 一、全局路由守卫1、全局前置守卫 beforeEach 在全局前置守卫中&#xff0c;我们可以访问到即将要进入的路由对象 to&#xff0c;以及当前的路由…

虹科分享 | 解决外科医生的担忧:AR让技术自己开口说话

在手术室中&#xff0c;分心可能导致严重错误和伤害&#xff0c;这凸显了在手术过程中减少对外科医生干扰的重要性。对于外科医生来说&#xff0c;在长时间的手术过程中&#xff0c;引入新技术设备时需要考虑多种因素。根据Vuzix对500多名外科医生的综合调查显示&#xff0c;使…

LeetCode 865. Smallest Subtree with all the Deepest Nodes【树,DFS,BFS,哈希表】1534

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

MFC中的Button修改颜色的方法

添加工具箱下面的MFC Button Control控件&#xff08;不使用普通的Button控件&#xff09;&#xff1b;给按键添加变量&#xff1a;m_MFCButton1&#xff0c;变量类型&#xff08;默认&#xff09;为&#xff1a;CMFCButton&#xff1b;testDlg.cpp中初始化中添加如下代码&…

GO语言常用标准库 fmt

GO语言常用标准库 fmt 1. fmt fmt包实现了类似C语言printf和scanf的格式化I/O。主要分为向外输出内容和获取输入内容两大部分。 1.1.1. 向外输出 标准库fmt提供了以下几种输出相关函数。 Print Print系列函数会将内容输出到系统的标准输出&#xff0c;区别在于Print函数直…

机械零件保养3d模拟演示打消客户购买顾虑

复杂机械的工作运转是复杂的&#xff0c;想要对机械有深度的理解和迭代&#xff0c;必须了解它的运转原理及参数&#xff0c;复杂机械运行原因教学存在着不可视、系统庞杂及知识点多等弊病&#xff0c;3D虚拟展示是基于web3d网页运行的三维页面&#xff0c;可以将复杂机械运行过…

Java复习-20-接口(3)- 代理设计模式

代理设计模式(Proxy) 功能&#xff1a;可以帮助用户将所有的开发注意力只集中在核心业务功能的处理上。 代理模式(Proxy Pattern)是一种结构性模式。代理模式为一个对象提供了一个替身&#xff0c;以控制对这个对象的访问。即通过代理对象访问目标目标对象&#xff0c;可以在目…