从零开始的DIY智能浇水应用
前言
作为一个新世纪打工人,平常也会去养一些花草,来给我的房间增加点绿色和活力,但是常常因为工作忙而忘记一些事情。,毕竟我大部分的时间都是陪伴着电脑的(严正声明:我不是个单身狗!!!
(¬◡¬)✧),之前在淘宝上买了个土壤湿度传感器和浇水设备,自己改造了一下,通过 WiFi 和 SDDC 成功接入了爱智盒子,现在准备搞一个爱智应用来进行设备的控制;
场景演示
先看一下我改造好的成品吧ヾ(๑╹◡╹)ノ",直接放在了我房间的展示柜上开始用了。
这是浇水器!

这是插进去的土壤湿度传感器的屁股!

(σ゚∀゚)σ..:*☆ 哎哟是不是很厉害啊!
这个花盆里面我插了之前的土壤湿度传感器和浇水器的出水口,然后浇水器的入水口我放在了一个装水的瓶子里,这样一个自动浇水的东西就完成了。因为这是我自己室内用的小设备,规模比较小,有想法的兄弟扩展扩展可以搞到在农业浇灌这方面去试试,想想还有点小兴奋呢。ヾ(>∀<)(ノ∀`●)⊃
应用演示
话不多说 ─=≡Σ(((つ•̀ω•́)つ,还是直接先看一下我的应用页面长什么样子,

一如既往的放了一个数据显示面板,一个设备选择模块,一个设备参数设置模块。
使用起来也是非常的简单,直接选择一下土壤湿度传感器以及浇水设备,拖动两个游标,设置浇水的适宜范围,每当我花盆里面的土壤湿度低于60%的时候就会通过 Spirit 向浇水器发送加水信号并开始加水,湿度达到85%就停止浇水,这样一个智慧浇水的场景就完成了。
整体实现逻辑是比较简单的,后面的话我也会逐步的在网上买一些其他的设备,搭建一些比较完整的智能场景出来。
代码分析
关于实现的代码也是利用了之前的设备模块 device,前端的我感觉就不用摆出来显摆了,比较简单的一个页面没啥好讲的,
只贴一下后端js部分的关键代码吧<( ̄ ﹌  ̄)@m 。
// 因为用的频率比较高,个人比较懒,所以就基于正常的逻辑封装了一下,基本可以满足我目前乃至后面的大部分需求了,其他个别需求遇到再扩充。
// device_manager.js
const Device = require('device');
const EventEmitter = require('events');
class DeviceManager extends EventEmitter {
constructor() {
super();
this.devMap = new Map();
this.controllerMap = new Map();
this.init();
}
init() {
// 获取当前所有已加入网络的在线设备!
Device.list(true, (error, list) => {
if (error) {
console.error('Device.list error!' + error);
} else {
list.forEach((item) => {
Device.info(item.devid, (error, info) => {
if (error) {
console.error('Device.info error!' + error);
} else {
this.devMap.set(item.devid, {
devid: item.devid,
alias: info.alias,
report: info.report
});
}
});
});
}
});
Device.on('join', async (devid, info) => {
const dev = { devid, ...info };
this.devMap.set(devid, dev);
this.emit('join', dev);
});
Device.on('lost', (devid) => {
const dev = this.devMap.get(devid);
this.devMap.delete(devid);
if (this.controllerMap.has(devid)) {
this.controllerMap.delete(devid);
}
if (!dev) {
this.emit('error', '应用出现未知错误,请退出重试!');
} else {
this.emit('lost', dev);
}
});
}
// 构建设备控制对象
generateController(devid) {
if (this.controllerMap.has(devid)) {
return Promise.resolve(this.controllerMap.get(devid))
}
const controller = new Device();
return new Promise((resolve, reject) => {
controller.request(devid, (error) => {
if (error) {
reject(error);
} else {
this.controllerMap.set(devid, controller);
resolve(controller);
}
});
})
}
// 删除控制器
deleteController(devid) {
this.controllerMap.delete(devid);
}
// 发送设备消息
sendDeviceInfo(devid, data) {
const controller = this.controllerMap.get(devid);
if (!controller) {
return Promise.reject('程序出现未知错误,请退出重试!')
}
return new Promise((resolve, reject) => {
controller.send(data, (err) => {
if (err) {
reject('控制设备失败,请重试!')
} else {
resolve();
}
}, 3)
})
}
}
const devManager = new DeviceManager();
module.exports = {
devManager
}
以上就是封装的设备管理模块了,接下来在main.js中就会去使用该模块中的相关方法;
// main.js
...
function generateDevController(devid) {
return new Promise((resolve, reject) => {
const dev = devManager.devMap.get(devid);
devManager.generateController(devid).then((controller) => {
controller.on('message', (data) => {
const points = humidity_water_scene.settings.points;
if (isSceneDev(devid) && getDeviceType(dev) === 'humidity') {
socketIO.emit('humidity', Number(data.data.soil_humidity.toFixed(1))); // 0-100
if (!waterDev) {
return;
}
if (data.data.soil_humidity < points[0] && !watering) {
startWater(); // 浇水
} else if (data.data.soil_humidity >= points[0] && watering) {
stopWater(); // 停水
}
} else if (getDeviceType(dev) === 'water') {
if (data.data.watering === 'ON' && watering && t === 0 && humidityDev) {
setHumidityTimer(1000);
} else if (data.data.watering === 'OFF' && !watering && t) {
clearInterval(t);
t = 0
}
}
});
resolve(controller);
}).catch(() => {
reject(`应用缺少控制${dev.alias}的权限!`);
})
})
}
...
上面的代码调用封装的设备管理模块实例的generateController方法来构造设备控制对象,
可以看到在设备消息监听事件 message 中如果湿度感应设备返回的数据值小于我们指定的值就会调用startWater方法进行浇水,否则就会停止浇水;
同样浇水设备会根据控制浇水开关命令,来返回当前设备状态,如果浇水设备处于运行中,则会主动加快获取湿度感应器的实时数值,便于实时控制设备。

总结
整体实现没有太大的问题,某些细节方面可能还需要优化一下,不过现在已经开始用了,当然肯定不会直接接到水龙头上,不然程序要是出bug了,那代价就有点太大了( uTェTu )!
今天的分享到此就结束了,具体的详细代码可以去灵感桌面的秘密宝库里面去查看,不说了,言尽于此,睡了。
从零开始的DIY智能浇水应用的更多相关文章
- 从零开始的DIY智能家居 - 基于 ESP32 的智能浇水器
前言 上次 土壤湿度传感器 完成之后,就立下一个 flag 要搭建一个智慧浇水的智能场景,现在终于有时间填坑了!(o゚▽゚)o 智慧浇水场景的核心设备有三个: 检测土壤状态的:土壤湿度传感器 通过这个 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器
前言 自从上次做了那个 甲醛传感器 和 水浊度传感器 之后开始尝到智能家居的甜头了,这两东西有没有用我不知道,但是没事的时候掏出手机瞄两眼,看着就让人很安心( ̄︶ ̄). 于是懒惰的我开始琢磨把给植物浇 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的智能水浊度传感器
前言 家里有个鱼缸养了几条鱼来玩玩,但是换水的问题着实头疼,经常一个不注意就忘记换水,鱼儿就没了.o(╥﹏╥)o 在获得 Spirit 1 边缘计算机 后就相当于有了一个人智能设备服务器,可以自己开发 ...
- 从零开始的DIY智能家居 - 基于 ESP32 的智能光照传感器
前言 上周出差有点急,结果家里灯没关,开了整整一周的时间(T▽T),整个人都裂开了,准备做一个能够远程控制灯的东西,让我以后出差能远程把家里灯关了. 第一步就是做这期的主题 - 智能光照传感器,因为我 ...
- DIY智能家居——零基础入门篇
概要 本文主要根据笔者从零开始接触硬件,以小白视角开启IoT探索,根据相关资料DIY一个温湿度传感器.后经过探索发现新大陆--Home Assistant&Homebridge,最终实现了一个 ...
- Diy智能家居-1.基于esp8266的语音控制系统(开篇)
目录Diy智能家居-1.基于esp8266的语音控制系统(开篇) https://blog.csdn.net/arno1988/article/details/82628589 Diy智能家居-2.基 ...
- 从零开始写STL - 智能指针
从零开始写STL - 智能指针 智能指针的分类及其特点: scoped_ptr:初始化获得资源控制权,在作用域结束释放资源 shared_ptr: 引用计数来控制共享资源,最后一个资源的引用被释放的时 ...
- 从零开始 DIY 智能家居 - 智能开窗器
前言 做完智慧浇水器之后对这种可以节省时间和精力的场景总有一种谜之向往(懒鬼是这样的),这次我准备做一个可以自动开窗的装置,结合之前的甲醛检测传感器就可以实现甲醛含量过高自动开窗通风,之后还可以把燃气 ...
- 从零开始 DIY 智能家居 - 基于 ESP32 的智能紫外线传感器模块
目录 前言 硬件选择 二.使用步骤 获取代码 设备控制命令: 设备和协议初始化流程: 配置设备信息 回调函数注册 数据获取与上报流程 总结 前言 做了这么多传感器都是自己玩,这次家里人看不下去了,非得 ...
随机推荐
- activemq启动错误UnsupportedClassVers rg/apache/activemq/console/Main:Unsupported major.minor version52.0
ActiveMQ与java的JDK是有版本对应匹配的. 下面提供一个匹配图: MQ版本号 Build-Jdk 依赖JDKapache-activemq-5.0.0 1.5.0_12 1.5+apach ...
- 将dict.define转化成dict.txt
在使用捷通智能灵云外呼系统V6.1时.需要大量使用到模式码,也就是正则表达式.而老版本365还是使用场景文件. 当要将老版本改编成新版本的时候,需要需要将dict.define文件中的一行行的词条用& ...
- php获取纳秒方法
PHP不提供精度高于微秒的函数. 可以使用system功能,直接从机器中获得的价值,如果你运行的是Linux: $nanotime = system('date +%s%N');
- jQuery <= 1.11.3 DomXSS漏洞
听团里说WordPress又爆跨站漏洞了:" XSS漏洞在Jetpack和二十五默认主题影响百万WordPress用户 ",分析发现原来是jQuery老版本的DOM XSS漏洞[错 ...
- Jmeter扩展组件开发(8) - 函数助手扩展开发demo
前提条件 1.pom文件引用ApacheJMeter_functions包 <dependency> <groupId>org.apache.jmeter</groupI ...
- oracle 基础SQL语句 版本5.7.29
一.表与用户介绍 oracle安装完成后默认会有很多用户,大致分为2类用户:一类是必需的帐户,一类是存储各种应用的帐户,默认密码如下: oracle自带的也会有很多默认表存在: 二.创建用户.创建表空 ...
- js运行机制 值引用 值传递
1.js是单线程的 为什么是单线程的呢 因为js作为浏览器脚本语言,会有很多和用户的互动,以及操作dom,多个线程会出问题. 2.js有同步任务,异步任务(ajax,用户点击等,settimeou ...
- 羽夏逆向破解日记簿——RunAsDate的实现原理分析
前言 RunAsDate是一个小工具,允许您在指定的日期和时间运行程序,不过有人用它来破解有时间限制了.此实用程序不会更改计算机的当前系统日期和时间,但只会将指定的日期/时间注入所需的应用程序.该 ...
- jzoj4496-[GDSOI2016]互补约数【莫比乌斯反演】
正题 题目链接:https://gmoj.net/senior/#main/show/4496 题目大意 给出\(n\),定义 \[f(i)=\sum_{d|i}gcd(d,\frac{i}{d}) ...
- T183637-变异距离(2021 CoE III C)【单调栈】
正题 题目链接:https://www.luogu.com.cn/problem/T183637 题目大意 给出\(n\)个二元组\((x_i,y_i)\),求最大的 \[|x_i-x_j|\time ...