如果说 Java 和 C# 哪个是最好的开发语言,无疑会挑起程序员之间的相互怒怼,那如果说 JavaScript 是动态性最好的语言,相信大家都不会有太大的争议。随着越来越多的硬件平台和开发板开始支持 JavaScript,JavaScript 在硬件端以及物联网领域有了新的机会。
图 1 是一个智能家居物联平台的数据链路。
图 1 智能家居物联平台的数据链路
一般来说,可以把 IoT 应用分为如图所示的四层。
物联设备(下文统称为 client),可以是单个设备或多个设备组成的应用场景。比如冰箱把运行的功耗数据、库存数据、温度数据采集,通过 gateway 发送到 cloud 层,cloud 层收集数据后进行异常判断,做智能模式推荐等业务处理后到 application 层进行展现和交互。用户可以通过冰箱的设备数据进行模式选择,还可以做一些与设备无关的增值服务,比如听音乐、买菜等,这就是一个智能冰箱的数据链路。还有些 client 是成组智能场景的,比如温湿度传感器将数据上传到 cloud,经过处理和加工,动态控制家中空调的温度,调节空气净化器的运行模式等。这么描述好像没有体现出 cloud 层的作用,那如果运行模式是用户预先配置好的呢?如 "当温度超过 25 度,请帮我打开空调",这些业务都可以通过 cloud 层进行处理。
client 层的连接方式有 WiFi、Bluetooth、Zigbee,而 MQTT 是为了让物联网设备更加互联互通而出现的应用层数据协议。
MQTT 是一个长连接的通讯应用层协议,最大的特点是数据精简、消息可靠、Publish-Subscribe 模式灵活易用。MQTT 已经成为 IoT 传输的标准协议,应用非常广泛。
图 2 中 Client 指的是物联网设备。Client 通过对 Topic 的订阅和发布数据管理应用中的数据流动,而 Broker 是 MQTT 应用中用于管理 Topic 的角色。Server 是物联网应用中的服务端,用于处理业务逻辑。
图 2 MQTT 的数据链路图
MQTT 被广泛使用的一个重要的原因是 MQTT 的生态非常完善,同时也支持 JavaScript。因此图 2 所示的所有链路和模块,都可以通过 JavaScript 实现。
图 3 JavaScript 在 MQTT 架构中常用的架构
JavaScript 在 MQTT 架构中常用的框架
mosca( https://github.com/mcollina/mosca ) mosca 是一个用 JavaScript 实现的 MQTT Broker。不仅如此,mosca 还增加了对数据库,如 Redis、MongoDB 的支持,用来实现消息数据的存储。
MQTT.js( https://github.com/mqttjs/MQTT.js ) MQTT.js 是官网推荐的 JavaScript 实现的 Client 端。
KOA 和 Express 这两者都是非常主流的 Node 版本的 Server,简单易用。
这节我们运用之前介绍的框架,自己动手完成一个简单的物联网应用。应用场景如图 4 所示,温度传感器用于接收温度,并把文档通过 MQTT 发送到 Server 端,在 Server 端进行业务处理,根据温度计算出穿衣提示,通过 MQTT 把数据发送到特定的 Topic,App 订阅 Topic 获取数据后进行展现。
图 4 "穿衣提示" 业务场景框架
Broker 端的实现
Broker 端使用 mosca,参考网页 https://github.com/mcollina/mosca 。
- nmp install mosca--save
- var mosca = require('mosca');
- var ascoltatore = {
- //using ascoltatore
- // type: 'mongo',
- // url: 'mongodb://localhost:27017/mqtt',
- // pubsubCollection: 'ascoltatori',
- // mongo: {}
- };
- var settings = {
- port: 1883,
- backend: ascoltatore
- };
- var server = new mosca.Server(settings);
- server.on('clientConnected',
- function(client) {
- console.log('client connected', client.id);
- });
- // fired when a message is received
- server.on('published',
- function(packet, client) {
- console.log('Published', packet.payload); //{"clientId":"mqttjs_02fea7b4","topic":"/tips"}
- // console.log('>>>packet', packet); //{"clientId":"mqttjs_02fea7b4","topic":"/tips"}
- });
- server.on('ready', setup);
- // fired when the mqtt server is ready
- function setup() {
- console.log('Mosca server is up and running');
- }
代码完成后,启动文件,本地的一个 Broker 就跑在 localhost 的 1883 端口上了。
Client 端的温度传感器实现
Client 使用 MQTT.js 实现,参考网页 https://github.com/mqttjs/MQTT.js
- npm install mqtt--save
- var mqtt = require('mqtt');
- var client = mqtt.connect('mqtt://localhost:1883');
- client.on('connect', function () {
- console.log('>>> connected')
- // client.subscribe('/tips')
- setInterval(
- ()=>{client.publish('/temperature', '30');},
- 3000
- );
- })
- client.on('message', function (topic, message) {
- // message is Buffer
- console.log(message.toString())
- })
- // client.end();
执行 Node index 后 Client 就启动了,可以看到在 MQTT.connect 方法中连接了上一节中启动的 Broker 地址,连接成功后,Client 会输出日志,">>> connected",Broker 的控制台也会输出 Client 的连接信息。
这里模拟了温度传感器,定时 3 秒向 / temperature 的 Topic 中发送温度数据。
本节的温度器可以在电脑中使用 Node 方式运行,也可以运行在支持 JavaScript 的开发板中,如 RUFF、NodeMCU、Raspberry Pi,并且可以使用真实的传感器。
Server 的实现
Server 使用 MQTT.js 订阅 Client 发送到 / temperature Topic 的数据进行处理,把处理后的数据转译成 JSON 发送到另一业务主题 / tips 中。
实现代码如下:
- 'use strict'
- const mqtt = require('mqtt');
- var client = mqtt.connect('mqtt://localhost:1883');
- client.on('connect',
- function() {
- console.log('>>> connected');
- client.subscribe('/temperature');
- })
- client.on('message',
- function(topic, message) {
- var temperature = parseInt(message.toString());
- var data = {
- temperature
- };
- if (temperature >= 60) {
- data.tips = "热... 500服务器故障";
- } else if (temperature >= 50) {
- data.tips = "今天天气非常热,建议不要穿衣服了";
- } else if (temperature >= 40) {
- data.tips = "今天天气十分的热,建议穿短袖T恤+短裤";
- } else if (temperature >= 30) {
- data.tips = "今天天气有点的热,建议穿短袖T恤";
- } else if (temperature >= 0) {
- data.tips = "今天天气正好,可以穿上一件薄衣服";
- } else if (temperature >= -10) {
- data.tips = "今天天气十分寒冷,棉袄可以穿上一件";
- } else {
- data.tips = "今天天气十分十分寒冷,棉袄可以穿上二件";
- }
- client.publish('/tips', JSON.stringify(data));
- // if (temperature+1) {}
- // message is Buffer
- console.log(JSON.stringify(data));
- })
App 的实现
Demo 的 App 使用 KOA 启动一个 Web,在 Web 中展现当前温度对应的穿衣提示,通过订阅 tips 获取数据。
- $ npm install koa
- 'use strict'
- const Koa = require('koa');
- const mqtt = require('mqtt');
- const app = new Koa();
- var msg = {temperature:"-",tips:""};
- // response
- app.use(ctx => {
- ctx.body = "当前温度:" + msg.temperature + "度" + "\n" + '穿衣提示:'+msg.tips + "\n" ;
- });
- app.listen(3000);
- //mqtt
- var client = mqtt.connect('mqtt://localhost:1883');
- client.on('connect', function () {
- console.log('>>> connected');
- client.subscribe('/tips');
- })
- client.on('message', function (topic, message) {
- var data = JSON.parse(message.toString());
- console.log(message.toString());
- console.log(data.tips);
- msg = data;
- // if (temperature+1) {}
- // message is Buffer
- // let str = message.toString();
- // let data = JSON.parse(message);
- // console.log(data.tips);
- // msg = message.toString();
- })
Demo 小节
本章给出了一个简单的物联网业务的业务场景和实现逻辑,其中 Client 也可以运行在电脑上进行 Demo 查看,或是跑在真实物联设备或开发版上。如图 5,笔者使用 RUFF 开发板实现了一次。
图 5 Demo 硬件演示
完整 Demo 代码已经分享在 github 中,大家可以输入 URL 下载。
https://github.com/coolnameismy/javascript-mqtt-demo-wearingTip
本文和大家交流了物联网应用的一般数据链路、MQTT 协议的架构,并基于 MQTT 实现了一个简单的物联网应用。
现在正是前端工程师的大好机会,越来越多的嵌入式设备都开始支持 JavaScript,原因是现在有很多 JavaScript 引擎可以把 JavaScript 转换成各种平台的底层代码,比较有名的有 Jerryscript、Duktape 等。随着越来越多的 JavaScript 工程师进入嵌入式开发的领域,嵌入式应用开发也会出现前后端分离的情况(应用开发或是驱动开发),类似于 Web 开发的前后端分离。前端关注在应用、创意、数据链路、用户体现上,而后端则关心 GPIO、I2C 的底层数据接口和驱动,平台兼容性等方向。
来源: http://www.open-open.com/lib/view/open1498618497448.html