基于orangePi的智能家居系统

news2024/9/19 9:43:07

目录

 一.接线图

1.orangePi接线

2.继电器接线 

二.语音模块的配置

1.pin脚的配置

2.命令词自定义信息

 三.测试

1.通过gpio指令测试烟雾检测器是否正确连接

2.编写脚本测试其他模组接线是否正常

四.人脸识别方案

1.首先开通人脸搜索识别服务

2. 点击产品控制台,向人脸数据库中添加人脸样本数据

3.去香橙派终端执行此命令,下载阿里云SDK包

4.下载完成后,配置环境变量

5.切换至下列目录,点击人脸搜索示例代码

6.封装python代码为一个函数,并且取返回结果中最大的score值作为最终比对结果

7.C语言调用python阿里云接口

五.POSIX消息队列

1.基本API用法

 2. mq_notiy函数的使用

六.智能家居的实现

1.项目的整体框架大致如下:

2.整个项目开启4个监听线程,分别是:

3.项目结构大致如下

3.1首先,从香橙派上利用apt download下载依赖包的头文件和库文件,并拷贝到宿主机里:

3.2解压到/home/mi/Desktop/smarthome/3rd/下

3.3编写Makefile

3.4智能家居具体代码实现

face.py

face.c

face.h

msg_queue.c

msg_queue.h

myoled.c

myoled.h

socket.c

socket.h

control.c

control.h

gdevice.c

gdevice.h

global.h

voice_interface.c

voice_interface.h

smoke_interface.c

smoke_interface.h

socket_interface.c

socket_interface.h

receive_interface.c

receive_interface.h

4.inih解析库介绍

定义设备控制ini文件gdevice.ini

5.Makefile文件编写


 一.接线图

1.orangePi接线

2.继电器接线 

二.语音模块的配置

进入语音模块官网  http://www.smartpi.cn/#/  ,配置词条和识别后的串口输出指令。

1.pin脚的配置


2.命令词自定义信息

 三.测试

1.通过gpio指令测试烟雾检测器是否正确连接

sudo gpio mode 6 input   设置引脚6为输入状态

sudo gpio readall              查看引脚6为高电压(此时无烟)

sudo gpio readall              查看引脚6为变为了低电压(此时有烟)

2.编写脚本测试其他模组接线是否正常

gpio mode 2 out #卧室灯
gpio mode 5 out #课厅灯
gpio mode 7 out #电磁锁
gpio mode 8 out #风扇
gpio mode 9 out #蜂鸣器

#全部拉高,继电器断开
for i in 2 5 7 8 9
do
    gpio write $i 1
done

for i in 2 5 7 8 9
do
    gpio write $i 0
    sleep 3
    gpio write $i 1
done

四.人脸识别方案

这里采用的是阿里云的人脸识别方案通义实验室视觉智能开放平台

1.首先开通人脸搜索识别服务

2. 点击产品控制台,向人脸数据库中添加人脸样本数据

3.去香橙派终端执行此命令,下载阿里云SDK包

4.下载完成后,配置环境变量

~/.bashrc/etc/profile 的末尾输入下面俩行(替换为你自己的阿里云AccessKey)

export ALIBABA_CLOUD_ACCESS_KEY_ID=<access_key_id> 
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<access_key_secret>

5.切换至下列目录,点击人脸搜索示例代码

 

# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_facebody20191230

import os
from alibabacloud_facebody20191230.models import SearchFaceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_facebody20191230.client import Client
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
    # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
    # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html。
    # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
    access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
    access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
    # 访问的域名
    endpoint='facebody.cn-shanghai.aliyuncs.com',
    # 访问的域名对应的region
    region_id='cn-shanghai'
)
runtime_option = RuntimeOptions()
search_face_request = SearchFaceRequest(
  db_name='Face1',
    image_url='http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/SearchFace/SearchFace1.png',
    limit=2
)
try:
  # 初始化Client
  client = Client(config)
  response = client.search_face_with_options(search_face_request, runtime_option)
  # 获取整体结果
  print(response.body)
except Exception as error:
  # 获取整体报错信息
  print(error)
  # 获取单个字段
  print(error.code)
  # tips: 可通过error.__dict__查看属性名称

6.封装python代码为一个函数,并且取返回结果中最大的score值作为最终比对结果

# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_facebody20191230
# face.py

import os
import io
from urllib.request import urlopen
from alibabacloud_facebody20191230.client import Client
from alibabacloud_facebody20191230.models import SearchFaceAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
    # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
    # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html。
    # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
    access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
    access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
    # 访问的域名
    endpoint='facebody.cn-shanghai.aliyuncs.com',
    # 访问的域名对应的region
    region_id='cn-shanghai'
)

def alibaba_face():
  search_face_request = SearchFaceAdvanceRequest()
  # 场景一:文件在本地
  stream0 = open(r'/tmp/SearchFace.jpg', 'rb')
  search_face_request.image_url_object = stream0

  #场景二:使用任意可访问的url
  #url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/facebody/SearchFace1.png'
  #img = urlopen(url).read()
  #search_face_request.image_url_object = io.BytesIO(img)

  # 阿里云人脸数据库的名称为'default'
  search_face_request.db_name = 'default'
  search_face_request.limit = 5

  runtime_option = RuntimeOptions()

  try:
    # 初始化Client
    client = Client(config)
    response = client.search_face_advance(search_face_request, runtime_option)
    print(response.body)
    match_list = response.body.to_map()['Data']['MatchList']
    Scores = [item['Score'] for item in match_list[0]['FaceItems']] #set集合,无序不重复的数据集合
    max_score = max(Scores)
    # 获取整体结果
    value = round(max_score, 2)
    return value
  except Exception as error:
    # 获取整体报错信息
    print(error)
    # 获取单个字段
    print(error.code)
    return 0.0
    # tips: 可通过error.__dict__查看属性名称

  #关闭流
  #stream0.close()

if __name__ == "__main__":
  alibaba_face()

运行结果

7.C语言调用python阿里云接口

 face.c

#include <Python.h>

#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/SearchFace.jpg"
#define SEARCHFACE_FILE "/tmp/SearchFace.jpg"

void face_init(void){
	// 初始化Python解释器
    Py_Initialize(); 
    // 导入 sys 模块
    PyObject *sys = PyImport_ImportModule("sys");
    // 获取 sys 模块的 path 属性
    PyObject *path = PyObject_GetAttrString(sys, "path");
    // 将当前路径添加到 sys.path 中
    PyList_Append(path, PyUnicode_FromString("."));
    Py_DECREF(sys);  // 释放 sys 引用
    Py_DECREF(path); // 释放 path 引用
}

void face_final(void){
    // 关闭Python解释器
    Py_Finalize();
}

double face_category(void)
{
	double result = 0.0;
	// A.使用 wget 命令从本地服务器下载一张快照图片
 	system(WGET_CMD);
	// B.检查刚才下载的图片文件是否存在
    if (0 != access(SEARCHFACE_FILE, F_OK))
    {
		return result;
	}
	// C.导入 Python 模块
	PyObject *pModule = PyImport_ImportModule("face"); //face.py 
	if (!pModule)
	{
		PyErr_Print(); // 如果导入失败,使用 PyErr_Print() 打印错误信息
		printf("Error: failed to load face.py\n");
		goto FAILED_MODULE; // 通过 goto 跳转到 FAILED_MODULE 标签,进行清理工作并退出
	}

	// D.从模块中获取 alibaba_face 函数
	PyObject *pFunc = PyObject_GetAttrString(pModule, "alibaba_face");
	if (!pFunc)
    {
        PyErr_Print(); // 如果导入失败,使用 PyErr_Print() 打印错误信息
        printf("Error: failed to load alibaba_face\n");
		goto FAILED_FUNC; // 通过 goto 跳转到 FAILED_FUNC 标签,进行清理工作并退出
    }

	// E.调用alibaba_face函数
	PyObject *pValue = PyObject_CallObject(pFunc, NULL); 
	if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
		goto FAILED_VALUE;
    }

	// F.解析调用alibaba_face函数的返回值,转行成c语言格式
	if (!PyArg_Parse(pValue, "d", &result)) 
	{
		PyErr_Print();
		printf("Error: parse failed");
		goto FAILED_VALUE;
	}

	printf("result=%0.2lf\n", result);

FAILED_VALUE:
	Py_DECREF(pValue);
FAILED_FUNC:
	Py_DECREF(pFunc);
FAILED_MODULE:
	Py_DECREF(pModule);
	
	return result;
}

五.POSIX消息队列

1.基本API用法

#include <mqueue.h>
//创建或打开消息队列
mqd_t mq_open(const char *name, int oflag,mode_t mode, struct mq_attr attr ); 
//关闭消息队列
int mq_close(mqd_t mqdes);  
//删除消息队列                                                  
int mq_unlink(const char *name);      
//发送消息                                        
int mq_send(mqd_t mqdes, const char *ptr, size_tlen, unsigned int prio);      
//接受消息
ssize_t mq_receive(mqd_t mqdes, char *ptr, size_tlen, unsigned int *prio);    

//消息队列的属性
struct mq_attr{
    long mq_flags;//阻塞标志,0(阻塞)或O_NONBLOCK
    long mq_maxmsg;//最大消息数
    long mq_msgsize;//每个消息最大大小
    long mq_curmsgs;//当前消息数
};
#endif
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

// 消息队列的名字
#define QUEUE_NAME "/test_queue"
// 要发送的消息
#define MESSAGE "hello,world"

void *sender_thread(void *arg) {
    sleep(10);
    mqd_t mqd = *(mqd_t *)arg;
    // 发送消息
    char message[] = MESSAGE;
    printf("sender_thread message is: %s, mqd = %d\n", message, (int)mqd);

    if (mq_send(mqd, message, strlen(message) + 1, 0) == -1) {
        switch (errno) {
            case EAGAIN:
                // 消息队列已满,且设置了 O_NONBLOCK 标志
                printf("Error: The message queue is full.\n");
                break;
            case EBADF:
                // 描述符无效或未打开为写
                printf("Error: Invalid message queue descriptor or not open for writing.\n");
                break;
        }
        perror("mq_send");
    } else {
        // 消息发送成功的处理
        printf("Message sent successfully.\n");
    }

    return NULL;
}

void *receiver_thread(void *arg) {
    sleep(10);
    // 获取消息队列描述符
    mqd_t mqd = *(mqd_t *)arg;
    // 定义合理大小的消息缓冲区
    char message[256];
    // 接受消息
    ssize_t size = mq_receive(mqd, message, sizeof(message), NULL);
    // 错误检查
    if (size >= 0) {
        printf("Message receive successfully.\n");
        printf("receiver_thread message is: %s, size is: %zd, mqd = %d\n", message, size, (int)mqd);
    } else {
    // 根据错误码进行不同的处理
        switch (errno) {
            case EAGAIN: //消息队列已经满
                fprintf(stderr, "mq_receive error: The queue is empty and O_NONBLOCK was set.\n");
                break;
            case EBADF: //检查mqd是否成功打开
                fprintf(stderr, "mq_receive error: Invalid descriptor or not opened for reading.\n");
                break;
        }
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    pthread_t sender, receiver;
    mqd_t mqd = -1;
    struct mq_attr attr = {0}; // 初始化结构体

    attr.mq_flags = 0; // 阻塞模式
    attr.mq_maxmsg = 10; // 最大消息数为10条
    attr.mq_msgsize = 256; // 每个消息的最大大小
    attr.mq_curmsgs = 0; // 当前消息数

    // 创建消息队列
    mqd = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0666, &attr);
    if (mqd == (mqd_t)-1) {
        perror("mq_open");
        return -1;
    }

    // 创建线程
    if (pthread_create(&sender, NULL, sender_thread, (void *)&mqd) != 0) {
        perror("Create sender_thread failed!\n");
        return -1;
    }
    if (pthread_create(&receiver, NULL, receiver_thread, (void *)&mqd) != 0) {
        perror("Create receiver_thread failed!\n");
        return -1;
    }

    // 线程等待
    pthread_join(sender, NULL);
    pthread_join(receiver, NULL);

    // 关闭消息队列
    mq_close(mqd);
    // 删除消息队列
    mq_unlink(QUEUE_NAME);

    return 0;
}

运行后,可通过ls -al /dev/mqueue/查看系统中含有哪些消息队列

<

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2113610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【重学 MySQL】十五、过滤数据

【重学 MySQL】十五、过滤数据 基本用法使用AND、OR和NOT使用IN操作符使用BETWEEN操作符使用LIKE操作符使用IS NULL和IS NOT NULL 在MySQL中&#xff0c;过滤数据主要通过WHERE子句来实现。WHERE子句允许你指定条件来过滤从表中检索出来的行。只有当行满足WHERE子句中的条件时&…

个人随想-一个有意思的鼠标截屏RAG

multi-model rag现在的技术已经比较成熟了&#xff0c;我们也落地了很多公司的rag和agent项目。今天先不说项目落地&#xff0c;今天给大家分享一个有意思的需求。 广州的一家公司&#xff0c;当我们rag搭建完成后&#xff0c;他们的一个产品经理提了一个需求。他们说&#xf…

C#转java工具

使用 激活 点击关闭即可 参考文献 https://www.cnblogs.com/liyhbk/p/17358520.html

【视频教程】手把手AppWizard轻松制作一个emWin滑动主界面控制框架,任意跳转控制(2024-09-06)

现在的新版AppWizard已经比较好用&#xff0c;用户可以轻松的创建各种项目常规界面。 比如早期创建一个支持滑动的主界面框架&#xff0c;并且可以跳转各种子界面&#xff0c;仅仅界面布局和各种图片格式转换都要花不少时间&#xff0c;而现在使用AppWizard&#xff0c;可以说…

关键点检测(7)——yolov8-head的搭建

前两节我学习了yolov8的backbone和head操作。这一节就到了head部分。  我们知道yolov8在流行的yolov5的架构上进行了扩展。在多个方面提供了改进。尤其是head部分&#xff0c;变化最大。yolov8模型与其前身的主要区别在于使用了无锚点检测&#xff08;即从原先的耦合头变成了解…

无人机电调接线

接线方式&#xff1a; 电调的作用是将飞控板的PWM控制信号转变为电流信号 因为电机的电流是很大的&#xff0c;通常每个点击正常工作时都平均有3A左右的电流&#xff0c;如果没有电调的存在&#xff0c;飞控无法承受这么大的电流。 电调的选择&#xff1a;电调上标的电流值是…

240907-Gradio渲染装饰器Render-Decorator

A. 最终效果 B. 示例代码 import gradio as gr import gradio as grwith gr.Blocks() as demo:input_text gr.Textbox()gr.render(inputsinput_text)def show_split(text):if len(text) 0:gr.Markdown("## No Input Provided")else:# for letter in text:for lett…

精通Java微服务

第1章 微服务是在面向服务架构SOA的基础上进一步发展而来的&#xff0c;它比SOA做得更加彻底&#xff0c;其单体服务被更加彻底地划分&#xff0c;最大限度地实现了服务的单一职责。 1.1.2互联网 即计算机网络&#xff0c;连接了世界上数以万计的计算机设备&#xff08;可联…

ROADM(可重构光分插复用器)-介绍

1. 引用 https://zhuanlan.zhihu.com/p/163369296 https://zhuanlan.zhihu.com/p/521352954 https://zhuanlan.zhihu.com/p/91103069 https://zhuanlan.zhihu.com/p/50610236 术语&#xff1a; 英文缩写描述灰光模块彩光模块CWDM&#xff1a;Coarse Wave-Length Division …

1233333333333

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

【JVM】JVM栈帧中的动态链接 与 Java的面向对象特性--多态

栈帧 每一次方法调用都会有一个对应的栈帧被压入栈&#xff08;虚拟机栈&#xff09;中&#xff0c;每一个方法调用结束后&#xff0c;都会有一个栈帧被弹出。 每个栈帧中包括&#xff1a;局部变量表、操作数栈、动态链接、方法返回地址。 JavaGuide&#xff1a;Java内存区域…

STM32CubeMX和HAL库

目录 STM32CubeMX和HAL库介绍 STM32Cube主要包括两部分 安装MCU固件包 软件功能与基本使用 STM32CubeMX和HAL库介绍 STM32CubeMX软件是ST有限公司为STM32系列微控制器快速建立工程&#xff0c;并快速初始化使用到的外设、GPIO等而设计的&#xff0c;大大缩短了开发时间。 同…

【面试八股总结】MySQL日志:undo log、redo log、binlog

MySQL中存在三种日志&#xff1a; undo log&#xff08;回滚日志&#xff09;&#xff1a;是 Innodb 存储引擎层生成的日志&#xff0c;实现了事务中的原子性&#xff0c;主要用于事务回滚和 MVCC。redo log&#xff08;重做日志&#xff09;&#xff1a;是 Innodb 存储引擎层…

服务网关工作原理,如何获取用户真实IP?

文章目录 一、什么是网关二、网关工作原理 (★)三、SpringCloud Gateway3.1 Gateway 简介3.2 Gateway 环境搭建3.3 自定义路由规则 (★)3.4 局部过滤器3.5 全局过滤器&#xff08;案例&#xff1a;获取用户真实IP地址&#xff09; (★) 补充1&#xff1a;不同类型的客户端如何设…

MapSet之相关概念

系列文章&#xff1a; 1. 先导片--Map&Set之二叉搜索树 2. Map&Set之相关概念 目录 1.搜索 1.1 概念和场景 1.2 模型 2.Map的使用 2.1 关于Map的说明 2.2 关于Map.Entry的说明 2.3 Map的常用方法说明 3.Set的说明 3.1关于Set说明 3.2 常见方法说明 1.搜…

CTFHub技能树-Git泄漏-Index

目录 一、Git索引&#xff08;Index&#xff09;的基本概念 二、解题过程 主旨&#xff1a;使用git泄漏恢复源代码 方法一&#xff1a;使用GitHack手动恢复 方法二&#xff1a;直接使用Git_Extract获取网站源代码拿去flag 当前大量开发人员使用git进行版本控制&#xff0c…

图神经网络(2)预备知识

1. 图的基本概念 对于接触过数据结构和算法的读者来说&#xff0c;图并不是一个陌生的概念。一个图由一些顶点也称为节点和连接这些顶点的边组成。给定一个图G(V,E), 其 中V{V1,V2,…,Vn} 是一个具有 n 个顶点的集合。 1.1邻接矩阵 我们用邻接矩阵A∈Rnn表示顶点之间的连接关…

初识Linux · 有关gdb

目录 前言&#xff1a; 1 预备知识 2 gdb的使用 前言&#xff1a; 当我们Linux学到了这里的时候&#xff0c;我们大概会有一种感觉是&#xff0c;从VS2022转战Linux&#xff0c;写代码对我们来说是一种重新构建读写代码的一个过程&#xff0c;从文本编辑器&#xff0c;到文…

怎样将手机屏幕(远程)投屏到家里的大电视上?

我不住家里&#xff0c;前几次回去都会替老爸老妈清理手机。这两个星期没空回去&#xff0c;老爸吐槽手机用几天就又卡了&#xff0c;其实就是清理一些手机缓存的问题。 我说我远程控制他的手机&#xff0c;给他清理一下。他一听“控制”就不喜欢&#xff0c;说我大了&#xf…

视频中的噪点怎么去除?

在数字视频时代&#xff0c;拍摄高质量的视频成为了许多人的追求。然而&#xff0c;在实际拍摄过程中&#xff0c;由于多种原因&#xff0c;我们常常会遇到视频噪点过多、画面模糊的问题&#xff0c;这不仅影响了观看体验&#xff0c;还可能让精心拍摄的作品大打折扣。那么&…