这一模块的思路和前面的语言控制模块很相似,差别只是调用TCP 去控制
废话少说,放码过来
增添/修改代码
smoke_interface.c
#include <pthread.h>
#include <wiringPi.h>
#include <stdio.h>
#include "smoke_interface.h"
#include "control.h"
#include "mq_queue.h"
#include "global.h"
#include <netinet/tcp.h> // 设置 tcp 心跳 的参数
#define SMOKE_PIN 6 // 烟雾报警模块接的引脚
#define SMOKE_MODE INPUT
static int s_fd = -1;
static int smoke_init(void)
{
printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
pinMode(SMOKE_PIN, SMOKE_MODE); // 引脚 和 模式配置
return 0;
}
static void smoke_final(void)
{
// do nothing
}
static void* smoke_get(void *arg)
{
// AA 55 45 00 55 AA --> 45 00 -->触发警报
int status = HIGH; //低电平有效 -- 默认设置为高电平
int switch_status = 0; // 报警开关 -- 默认设置为不开 -- 0
ssize_t byte_send = -1;
unsigned char buffer[6] = {0xAA,0x55,0x00,0x00,0x55,0xAA};
mqd_t mqd = -1;
ctrl_info_t * ctrl_info = NULL;
if(NULL != arg)
ctrl_info = (ctrl_info_t*)arg;
if(NULL != ctrl_info)
mqd = ctrl_info->mqd;
if((mqd_t)-1 == mqd)
{
pthread_exit(0);
}
pthread_detach(pthread_self()); // 父子线程分离
printf("%s thread start.\n",__func__);
while(1)
{
status = digitalRead(SMOKE_PIN); // 读取当前引脚状态
if(LOW == status) // 探测到烟雾 -- 发生报警
{
switch_status = 1; // 打开报警器开关
buffer[2] = 0x45;
buffer[3] = 0x00;// 低电平触发警报 --
//蜂鸣器是低电平触发 --> 我们这里把buffer 修改得与beep匹配,方便与他产生联系
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]);
byte_send = mq_send(mqd, buffer, 6,0); // 向消息队列里面发送数据 -- 接收到后语言模块会识别播报 - 火灾警报
if (-1 == byte_send)
{
continue;
}
}
else if(HIGH == status && 1 == switch_status) // 未探测到烟雾,并且报警器开关还没关闭 -- 关闭报警器开关
{
switch_status = 0; // 关闭报警器开关
buffer[2] = 0x45;
buffer[3] = 0x01;//警报结束
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]);
byte_send = mq_send(mqd, buffer, 6,0);
if (-1 == byte_send)
{
continue;
}
}
sleep(5);
}
pthread_exit(0); // 退出线程
}
struct control smoke_control ={
.control_name = "smoke",
.init = smoke_init,
.final = smoke_final,
.get = smoke_get,
.set = NULL, //不需要实现 设置
.next = NULL
};
struct control *add_smoke_to_ctrl_list(struct control *phead)
{
return add_interface_to_ctrl_list(phead,&smoke_control);
}
smoke_interface.h
#ifndef ___SMOKE_INTERFACE_H___
#define ___SMOKE_INTERFACE_H___
#include "control.h"
struct control *add_smoke_to_ctrl_list(struct control *phead);
#endif
修改的main.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <wiringPi.h>
#include "control.h"
#include "mq_queue.h"
#include "voice_interface.h"
#include "socket_interface.h"
#include "smoke_interface.h"
#include "receive_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; // 统计节点数
if(-1 == wiringPiSetup())// 初始化 wiringPi 库
{
perror("wiringPi Init");
return -1;
}
// 创建消息队列
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;
}
// 头插法插入 , so 头一直在变化
ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);
ctrl_info->ctrl_phead = add_smoke_to_ctrl_list(ctrl_info->ctrl_phead);
ctrl_info->ctrl_phead = add_receive_to_ctrl_list(ctrl_info->ctrl_phead);
pointer = ctrl_info->ctrl_phead;
while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数
{
if(NULL != pointer->init)
{
printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
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){
printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API
}
pointer = pointer->next;
}
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(NULL != ctrl_info)
free(ctrl_info); // 这个是malloc 堆区申请的内存 --> 需要手动的释放
if(NULL != tid)
free(tid);
return 0;
}
编译执行:
编译:
make
发送到arm-64平台
scp ./obj/smarthome orangepi@192.168.1.11:/home/orangepi
// 需要用到阿里云人脸识别接口,需要调用 py文件,一起传过去
scp src/face.py orangepi@192.168.1.11:/home/orangepi
执行:
sudo -E ./smarthome