0


基于ARM树莓派实现智能家居:语音识别控制,Socket网络控制,火灾报警检测,实时监控

一 项目说明

① 设计框架

● 项目架构采用简单工厂模式来设计,将语音识别,TCP服务器设计成链表的每个节点,形成控制工厂。

● 将餐厅灯,卧室灯,二楼灯,泳池灯,蜂鸣器,火焰检测模块,也设计成链表的每个节点,形成设备端工厂。

● 基于这种架构保证项目的稳定性和功能拓展性,在添加新功能的时候,只需要添加一个链表节点文件文件就可以。

● 不管是设备端还是控制端,在实际调试过程中又涉及到临界资源的竞争,所以采用多线程来解决这个问题。

● 语音处理用的是SU-03T模块的二次开发,对串口数据进行修改并整合到树莓派的串口通信中去。

② 功能说明

● 语音模块识别语音来控制各个灯的开关,基于串口通信来配置语音命令的内容。

● 搭建TCP服务器,用socket网络通信的方式控制各个灯的开关,手机客户端发送指令到电脑服务器端来实现控制功能。

● 火灾报警,火焰检测模块结合蜂鸣器开发。接收火焰状态,检测有火源靠近时,蜂鸣器输出低电平发出警报声响,并在终端显示火灾危险提示,检测没有火源时,蜂鸣器输出高电平,停止报警声。

● 实时监控,将摄像头模块安装于树莓并配置树莓派摄像头的接口参数,打开摄像头,写入树莓ip地址及端口即可。

③ 硬件说明

树莓派开发板(3B),继电器组,房屋模型,蜂鸣器,语音模块,火焰检测模块,电池盒,摄像头,杜邦线,灯具,USB-TTL模块(串口调试)

④ 软件说明

SecureCRT8.0(树莓派终端),sourceinsight(代码编辑),filezilla(文件传输),AiThinker Serial Tool(串口调试),NetAssist(网络调试)。

二 项目代码

<1> mainPro.c 主函数

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <pthread.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include "contrlDevices.h"//外接设备
  10. #include "InputCommand.h"//控制
  11. struct InputCommander *pCommandHead = NULL;
  12. struct Devices *pdeviceHead = NULL;
  13. struct InputCommander *socketHandler = NULL;
  14. int c_fd;
  15. //外设的设备查询
  16. struct Devices *findDeviceByName(char *name,struct Devices *phead)
  17. {
  18. struct Devices *tmp = phead;
  19. if(phead == NULL){
  20. return NULL;
  21. }else{
  22. while(tmp != NULL){
  23. if(strcmp(tmp->deviceName,name) == 0){
  24. return tmp;
  25. }
  26. tmp = tmp->next;
  27. }
  28. return NULL;
  29. }
  30. };
  31. //控制设备查询
  32. struct InputCommander *findCommandByName(char *name,struct InputCommander *phead)
  33. {
  34. struct InputCommander *tmp = phead;
  35. if(phead == NULL){
  36. return NULL;
  37. }else{
  38. while(tmp != NULL){
  39. if(strcmp(tmp->commandName,name) == 0){
  40. return tmp;
  41. }
  42. tmp = tmp->next;
  43. }
  44. return NULL;
  45. }
  46. };
  47. //控制灯函数,用于语音线程
  48. void Command(struct InputCommander *CmdHandler)
  49. {
  50. struct Devices *tmp =NULL;
  51. if(strcmp("yo",CmdHandler->command) == 0){
  52. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  53. if(tmp != NULL){
  54. tmp->open(tmp->pinNum);
  55. printf("已打开泳池灯\n");
  56. }
  57. }
  58. if(strcmp("yc",CmdHandler->command) == 0){
  59. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  60. if(tmp != NULL){
  61. tmp->close(tmp->pinNum);
  62. printf("已关闭泳池灯\n");
  63. }
  64. }
  65. if(strcmp("eo",CmdHandler->command) == 0){
  66. tmp = findDeviceByName("upstairLight",pdeviceHead);
  67. if(tmp != NULL){
  68. tmp->open(tmp->pinNum);
  69. printf("已打开二楼灯\n");
  70. }
  71. }
  72. if(strcmp("ec",CmdHandler->command) == 0){
  73. tmp = findDeviceByName("upstairLight",pdeviceHead);
  74. if(tmp != NULL){
  75. tmp->close(tmp->pinNum);
  76. printf("已关闭二楼灯\n");
  77. }
  78. }
  79. if(strcmp("co",CmdHandler->command) == 0){
  80. tmp = findDeviceByName("restauranLight",pdeviceHead);
  81. if(tmp != NULL){
  82. tmp->open(tmp->pinNum);
  83. printf("已打开餐厅灯\n");
  84. }
  85. }
  86. if(strcmp("cc",CmdHandler->command) == 0){
  87. tmp = findDeviceByName("restauranLight",pdeviceHead);
  88. if(tmp != NULL){
  89. tmp->close(tmp->pinNum);
  90. printf("已关闭餐厅灯\n");
  91. }
  92. }
  93. if(strcmp("wo",CmdHandler->command) == 0){
  94. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  95. if(tmp != NULL){
  96. tmp->open(tmp->pinNum);
  97. printf("已打开卧室灯\n");
  98. }
  99. }
  100. if(strcmp("wc",CmdHandler->command) == 0){
  101. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  102. if(tmp != NULL){
  103. tmp->close(tmp->pinNum);
  104. printf("已关闭卧室灯\n");
  105. }
  106. }
  107. if(strcmp("ao",CmdHandler->command) == 0){
  108. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  109. if(tmp != NULL) tmp->open(tmp->pinNum);
  110. tmp = findDeviceByName("upstairLight",pdeviceHead);
  111. if(tmp != NULL) tmp->open(tmp->pinNum);
  112. tmp = findDeviceByName("restauranLight",pdeviceHead);
  113. if(tmp != NULL) tmp->open(tmp->pinNum);
  114. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  115. if(tmp != NULL) tmp->open(tmp->pinNum);
  116. printf("已打开所有灯\n");
  117. }
  118. if(strcmp("ac",CmdHandler->command) == 0){
  119. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  120. if(tmp != NULL) tmp->close(tmp->pinNum);
  121. tmp = findDeviceByName("upstairLight",pdeviceHead);
  122. if(tmp != NULL) tmp->close(tmp->pinNum);
  123. tmp = findDeviceByName("restauranLight",pdeviceHead);
  124. if(tmp != NULL) tmp->close(tmp->pinNum);
  125. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  126. if(tmp != NULL) tmp->close(tmp->pinNum);
  127. printf("已关闭所有灯\n");
  128. }
  129. }
  130. //语音线程
  131. void *voice_thread(void *datas)
  132. {
  133. struct InputCommander *voiceHandler;
  134. //struct Devices *tmp =NULL;
  135. int nread;
  136. voiceHandler = findCommandByName("voice",pCommandHead);
  137. if(voiceHandler == NULL){
  138. printf("find voiceHandler error\n");
  139. pthread_exit(NULL);
  140. }else{
  141. if(voiceHandler->Init(voiceHandler,NULL,NULL) < 0){
  142. printf("voice init error\n");
  143. pthread_exit(NULL);
  144. }else{
  145. printf("%s init success\n",voiceHandler->commandName);
  146. while(1){
  147. nread = voiceHandler->getCommand(voiceHandler);
  148. if(nread == 0){
  149. printf("nodata form voice\n");
  150. }else{
  151. printf("do device contrl --> %s\n",voiceHandler->command);
  152. Command(voiceHandler);
  153. }
  154. }
  155. }
  156. }
  157. }
  158. //接收客户端指令
  159. void *read_thread(void *datas)
  160. {
  161. int n_read;
  162. struct Devices *tmp =NULL;
  163. memset(socketHandler->command,'\0',sizeof(socketHandler->command));
  164. n_read = read(c_fd,socketHandler->command,sizeof(socketHandler->command));
  165. if(n_read == -1){
  166. perror("read");
  167. }else if(n_read>0){
  168. printf("\nget: %d,%s\n",n_read,socketHandler->command);
  169. if(strcmp("yo",socketHandler->command) == 0){
  170. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  171. if(tmp != NULL){
  172. tmp->open(tmp->pinNum);
  173. printf("已打开泳池灯\n");
  174. }
  175. }
  176. if(strcmp("yc",socketHandler->command) == 0){
  177. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  178. if(tmp != NULL){
  179. tmp->close(tmp->pinNum);
  180. printf("已关闭泳池灯\n");
  181. }
  182. }
  183. if(strcmp("eo",socketHandler->command) == 0){
  184. tmp = findDeviceByName("upstairLight",pdeviceHead);
  185. if(tmp != NULL){
  186. tmp->open(tmp->pinNum);
  187. printf("已打开二楼灯\n");
  188. }
  189. }
  190. if(strcmp("ec",socketHandler->command) == 0){
  191. tmp = findDeviceByName("upstairLight",pdeviceHead);
  192. if(tmp != NULL){
  193. tmp->close(tmp->pinNum);
  194. printf("已关闭二楼灯\n");
  195. }
  196. }
  197. if(strcmp("co",socketHandler->command) == 0){
  198. tmp = findDeviceByName("restauranLight",pdeviceHead);
  199. if(tmp != NULL){
  200. tmp->open(tmp->pinNum);
  201. printf("已打开餐厅灯\n");
  202. }
  203. }
  204. if(strcmp("cc",socketHandler->command) == 0){
  205. tmp = findDeviceByName("restauranLight",pdeviceHead);
  206. if(tmp != NULL){
  207. tmp->close(tmp->pinNum);
  208. printf("已关闭餐厅灯\n");
  209. }
  210. }
  211. if(strcmp("wo",socketHandler->command) == 0){
  212. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  213. if(tmp != NULL){
  214. tmp->open(tmp->pinNum);
  215. printf("已打开卧室灯\n");
  216. }
  217. }
  218. if(strcmp("wc",socketHandler->command) == 0){
  219. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  220. if(tmp != NULL){
  221. tmp->close(tmp->pinNum);
  222. printf("已关闭卧室灯\n");
  223. }
  224. }
  225. if(strcmp("ao",socketHandler->command) == 0){
  226. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  227. if(tmp != NULL) tmp->open(tmp->pinNum);
  228. tmp = findDeviceByName("upstairLight",pdeviceHead);
  229. if(tmp != NULL) tmp->open(tmp->pinNum);
  230. tmp = findDeviceByName("restauranLight",pdeviceHead);
  231. if(tmp != NULL) tmp->open(tmp->pinNum);
  232. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  233. if(tmp != NULL) tmp->open(tmp->pinNum);
  234. printf("已打开所有灯\n");
  235. }
  236. if(strcmp("ac",socketHandler->command) == 0){
  237. tmp = findDeviceByName("bathroomLight",pdeviceHead);
  238. if(tmp != NULL) tmp->close(tmp->pinNum);
  239. tmp = findDeviceByName("upstairLight",pdeviceHead);
  240. if(tmp != NULL) tmp->close(tmp->pinNum);
  241. tmp = findDeviceByName("restauranLight",pdeviceHead);
  242. if(tmp != NULL) tmp->close(tmp->pinNum);
  243. tmp = findDeviceByName("livingroomLight",pdeviceHead);
  244. if(tmp != NULL) tmp->close(tmp->pinNum);
  245. printf("已关闭所有灯\n");
  246. }
  247. }else{
  248. printf("client quit\n");
  249. }
  250. }
  251. //网络线程
  252. void *socket_thread(void *datas)
  253. {
  254. int n_read = 0;
  255. pthread_t readThread;
  256. struct sockaddr_in c_addr;
  257. memset(&c_addr,0,sizeof(struct sockaddr_in));
  258. int clen = sizeof(struct sockaddr_in);
  259. socketHandler = findCommandByName("socketServer",pCommandHead);
  260. if(socketHandler == NULL){
  261. printf("find socketHandler error\n");
  262. pthread_exit(NULL);
  263. }else{
  264. printf("%s init success\n",socketHandler->commandName);
  265. }
  266. socketHandler->Init(socketHandler,NULL,NULL);
  267. while(1){
  268. c_fd = accept(socketHandler->sfd,(struct sockaddr *)&c_addr,&clen);
  269. pthread_create(&readThread,NULL,read_thread,NULL);
  270. }
  271. }
  272. //火焰线程
  273. void *fire_thread(void *datas)
  274. {
  275. int status;
  276. struct Devices *fireDeviceTmp = NULL;
  277. struct Devices *beepDeviceTmp = NULL;
  278. fireDeviceTmp = findDeviceByName("fireIfOrNot",pdeviceHead);
  279. beepDeviceTmp = findDeviceByName("beep",pdeviceHead);
  280. fireDeviceTmp->deviceInit(fireDeviceTmp->pinNum);
  281. beepDeviceTmp->deviceInit(beepDeviceTmp->pinNum);
  282. while(1){
  283. status = fireDeviceTmp->changeStatus(fireDeviceTmp->pinNum); //读取“火焰传感器”状态
  284. if(status == 0){ //检测到火焰或强光源
  285. printf("fire danger warning!!!\n");
  286. beepDeviceTmp->open(beepDeviceTmp->pinNum); //打开蜂鸣器
  287. delay(1000);
  288. }else{
  289. beepDeviceTmp->close(beepDeviceTmp->pinNum); //关闭蜂鸣器
  290. }
  291. }
  292. }
  293. int main()
  294. {
  295. int status;
  296. char name[128];
  297. struct Devices *tmp = NULL;
  298. pthread_t voiceThread;
  299. pthread_t socketThread;
  300. pthread_t fireThread;
  301. if(-1 == wiringPiSetup()){ //初始化wiringPi库
  302. return -1;
  303. }
  304. //1.指令工厂
  305. pCommandHead = addvoiceContrlToInputCommandLink(pCommandHead);//语音
  306. pCommandHead = addSocketContrlToInputCommandLink(pCommandHead);//网络
  307. //2.设备控制工厂初始化
  308. pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);//泳池灯
  309. pdeviceHead = addUpstairLightToDeviceLink(pdeviceHead);//二楼灯
  310. pdeviceHead = addLivingroomLightToDeviceLink(pdeviceHead);//卧室灯
  311. pdeviceHead = addRestauranLightToDeviceLink(pdeviceHead);//餐厅灯
  312. pdeviceHead = addFireToDeviceLink(pdeviceHead);//火灾检测
  313. pdeviceHead = addBeepToDeviceLink(pdeviceHead);//蜂鸣器
  314. //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
  315. //3.线程池建立
  316. //3.1 语音线程
  317. pthread_create(&voiceThread,NULL,voice_thread,NULL);
  318. //3.2 socket线程
  319. pthread_create(&socketThread,NULL,socket_thread,NULL);
  320. //3.3 火灾线程
  321. pthread_create(&fireThread,NULL,fire_thread,NULL);
  322. /*while(1){ //用于四盏灯的调试
  323. printf("input:\n");
  324. scanf("%s",name);
  325. tmp = findDeviceByName(name,pdeviceHead);
  326. if(tmp != NULL){
  327. tmp->deviceInit(tmp->pinNum);
  328. tmp->open(tmp->pinNum);
  329. }
  330. }*/
  331. pthread_join(voiceThread,NULL);
  332. pthread_join(socketThread,NULL);
  333. pthread_join(fireThread,NULL);
  334. return 0;
  335. }

<2> InputCommand.h 控制设备头文件

  1. #include <wiringPi.h>
  2. #include <stdlib.h>
  3. struct InputCommander{
  4. char commandName[128];
  5. char deviceName[128];
  6. char command[32];
  7. int (*Init)(struct InputCommander *voicer,char *ipAdress,char *port);
  8. int (*getCommand)(struct InputCommander *voicer);
  9. char log[1024];
  10. int fd;
  11. char port[12];
  12. char ipAddress[32];
  13. int sfd;
  14. struct InputCommander *next;
  15. };
  16. struct InputCommander *addvoiceContrlToInputCommandLink(struct InputCommander *phead);
  17. struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead);

<3> contrlDevices.h 外接设备头文件

  1. #include <wiringPi.h>
  2. #include <stdlib.h>
  3. struct Devices{
  4. char deviceName[128];
  5. int status;
  6. int pinNum;
  7. int (*open)(int pinNum);
  8. int (*close)(int pinNum);
  9. int (*deviceInit)(int pinNum);
  10. int (*changeStatus)(int status);
  11. struct Devices *next;
  12. };
  13. struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
  14. struct Devices *addUpstairLightToDeviceLink(struct Devices *phead);
  15. struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead);
  16. struct Devices *addRestauranLightToDeviceLink(struct Devices *phead);
  17. struct Devices *addFireToDeviceLink(struct Devices *phead);
  18. struct Devices *addBeepToDeviceLink(struct Devices *phead);

<4> bathroomLight.c 泳池灯

  1. #include "contrlDevices.h"
  2. int bathroomLightOpen(int pinNum)
  3. {
  4. digitalWrite(pinNum,LOW);
  5. }
  6. int bathroomLightClose(int pinNum)
  7. {
  8. digitalWrite(pinNum,HIGH);
  9. }
  10. int bathroomLightCloseInit(int pinNum)
  11. {
  12. pinMode(pinNum,OUTPUT);
  13. digitalWrite(pinNum,HIGH);
  14. }
  15. int bathroomLightCloseStatus(int status)
  16. {
  17. }
  18. struct Devices bathroomLight = {
  19. .deviceName = "bathroomLight",
  20. .pinNum = 21,
  21. .open = bathroomLightOpen,
  22. .close = bathroomLightClose,
  23. .deviceInit = bathroomLightCloseInit,
  24. .changeStatus = bathroomLightCloseStatus
  25. };
  26. struct Devices *addBathroomLightToDeviceLink(struct Devices *phead)
  27. {
  28. if(phead == NULL){
  29. return &bathroomLight;
  30. }else{
  31. bathroomLight.next = phead;
  32. phead = &bathroomLight;
  33. }
  34. }

<5> livingroomLight.c 卧室灯

  1. #include "contrlDevices.h"
  2. int livingroomLightOpen(int pinNum)
  3. {
  4. digitalWrite(pinNum,LOW);
  5. }
  6. int livingroomLightClose(int pinNum)
  7. {
  8. digitalWrite(pinNum,HIGH);
  9. }
  10. int livingroomLightCloseInit(int pinNum)
  11. {
  12. pinMode(pinNum,OUTPUT);
  13. digitalWrite(pinNum,HIGH);
  14. }
  15. int livingroomLightCloseStatus(int status)
  16. {
  17. }
  18. struct Devices livingroomLight = {
  19. .deviceName = "livingroomLight",
  20. .pinNum = 24,
  21. .open = livingroomLightOpen,
  22. .close = livingroomLightClose,
  23. .deviceInit = livingroomLightCloseInit,
  24. .changeStatus = livingroomLightCloseStatus
  25. };
  26. struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead)
  27. {
  28. if(phead == NULL){
  29. return &livingroomLight;
  30. }else{
  31. livingroomLight.next = phead;
  32. phead = &livingroomLight;
  33. }
  34. }

<6> restaurantLight.c 餐厅灯

  1. #include "contrlDevices.h"
  2. int restauranLightOpen(int pinNum)
  3. {
  4. digitalWrite(pinNum,LOW);
  5. }
  6. int restauranLightClose(int pinNum)
  7. {
  8. digitalWrite(pinNum,HIGH);
  9. }
  10. int restauranLightCloseInit(int pinNum)
  11. {
  12. pinMode(pinNum,OUTPUT);
  13. digitalWrite(pinNum,HIGH);
  14. }
  15. int restauranLightCloseStatus(int status)
  16. {
  17. }
  18. struct Devices restauranLight = {
  19. .deviceName = "restauranLight",
  20. .pinNum = 23,
  21. .open = restauranLightOpen,
  22. .close = restauranLightClose,
  23. .deviceInit = restauranLightCloseInit,
  24. .changeStatus = restauranLightCloseStatus
  25. };
  26. struct Devices *addRestauranLightToDeviceLink(struct Devices *phead)
  27. {
  28. if(phead == NULL){
  29. return &restauranLight;
  30. }else{
  31. restauranLight.next = phead;
  32. phead = &restauranLight;
  33. }
  34. }

<7> upstairLight.c 二楼灯

  1. #include "contrlDevices.h"
  2. int upstairLightOpen(int pinNum)
  3. {
  4. digitalWrite(pinNum,LOW);
  5. }
  6. int upstairLightClose(int pinNum)
  7. {
  8. digitalWrite(pinNum,HIGH);
  9. }
  10. int upstairLightCloseInit(int pinNum)
  11. {
  12. pinMode(pinNum,OUTPUT);
  13. digitalWrite(pinNum,HIGH);
  14. }
  15. int upstairLightCloseStatus(int status)
  16. {
  17. }
  18. struct Devices upstairLight = {
  19. .deviceName = "upstairLight",
  20. .pinNum = 22,
  21. .open = upstairLightOpen,
  22. .close = upstairLightClose,
  23. .deviceInit = upstairLightCloseInit,
  24. .changeStatus = upstairLightCloseStatus
  25. };
  26. struct Devices *addUpstairLightToDeviceLink(struct Devices *phead)
  27. {
  28. if(phead == NULL){
  29. return &upstairLight;
  30. }else{
  31. upstairLight.next = phead;
  32. phead = &upstairLight;
  33. }
  34. }

<8> fire.c 火焰传感器

  1. #include "contrlDevices.h"
  2. int fireIfOrNotInit(int pinNum)
  3. {
  4. pinMode(pinNum,INPUT);
  5. digitalWrite(pinNum,HIGH);
  6. }
  7. int fireStatusRead(int pinNum)
  8. {
  9. return digitalRead(pinNum);
  10. }
  11. struct Devices fireIfOrNot = {
  12. .deviceName = "fireIfOrNot",
  13. .pinNum = 25,
  14. .deviceInit = fireIfOrNotInit,
  15. .changeStatus = fireStatusRead
  16. };
  17. struct Devices *addFireToDeviceLink(struct Devices *phead)
  18. {
  19. if(phead == NULL)
  20. {
  21. return &fireIfOrNot;
  22. }else{
  23. fireIfOrNot.next = phead;
  24. phead = &fireIfOrNot;
  25. //return phead;
  26. }
  27. }

<9> beep.c 蜂鸣器

  1. #include "contrlDevices.h"
  2. //struct Devices *addBeepToDeviceLink(struct Devices *phead);
  3. int beepInit(int pinNum) //初始化函数
  4. {
  5. pinMode(pinNum,OUTPUT); //配置引脚为输出引脚
  6. digitalWrite(pinNum,HIGH); //引脚输出高电平,即默认为关闭状态
  7. }
  8. int beepOpen(int pinNum) //打开蜂鸣器函数
  9. {
  10. digitalWrite(pinNum,LOW);
  11. }
  12. int beepClose(int pinNum) //关闭蜂鸣器函数
  13. {
  14. digitalWrite(pinNum,HIGH);
  15. }
  16. struct Devices beep = { //蜂鸣器设备链表节点
  17. .deviceName = "beep",
  18. .pinNum = 29,
  19. .deviceInit = beepInit,
  20. .open = beepOpen,
  21. .close = beepClose,
  22. //.next = NULL
  23. };
  24. struct Devices* addBeepToDeviceLink(struct Devices *phead) //头插法将设备节点加入设备工厂链表函数
  25. {
  26. if(phead == NULL){
  27. return &beep;
  28. }else{
  29. beep.next = phead;
  30. phead = &beep;
  31. }
  32. }

<10> voiceContrl.c 语音模块

  1. #include <wiringPi.h>
  2. #include <stdio.h>
  3. #include <wiringSerial.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "InputCommand.h"
  8. int voiceGetCommand(struct InputCommander *voicer)//获取指令函数
  9. {
  10. int nread = 0;
  11. memset(voicer->command,'\0',sizeof(voicer->command));
  12. nread = read(voicer->fd,voicer->command,sizeof(voicer->command));//将串口的指令读到voicer->command中
  13. return nread;
  14. }
  15. int voiceInit(struct InputCommander *voicer,char *ipAdress,char *port)
  16. {
  17. int fd;
  18. if((fd = serialOpen(voicer->deviceName,9600))==-1){ //初始化树莓派串口
  19. perror("serialOpen");
  20. return -1;
  21. }
  22. voicer->fd = fd; //打开串口文件成功,返回“文件描述符”到“语音控制”链表节点中
  23. return fd;
  24. }
  25. struct InputCommander voiceContrl = { //语音控制链表节点
  26. .commandName = "voice",
  27. .deviceName = "/dev/ttyAMA0",
  28. .command = {'\0'},
  29. .Init = voiceInit,
  30. .getCommand = voiceGetCommand,
  31. .log = {'\0'},
  32. .next = NULL
  33. };
  34. struct InputCommander *addvoiceContrlToInputCommandLink(struct InputCommander *phead)//头插法将“语音控制”链表节点加入指令控制工厂链表函数
  35. {
  36. if(phead == NULL){
  37. return &voiceContrl;
  38. }else{
  39. voiceContrl.next = phead;
  40. phead = &voiceContrl;
  41. return phead;
  42. }
  43. }

<11> socketContrl.c 服务器

  1. #include <wiringPi.h>
  2. #include <stdio.h>
  3. #include <wiringSerial.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <string.h>
  11. #include "InputCommand.h"
  12. int socketGetCommand(struct InputCommander *socketMes)
  13. {
  14. int c_fd;
  15. int n_read = 0;
  16. struct sockaddr_in c_addr;
  17. memset(&c_addr,0,sizeof(struct sockaddr_in));
  18. int clen = sizeof(struct sockaddr_in);
  19. c_fd = accept(socketMes->sfd,(struct sockaddr *)&c_addr,&clen);
  20. n_read = read(c_fd,socketMes->command,sizeof(socketMes->command));
  21. if(n_read == -1){
  22. perror("read");
  23. }else if(n_read>0){
  24. printf("\nget: %d\n",n_read);
  25. }else{
  26. printf("client quit\n");
  27. }
  28. return n_read;
  29. }
  30. int socketInit(struct InputCommander *socketMes,char *ipAdress,char *port) //socket初始化
  31. {
  32. int s_fd;
  33. struct sockaddr_in s_addr;
  34. memset(&s_addr,0,sizeof(struct sockaddr_in));
  35. //1. socket创建
  36. s_fd = socket(AF_INET, SOCK_STREAM, 0);
  37. if(s_fd == -1){
  38. perror("socket");
  39. exit(-1);
  40. }
  41. s_addr.sin_family = AF_INET;
  42. s_addr.sin_port = htons(atoi(socketMes->port));
  43. inet_aton(socketMes->ipAddress,&s_addr.sin_addr);
  44. //2. bind
  45. bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
  46. //3. listen
  47. listen(s_fd,10);
  48. printf("socker Server listening ......\n");
  49. socketMes->sfd = s_fd;
  50. return s_fd; //套接字描述符返回到网络控制链表节点
  51. }
  52. struct InputCommander socketContrl = {
  53. .commandName = "socketServer",
  54. .command = {'\0'},
  55. .port = "8080",
  56. .ipAddress = "192.168.1.7",
  57. .Init = socketInit,
  58. .getCommand = socketGetCommand,
  59. .log = {'\0'},
  60. .next = NULL
  61. };
  62. struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead)//头插法将设备节点加入设备工厂链表函数
  63. {
  64. if(phead == NULL){
  65. return &socketContrl;
  66. }else{
  67. socketContrl.next = phead;
  68. phead = &socketContrl;
  69. }
  70. }

三 项目演示

四 项目问题总结

通过这个项目,我对于简单工厂模式,Linux操作系统的文件,进程,线程,网络以及Linux字符设备开发都有了比较大的收获。整个项目的逻辑还算简单明了,但在实际开发调试过程中也会遇到一些问题,还好都逐一发现并解决。

问题一

语音控制不了灯

分析解决:串口测试语音能通过,串口命令测试灯也能通过,代码没有任何报错,逻辑也没有任何问题,唯独语音控制不了灯。我的语音逻辑是通过if来判断收到的控制指令从而实现对灯的控制。既然其他方面没有问题,那就是if判断不了收到的控制指令,所以把问题锁定于此。我将语音SDK重新生成配置,将判断条件修改成和语音SDK一致的内容后,继续先用串口测语音,再用串口测灯,最后实现语音控制灯,顺利实现。总结就是:语音配置的参数内容必须和判断条件的内容一致,才能准确判断并执行。之前做过语音控制刷抖音,因为太简单,中间没有任何报错,所以也就没有发现这个问题。笔记于此,当是提醒。

问题二

段错误

分析解决:做火灾检测报警这一块,因为是蜂鸣器和火焰传感器的结合,所以须将蜂鸣器整合在火焰线程中,编译后直接提示段错误,没有其他任何报错。我先检查了火焰,蜂鸣器,外接设备头文件以及火焰线程部分的代码,没有问题,至少肉眼可见的逻辑是没有问题的,然后在检查火焰传感器和蜂鸣器的IO口接线方面,也没有问题。捣鼓了很长时间无果,还好心理素质过硬,面向百度,依然无果。在最后,尝试用printf的方法将问题锁定在火焰线程中蜂鸣器的初始化部分。最后的最后才发现,在主函数int main()中设备控制工厂初始化没有添加蜂鸣器部分代码。

问题三

连接服务器超时

其实这不算什么问题,只是记录下来。通过手机客户端发送指令到服务器端实现控制灯,那么就需要连接服务器,如果出现连接超时或连接错误,首先排查是否能ping通网络,然后检查代码,ip,端口,如果都没问题,就可以考虑端口号是否被占用,修改下端口,多尝试连接几次。

问题四

线材和模块布局凌乱

前期没注意这个问题,只管接线并测试各模块的功能,到后期快完结时,走线杂乱已无力回天。后面的开发中值得注意!

五 项目相关知识点整理

该项目所涉及到的知识点,我将往期相关的博文都归纳在此:

C语言设计模式:实现简单工厂模式和工程创建

树莓派编程控制继电器及继电器组

通过Linux串口实现树莓派与电脑通信

树莓派+摄像头:mjpg-streamer实现监控功能的配置及调试

基于Linux串口实现语音控制刷抖音

C语言数据结构:链表的增删改查及动态创建

Linux网络编程:Socket服务器和客户端实现双方通信

Linux线程:创建(pthread_create),等待(pthread_join),退出(pthread_exit)

Orangepi Zero2 全志H616:蜂鸣器,链接库,shell脚本


本文转载自: https://blog.csdn.net/m0_74985965/article/details/130407389
版权归原作者 AsheHero 所有, 如有侵权,请联系我们删除。

“基于ARM树莓派实现智能家居:语音识别控制,Socket网络控制,火灾报警检测,实时监控”的评论:

还没有评论