增加/修改代码
在receive_interface.c里面 进一步实现了hanler_device 线程函数
hanler_device ()
// 这这个处理函数实现了:对客厅灯 和 卧室灯 风扇的语音控制
还实现了烟雾报警功能
static void *handler_device(void *arg)
{
pthread_detach(pthread_self()); // 和主线程(他的父线程)分离
recv_msg_t *recv_msg = NULL;
struct gdevice *cur_gdev = NULL;
char success_or_failed[20] = "success";
pthread_t tid = -1;
int smoke_status = 0;
int ret = -1;
if (NULL != arg) // 有参数
{
recv_msg = (recv_msg_t *)arg; // 获取参数
printf("recv_len = %d\n", recv_msg->msg_len);
printf("%s|%s|%d, handler: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", __FILE__, __func__, __LINE__,
recv_msg->buffer[0], recv_msg->buffer[1], recv_msg->buffer[2], recv_msg->buffer[3], recv_msg->buffer[4], recv_msg->buffer[5]);
}
// need to do something
if (NULL != recv_msg && NULL != recv_msg->buffer) // if 消息队列非空,并且buffer 里面接收到数据
{
// recv_msg->buffer[2] --> 第三位 用于存放设备类型
cur_gdev = find_device_by_key(pdevhead, recv_msg->buffer[2]);
printf("%s|%s|%d,find success buffer[2] = 0x%x \n", __FILE__, __func__, __LINE__, recv_msg->buffer[2]);
}
if (NULL != cur_gdev) // if 能找到的这设备 --> 设备存在
{
printf("%s|%s|%d, cur_gdev \n", __FILE__, __func__, __LINE__);
// BUFFER 的第四个参数 用于 存放开关状态 0 表示开, 1 表示关
cur_gdev->gpio_status = recv_msg->buffer[3] == 0 ? LOW : HIGH; // 获取状态存入cur_gdev中
// printf("%s|%s|%d,Set before set_gpio_device_status\n",__FILE__,__func__,__LINE__);
ret = set_gpio_device_status(cur_gdev); // 将获取到的状态真正赋值给引脚
// printf("%s|%s|%d, after set_gpio_device_status \n",__FILE__,__func__,__LINE__);
// printf("%s|%s|%d,Set success status = %d\n",__FILE__,__func__,__LINE__,cur_gdev->gpio_status);
printf("%s|%s|%d, = %d\n", __FILE__, __func__, __LINE__,cur_gdev->voice_set_status);
if (1 == cur_gdev->voice_set_status) // 需要语言播报
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
if (NULL != recv_msg && NULL != recv_msg->ctrl_info && NULL != recv_msg->ctrl_info->ctrl_phead)
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
struct control *pcontrol = recv_msg->ctrl_info->ctrl_phead;
while (NULL != pcontrol)
{
if (strstr(pcontrol->control_name, "voice"))
{
if (0x45 == recv_msg->buffer[2] && 0 == recv_msg->buffer[3]) // 语音播报 打开
{
smoke_status = 1;
pthread_create(&tid, NULL, pcontrol->set, (void *)recv_msg->buffer);
break;
}
}
pcontrol = pcontrol->next;
}
}
}
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
if (-1 == ret) // 设置失败
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
memset(success_or_failed, '\0', sizeof(success_or_failed));
strncpy(success_or_failed, "failed", 6);
}
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
// 配置OLED
char oled_msg[512];
memset(oled_msg, 0, sizeof(oled_msg));
char *change_status = cur_gdev->gpio_status == LOW ? "Open" : "Close";
sprintf(oled_msg, "%s %s %s!\n", change_status, cur_gdev->dev_name, success_or_failed);
if(smoke_status == 1)
{
memset(oled_msg, 0, sizeof(oled_msg));
sprintf(oled_msg, "A risk of fire!\n");
}
myoled_show(oled_msg);
}
pthread_exit(0);
}
receive_interface.c
//就是实现了什么这个函数,放在这里方便理解
static void *handler_device(void *arg)
{
pthread_detach(pthread_self()); // 和主线程(他的父线程)分离
recv_msg_t *recv_msg = NULL;
struct gdevice *cur_gdev = NULL;
char success_or_failed[20] = "success";
pthread_t tid = -1;
int smoke_status = 0;
int ret = -1;
if (NULL != arg) // 有参数
{
recv_msg = (recv_msg_t *)arg; // 获取参数
printf("recv_len = %d\n", recv_msg->msg_len);
printf("%s|%s|%d, handler: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", __FILE__, __func__, __LINE__,
recv_msg->buffer[0], recv_msg->buffer[1], recv_msg->buffer[2], recv_msg->buffer[3], recv_msg->buffer[4], recv_msg->buffer[5]);
}
// need to do something
if (NULL != recv_msg && NULL != recv_msg->buffer) // if 消息队列非空,并且buffer 里面接收到数据
{
// recv_msg->buffer[2] --> 第三位 用于存放设备类型
cur_gdev = find_device_by_key(pdevhead, recv_msg->buffer[2]);
printf("%s|%s|%d,find success buffer[2] = 0x%x \n", __FILE__, __func__, __LINE__, recv_msg->buffer[2]);
}
if (NULL != cur_gdev) // if 能找到的这设备 --> 设备存在
{
printf("%s|%s|%d, cur_gdev \n", __FILE__, __func__, __LINE__);
// BUFFER 的第四个参数 用于 存放开关状态 0 表示开, 1 表示关
cur_gdev->gpio_status = recv_msg->buffer[3] == 0 ? LOW : HIGH; // 获取状态存入cur_gdev中
// printf("%s|%s|%d,Set before set_gpio_device_status\n",__FILE__,__func__,__LINE__);
ret = set_gpio_device_status(cur_gdev); // 将获取到的状态真正赋值给引脚
// printf("%s|%s|%d, after set_gpio_device_status \n",__FILE__,__func__,__LINE__);
// printf("%s|%s|%d,Set success status = %d\n",__FILE__,__func__,__LINE__,cur_gdev->gpio_status);
printf("%s|%s|%d, = %d\n", __FILE__, __func__, __LINE__,cur_gdev->voice_set_status);
if (1 == cur_gdev->voice_set_status) // 需要语言播报
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
if (NULL != recv_msg && NULL != recv_msg->ctrl_info && NULL != recv_msg->ctrl_info->ctrl_phead)
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
struct control *pcontrol = recv_msg->ctrl_info->ctrl_phead;
while (NULL != pcontrol)
{
if (strstr(pcontrol->control_name, "voice"))
{
if (0x45 == recv_msg->buffer[2] && 0 == recv_msg->buffer[3]) // 语音播报 打开
{
smoke_status = 1;
pthread_create(&tid, NULL, pcontrol->set, (void *)recv_msg->buffer);
break;
}
}
pcontrol = pcontrol->next;
}
}
}
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
if (-1 == ret) // 设置失败
{
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
memset(success_or_failed, '\0', sizeof(success_or_failed));
strncpy(success_or_failed, "failed", 6);
}
printf("%s|%s|%d,2\n", __FILE__, __func__, __LINE__);
// 配置OLED
char oled_msg[512];
memset(oled_msg, 0, sizeof(oled_msg));
char *change_status = cur_gdev->gpio_status == LOW ? "Open" : "Close";
sprintf(oled_msg, "%s %s %s!\n", change_status, cur_gdev->dev_name, success_or_failed);
if(smoke_status == 1)
{
memset(oled_msg, 0, sizeof(oled_msg));
sprintf(oled_msg, "A risk of fire!\n");
}
myoled_show(oled_msg);
}
pthread_exit(0);
}
添加设备
设备模版
struct gdevice
{
char dev_name[128]; //设备名称
int key; //key值,用于匹配控制指令的值
int gpio_pin; //控制的gpio引脚 6,7,8,9
int gpio_mode; //输入输出模式 INPUT OUTPUT -1
int gpio_status; //高低电平状态 LOW HIGH -1
int check_face_status; //是否进行人脸检测状态
int voice_set_status; //是否语音语音播报
struct gdevice *next;
};
gdevice.h
#include <stdio.h>
#include <wiringPi.h>
#ifndef __GDEVICE_H__
#define __GDEVICE_H__
struct gdevice
{
char dev_name[128]; //设备名称
int key; //key值,用于匹配控制指令的值
int gpio_pin; //控制的gpio引脚 6,7,8,9
int gpio_mode; //输入输出模式 INPUT OUTPUT -1
int gpio_status; //高低电平状态 LOW HIGH -1
int check_face_status; //是否进行人脸检测状态
int voice_set_status; //是否语音语音播报
struct gdevice *next;
};
//向设备列表中 添加 设备
struct gdevice *add_device_to_gdevice_list(struct gdevice *pgdevhead, struct gdevice *gdev);
// 在设备链表中找到设备 -- 根据 key 值去匹配 --> buffer[2] -- 控制设置号 buffer[3]--对应设备状态
struct gdevice *find_device_by_key(struct gdevice *pgdevhead, int key);
int set_gpio_device_status(struct gdevice *pgdev);
#endif
gdevice.c
#include "gdevice.h"
struct gdevice *add_device_to_gdevice_list(struct gdevice *pgdevhead, struct gdevice *gdev)
{
if (NULL == pgdevhead)
{
pgdevhead = gdev; // 直接传入我们的 voice_control
}
else // 头结点非空 - 链表有数据
{
gdev->next = pgdevhead; // 把新的节点的next指向头结点
pgdevhead = gdev; // 让心节点成为头结点
}
return pgdevhead;
}
// 有点写的个性化
struct gdevice *find_device_by_key(struct gdevice *pgdevhead, int key)
{
struct gdevice *p = NULL;
printf("%s|%s|%d, cur_gdev1 \n", __FILE__, __func__, __LINE__);
if (NULL != pgdevhead) // 链表非空就去查找
{
printf("%s|%s|%d, cur_gdev2\n", __FILE__, __func__, __LINE__);
p = pgdevhead;
while (NULL != p)
{
printf("%s|%s|%d, key =%x p->key = %x\n", __FILE__, __func__, __LINE__,key,p->key);
if (key == p->key){
return p; // 找到 就返回
printf("%s|%s|%d, cur_gdev2\n", __FILE__, __func__, __LINE__);
}
p = p->next;
}
}
return NULL; // 返回空 --> 链表为空 or 查找失败
}
int set_gpio_device_status(struct gdevice *pgdev)
{
printf("%s|%s|%d,begin set_gpio_device_status\n",__FILE__,__func__,__LINE__);
if(NULL == pgdev)
{
return -1;
}
if(-1 != pgdev->gpio_pin) // 如果引脚没有配置
{
if(-1 != pgdev->gpio_mode) // 如果引脚模式没有配置 -- 就去配置
{
printf("%s|%s|%d,before pinMode\n",__FILE__,__func__,__LINE__);
pinMode(pgdev->gpio_pin,pgdev->gpio_mode);// 配置引脚的输入输出
printf("%s|%s|%d,after pinMode\n",__FILE__,__func__,__LINE__);
}
if(-1 != pgdev->gpio_status)// 如果引脚状态没有配置 -- 就去配置
{
printf("%s|%s|%d,before digitalWrite\n",__FILE__,__func__,__LINE__);
digitalWrite(pgdev->gpio_pin,pgdev->gpio_status); // 配置为输出的时候,输出的电平
printf("%s|%s|%d,after digitalWrite\n",__FILE__,__func__,__LINE__);
}
}
return 0;
}
真正的设备
卧室灯
bled_gdevice.h
#ifndef __BLED_GDEVICE_H
#define __BLED_GDEVICE_H
struct gdevice *add_bled_to_gdevice_list(struct gdevice *pgdevhead);
#endif
bled_gdevice.c
#include "gdevice.h"
struct gdevice bled_gdev = {
.dev_name = "BR led",
.key = 0x42,
.gpio_pin = 5,
.gpio_mode = OUTPUT,
.gpio_status = HIGH,
.check_face_status = 0,
.voice_set_status = 0,
};
struct gdevice *add_bled_to_gdevice_list(struct gdevice *pgdevhead)
{ // 头插法
return add_device_to_gdevice_list(pgdevhead, &bled_gdev);
};
客厅灯
lrled_gdevice.h
#ifndef __LRLED_GDEVICE_H
#define __LRLED_GDEVICE_H
struct gdevice *add_lrled_to_gdevice_list(struct gdevice *pgdevhead);
#endif
lrled_gdevice.c
#include "gdevice.h"
struct gdevice lrled_gdev = {
.dev_name = "LV led",
.key = 0x41,
.gpio_pin = 2,
.gpio_mode = OUTPUT,
.gpio_status = HIGH,
.check_face_status = 0,
.voice_set_status = 0,
};
struct gdevice *add_lrled_to_gdevice_list(struct gdevice *pgdevhead)
{ // 头插法
return add_device_to_gdevice_list(pgdevhead, &lrled_gdev);
};
风扇
fan_gdevice.h
#ifndef __FAN_GDEVICE_H
#define __FAN_GDEVICE_H
struct gdevice *add_fan_to_gdevice_list(struct gdevice *pgdevhead);
#endif
fan_gdevice.c
#include "gdevice.h"
struct gdevice gdevice_fan = {
.dev_name = "fan",
.key = 0x43,
.gpio_pin = 7,
.gpio_mode = OUTPUT,
.gpio_status = LOW,
.check_face_status = 0,
.voice_set_status = 0,
.next = NULL};
struct gdevice *add_fan_to_gdevice_list(struct gdevice *phead)
{
return add_device_to_gdevice_list(phead, &gdevice_fan);
}
蜂鸣器
beep_gdevice.h
#ifndef __BEEP_GDEVICE_H
#define __BEEP_GDEVICE_H
struct gdevice *add_beep_to_gdevice_list(struct gdevice *pgdevhead);
#endif
beep_gdevice.c
#include "gdevice.h"
struct gdevice beep_gdev = {
.dev_name = "beep",
.key = 0x45,
.gpio_pin = 9,
.gpio_mode = OUTPUT,
.gpio_status = HIGH,
.check_face_status = 0,
.voice_set_status = 1,
};
struct gdevice *add_beep_to_gdevice_list(struct gdevice *pgdevhead)
{//头插法
return add_device_to_gdevice_list(pgdevhead, &beep_gdev);
};
编译执行:
编译:
make
发送到arm-64平台 -- 优化
我们把 下面这句指令添加到Makefile 里面,这样 就make编译完成的时候就会进行传送,
不需要我们手动输入
scp ./obj/smarthome orangepi@192.168.1.11:/home/orangepi
修改后的Makefile
CC := aarch64-linux-gnu-gcc
SRC := $(shell find src -name "*.c")
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
OBJ := $(subst src/,obj/,$(SRC:.c=.o))
TARGET=obj/smarthome
CFLAGS := $(foreach item, $(INC),-I$(item)) # -I./inc -I./3rd/usr/local/include
LIBS_PATH := ./3rd/usr/local/lib \
./3rd/lib/aarch64-linux-gnu \
./3rd/usr/lib/aarch64-linux-gnu \
./3rd/usr/lib/python3.10 \
#L
LDFLAGS := $(foreach item, $(LIBS_PATH),-L$(item)) # -L./3rd/usr/local/libs
LIBS := -lwiringPi -lpython3.10 -pthread -lexpat -lz -lcrypt
obj/%.o:src/%.c
mkdir -p obj
$(CC) -o $@ -c $< $(CFLAGS)
$(TARGET) :$(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
scp obj/smarthome orangepi@192.168.1.18:/home/orangepi
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
执行:
sudo -E ./smarthome
1632

被折叠的 条评论
为什么被折叠?



