赞
踩
1. 语音监听线程:用于监听语音指令, 当有语音指令过来后, 通过消息队列的方式给消息处理线程发送指令
2. 网络监听线程:用于监听网络指令,当有网络指令过来后, 通过消息队列的方式给消息处理线程发送指令
3. 火灾检测线程:当存在煤气泄漏或者火灾闲情时, 发送警报指令给消息处理线程
4. 消息监听线程: 用于处理以上3个线程发过来的指令,并根据指令要求配置GPIO引脚状态,OLED屏显示、语音播报,还有人脸识别开门
上述四个线程采用统一个对外接口接口,同时添加到监听链表中
统一的监听模块接口如下:
- struct control
- {
- char control_name[128]; //监听模块名称
- int (*init)(void); //初始化函数
- void (*final)(void);//结束释放函数
- void *(*get)(void *arg);//监听函数,如语音监听
- void *(*set)(void *arg); //设置函数,如语音播报
- struct control *next;
- };
//定义类似如下函数向这个统一的接口中添加
struct control *add_device_to_ctrl_list(struct control *phead, struct control *device);
被控制的设备类也统一配置接口,同时添加到设备链表中。
统一的设备类接口如下:
- struct gdevice
- {
- char dev_name[128]; //设备名称
- int key; //key值,用于匹配控制指令的值
- int gpio_pin; //控制的gpio引脚
- int gpio_mode; //输入输出模式
- int gpio_status; //高低电平状态
- int check_face_status; //是否进行人脸检测状态
- int voice_set_status; //是否语音语音播报
- struct gdevice *next;
- };
-------------------------------------------
- CC := aarch64-linux-gnu-gcc
- # SRC -- 存放所有的 .c 文件
- SRC := $(shell find src -name "*.c")
- # INC -- 存放所有的 头文件 (包括自己写的 和 第三方)
- INC := ./inc \
- ./3rd/usr/local/include \
- ./3rd/usr/include \
- ./3rd/usr/include/python3.10 \
- ./3rd/usr/include/aarch64-linux-gnu/python3.10 \
- ./3rd/usr/include/aarch64-linux-gnu
-
- # 把需要包含的 .c 文件,替换为.o 文件
- OBJ := $(subst src/,obj/,$(SRC:.c=.o))
-
-
- # 创建目标 , 并且指定存放位置
- TARGET = obj/smarthome
-
- # -I./inc -- 存放头文件路径
- CFLAGS := $(foreach item,$(INC),-I$(item))
-
-
- # -I 指定的 第三方 库文件路径
- LIBS_PATH := ./3rd/usr/local/lib \
- ./3rd/lib/aarch64-linux-gnu \
- ./3rd/usr/lib/aarch64-linux-gnu \
- ./3rd/usr/lib/python3.10 \
-
-
-
- # -L ./3rd/usr/local/LIBS
- LDFLAGS := $(foreach item,$(LIBS_PATH),-L$(item))
-
- # 指定我们要链接的库
- LIBS := -lwiringPi -lpython3.10 -pthread -lexpat -lz -lcrypt
-
-
- # 生成obj文件夹,里面包含源文件对应的.o文件
- obj/%.o:src/%.c
- mkdir -p obj
- $(CC) -o $@ -c $< $(CFLAGS)
-
- # 一来obj 下面的.o文件 编译
- $(TARGET) : $(OBJ)
- $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
-
- compile : $(TARGET)
-
- clean:
- rm $(TARGET) obj &(OBJ) -rf
-
- debug:
- echo $(CC)
- echo $(SRC)
- echo $(INC)
- echo $(OBJ)
- echo $(TARGET)
- echo $(CFLAGS)
- echo $(LDFLAGS)
- echo $(LIBS)
-
-
- .PHONY: clean compile debug

============================
- #include <stdio.h>
- #include <pthread.h>
- #include <stdlib.h>
-
- #include "control.h"
- #include "mq_queue.h"
- #include "voice_interface.h"
- #include "global.h"
-
- // msg_queue_create
-
-
-
- int main() {
- pthread_t thread_id;
- struct control *control_phead = NULL;
- struct control *pointer = NULL;
- ctrl_info_t *ctrl_info = NULL;
- ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));
- ctrl_info->ctrl_phead = NULL;
- ctrl_info->mqd = -1;
-
- int node_num = 0; // 统计节点数
-
- // 创建消息队列
- ctrl_info->mqd = msg_queue_create();
- if(-1 == ctrl_info->mqd)// 创建消息队列失败
- {
- printf("%s|%s|%d, mqd= %d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);
- return -1;
- }
-
- ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
- //ctrl_info->ctrl_phead = add_socket_to_ctrl_list(ctrl_info->ctrl_phead);
- //ctrl_info->ctrl_phead = add_fire_to_ctrl_list(ctrl_info->ctrl_phead);
-
-
- pointer = ctrl_info->ctrl_phead;
-
- while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数
- {
- if(NULL != pointer->init)
- {
- pointer->init();
- }
- pointer = pointer->next;
- node_num++; // 统计节点数
- }
-
- // 根据节点的总数 --> 创建对应数目的线程
- pthread_t *tid = (pthread_t *)malloc(sizeof(int) *node_num);
- pointer = ctrl_info->ctrl_phead;
-
- for(int i=0;i<node_num;++i)
- {
- if(NULL != pointer->get)
- pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API
-
- }
-
- for(int i=0;i<node_num;++i)
- {
- pthread_join(tid[i],NULL);
- }
-
- for(int i=0;i<node_num;++i)
- {
- if(NULL != pointer->final)
- pointer->final(); // 接打开的使用接口关闭
- pointer = pointer->next;
- }
-
- msq_queue_final(ctrl_info->mqd);
-
- }

-
- #if 0
- struct control
- {
- char control_name[128]; //监听模块名称
- int (*init)(void); //初始化函数
- void (*final)(void);//结束释放函数
- void *(*get)(void *arg);//监听函数,如语音监听
- void *(*set)(void *arg); //设置函数,如语音播报
- struct control *next;
- };
- #endif
-
- #include <pthread.h>
- #include <stdio.h>
- #include "voice_interface.h"
- #include "mq_queue.h"
- #include "uartTool.h"
- #include "global.h"
-
-
- static int serial_fd = -1; // static 这个 变量只在当前文件有效
-
- static int voice_init(void )
- {
- serial_fd = myserialOpen(SERIAL_DEV,BAUD); // 初始化并且打开串口
- printf("%s|%s|%d serial_fd = %d\n",__FILE__,__func__,__LINE__,serial_fd);
-
- return serial_fd;
- }
-
- static void voice_final(void)
- {
- if(-1 != serial_fd) // 打开串口成功
- {
- close(serial_fd); // 关闭我们打开的串口
- serial_fd = -1; // 复位
- }
- }
- // 接收语言指令
- static void* voice_get(void *arg)// mqd 通过arg 传参获得
- {
- int len = 0;
- mqd_t mqd = -1;
- ctrl_info_t * ctrl_info = NULL;
- if(NULL != arg)
- ctrl_info = (ctrl_info_t*)arg;
-
- unsigned char buffer[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 初始化 buffer
- if (-1 == serial_fd)
- {
- //打开串口
- serial_fd = voice_init();// 尝试打开串口
- if (-1 == serial_fd){ //还是打开失败
- printf("%s | %s | %d:open serial failed\n", __FILE__, __func__, __LINE__); // 三个宏的含义: 文件名 - main.c,函数名 - pget_voice ,行号 - 138
- pthread_exit(0);
- } // 串口打开失败 -->退出
- }
-
-
- mqd = ctrl_info->mqd; //为实现
-
-
- if((mqd_t)-1 == mqd)
- {
- pthread_exit(0);
- }
-
- pthread_detach(pthread_self());// 与父线程分离
- printf("%s thread start\n",__func__);
-
- while (1)
- {
- len = serialGetstring(serial_fd, buffer); // 通过串口获得语言输入
- printf("%s|%s|%d, 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
- printf("%s|%s|%d:len = %d\n",__FILE__,__func__,__LINE__,len);
- if (len > 0) // 判断是否 接到识别指令
- {
- if(buffer[0] == 0xAA && buffer[1] == 0x55
- &&buffer[4]==0x55 && buffer[5]==0xAA)
- {
- printf("%s|%s|%d, send: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
-
- send_msg(mqd,buffer,len); // 注意获取len长度不能使用strlen() --> 0x00 会识别为截止位-->只能读取到三个字节(但不是我们实际的截止位(0x55 0xAA ))
- }
- memset(buffer,0,sizeof(buffer)); // 复位buffer
- }
- }
-
- pthread_exit(0);
-
- }
-
- static void* voice_set(void *arg)
- {
-
- }
-
- struct control voice_control ={
- .control_name = "voice",
- .init = voice_init,
- .final = voice_final,
- .get = voice_get,
- .set = voice_set,
- .next = NULL
- };
-
-
- struct control *add_voice_to_ctrl_list(struct control *phead)
- {
- //头插法实现 添加链表节点
- struct control *pnew = NULL;
-
-
- if(NULL == phead)
- {
- phead = &voice_control; // 直接传入我们的 voice_control
- }
-
- else// 头结点非空 - 链表有数据
- {
- voice_control.next = phead; //把新的节点的next指向头结点
- voice_control = *phead; // 让心节点成为头结点
- }
-
- return phead;
-
- };
-

// 注意我们的Makefile 里面指定了使用交叉编译工具链: aarch64-linux-gnu-gcc
所以我们生成的文件在×86上是没法运行的,需要scp 传送到arm-64的系统上,
比如我们的orangepi02
make complie
或者
make
scp obj/smarthome orangepi@192.168.1.11:/home/orangepi
切换到我们的香橙派上:
sudo -E ./smarthome
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。