目录
一.接线图
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/查看系统中含有哪些消息队列
<