智能家居5 - 实现处理线程

增加/修改代码

在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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值