从零开始的DIY智能家居

发布时间:2024-11-28 15:35

家居DIY:从零开始打造个性化的壁灯 #生活乐趣# #生活分享# #家居生活方式# #家居 DIY 知识#

前言

​ 最近整理资料的时候,才发现之前写的一个智慧猫眼的爱智场景没有给大家写文章介绍,可能有的小伙伴之前也看到爱智官方引用我的这个代码给大家进行了一个直播演示,我个人还是觉得自己也有必要简单介绍一下(其实是代码被自己搞丢了,最近才找官方要回来)。整个场景所需要的嵌入式设备以及相关代码看看看我之前写的arduino 天下第一(暴论) – 智能猫眼与 SDDC 连接器移植到 arduino 上和从零开始的DIY智能家居 – 智能红外接近传感器,这里就不过多啰嗦了,直接来进入这次的正题。

在这里插入图片描述

界面&描述

​ 在讲解应用代码之前,先给大家看一下实现的界面以及介绍下整个场景的流程。
请添加图片描述

上图就是我们的这个应用的主页面,其实也就一个页面,为了方便把所有内容都放在一个页面里面了(就是懒!o(´^`)o)。不过不影响我接下来的表演。

从上到下,最上面黑色区域是摄像头拍摄到的一张张图片的显示区域,再往下就是关于人脸识别的一些信息和识别度等数据,这里还添加了一个根据灯关色温进行切换的表情显示。可以说说以上都是整个场景的一些数据展示。

中间部分我们可以看到有四个设备通过虚线连接到到爱智的一个演示图,我们通过点击每个图片对应的类型设备进行场景设备的选择,当设备被添加成功后,场景的业务逻辑会自动的运行。

主要业务逻辑:红外接近设备检测到物体靠近,会通知应用进行摄像头设备的拍照,再拿到返回的照片信息后,会通过人脸识别功能进行识别匹配,如果是授权人员,门锁设备将会进行开锁操作,同归灯泡会个根据当前人脸的表情进行色温调节。

除了可以自动识别开锁,应用也提供了手动开锁,那个大大的圆形的中间有个锁的按钮就是开锁按钮了。

最下面的授权成员,其实就是我们配置的人员人脸信息,主要还是通过调用手机摄像头进行拍照,然后通过人脸分析模块将得到的数据和个人信息进行持久化存储。

关于应用的大致描述就以上这些了。(/ω\)

代码分析

下面我们根据上面说的场景业务逻辑给大家简单过一遍代码。

添加授权人员信息

... // 添加成员信息 const multer = require('middleware').multer; const upload = multer({ dest: 'uploads/' }); // const upload = multer({ storage: multer.memoryStorage() }); app.post('/upload-file', upload.any(), (req, res) => {// 检测用户名是否存在const isExistName = lwir_camera_lock_light_scene.settings.faces.find((item) => { return item.name === req.body.name });if (isExistName) {return res.send({ result: false, message: '当前用户名的用户已存在!' });}const buffer = fs.readFile(path.join('./', req.files[0].path));const features = getFaceFeature(buffer);if (!features) {return res.send({ result: false, message: '人脸识别出错!' })}if (!features.length || features.length > 1) {return res.send({ result: false, message: '请确保图片中有且仅有单人头像!' });}// 先检测数据库中是否存在该人脸的信息const isExistFace = checkFaceAuthorization(features[0].keys);if (isExistFace) {return res.send({ result: false, message: '当前人脸信息已经在数据库中存在!' });}// 将人脸信息key录入数据库中lwir_camera_lock_light_scene.settings.faces.push({ name: req.body.name, keys: features[0].keys })updateSceneDB();res.send({ result: true, message: '人脸录入成功!' });emitMembers() }) // 获取图片上的人脸特征信息 function getFaceFeature(picture) {if (!picture) {return}const bitmap = imagecodec.decode(picture, {components: imagecodec.COMPONENTS_RGB});if (!bitmap || !bitmap.buffer) {return}const faces = facenn.detect(bitmap.buffer, {width: bitmap.width,height: bitmap.height,pixelFormat: facenn.PIX_FMT_RGB24}, true);const faceFeatures = [];if (faces.length) {let feature;faces.map((item) => {feature = facenn.feature(bitmap.buffer, {width: bitmap.width,height: bitmap.height,pixelFormat: facenn.PIX_FMT_RGB24}, item, {live: true,emotion: true})faceFeatures.push(feature);})}return faceFeatures; } // 检查人脸是否为授权成员 function checkFaceAuthorization(key) {for (const item of lwir_camera_lock_light_scene.settings.faces) {const res = facenn.compare(key, item.keys);if (res > 0) {socketIO.emit('similarity', Number((res * 100).toFixed(1)));}console.log("compare: ", res)if (res > 0.55) {socketIO.emit('face', { name: item[0] });return true;}}socketIO.emit('face', { name: '' });return false; } ...

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

场景自动化逻辑

// 构建设备控制对象 function generateDevController(devid) {return new Promise((resolve, reject) => {const dev = devManager.devMap.get(devid) || {};const type = getDeviceType(dev);devManager.generateController(devid).then((controller) => {controller.on('message', (data) => {console.info('message:', data);if (type === 'lock') {// 门锁socketIO.emit('lock', data.data.unlock);lockStatus = data.data.unlock;if (lockStatus === 'ON' && lightDev && lightDev.devid) {const lightController = devManager.controllerMap.get(lightDev.devid);if (lightController) {lightController.send({channel0: true}, undefined, 3)}}} else if (type === 'lwir') {// 红外感应if (data.data.proximity === 'ON' && cameraDev) {socketIO.emit('people')notify.push('智能猫眼', '检测到有人出现!');t = setInterval(() => { // 检测到物体靠近后,开启500ms定时器拍照处理 recogniseCateyeView(devManager.controllerMap.get(cameraDev.devid));}, 500);} else {clearInterval(t);}} else if (type === 'camera') {curImageSize = data.size;console.log('image size: ', curImageSize)}});resolve(controller);}).catch(() => {reject(`应用缺少控制${dev.alias}的权限!`);})}) } // 获取猫眼视图进行人脸识别分析开锁 function recogniseCateyeView(controller) {if (!controller) {return;}getCateyeData(controller).then((chunk) => {// 人脸分析const features = getFaceFeature(chunk);let isAuthorization = false; // 图片中是否存在授权用户if (features && features.length) {let scenes = '';switch (features[0].emotion) {case 'happy':scenes = 'relax'break;case 'sad':scenes = 'night'break;default:scenes = 'wakeup'break;}socketIO.emit('emotion', features[0].emotion);if (lightDev && lightDev.devid) {const lightController = devManager.controllerMap.get(lightDev.devid);if (lightController && lockStatus === 'ON') { // 开锁状态期间可以改变色温lightController.send({scenes}, undefined, 3)}}for (const item of features) {isAuthorization = checkFaceAuthorization(item.keys);if (isAuthorization) {break;}}} else {socketIO.emit('similarity', 0);socketIO.emit('face', { name: '' });}socketIO.emit('image', chunk.toString('base64'));if (isAuthorization && lockStatus === 'OFF') {unlock();}}).catch((err) => {console.error(err)}) } // 获取猫眼数据 function getCateyeData(controller) {return new Promise((resolve, reject) => { // 使用连接器进行分块传输const camConnector = new Device.Connector(controller, true);let chunks = [];camConnector.on('connect', function () {console.info('connect');})camConnector.on('data', function (chunk) {console.info('data: ', chunk.length);chunks.push(chunk);})camConnector.on('close', function () {console.info('close');})camConnector.on('error', function (error) {chunks = [];reject('connector error.')})camConnector.on('finish', function () {console.info('finish', chunks.length, curImageSize);if (!curImageSize) {return reject('no image size.');}if (!chunks.length) {return reject('no receive image.')}const chunk = Buffer.concat(chunks);console.log('chunk compare: ', chunk.length, curImageSize)if (chunk.length === curImageSize) {resolve(chunk);} else {reject('chunk lose.');}})camConnector.on('timeout', function (error) {chunks = [];const time = formatDate(new Date())reject(`connector timeout: ${time}`)})controller.send({cam: 'image',connector: camConnector}, undefined, 0)}) }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145

场景演示

场景演示这里就不录制了,大家可以去看官网当时的一个直播演示视频

总结

这个场景整个实现相对于之间的来说,还是相对比较复杂的,如果你可以自己开发这样的一个场景出来的话,那我感觉其他的爱智设备控制应用开发应该也不会有难度了。最后,如果大家觉得哪里写的有问题的话可以直言不讳哈!

网址:从零开始的DIY智能家居 https://www.yuejiaxmz.com/news/view/302280

相关内容

从零开始 DIY 智能家居
DIY布艺手工制作:从零开始打造独一无二的家居装饰品
好好住家居指南 : 从零开始的装
居家锻炼必看!从零开始提升你的健康
DIY手工花瓶制作全攻略:从零开始轻松打造独一无二的花艺品
智能家居diy书籍 智能家居 diy
Home Depot发展史:开启家居DIY时代零售巨头
如何开始 DIY 家居装修项目
DIY小屋制作全攻略:从零开始打造属于自己的小家
智能家居:便捷生活从这里开始

随便看看