使用JavaScript和MQTT开发物联网应用示例解析


Posted in Javascript onAugust 07, 2020

如果说Java和C#哪个是最好的开发语言,无疑会挑起程序员之间的相互怒怼,那如果说JavaScript是动态性最好的语言,相信大家都不会有太大的争议。随着越来越多的硬件平台和开发板开始支持JavaScript,JavaScript在硬件端以及物联网领域有了新的机会。

IoT应用开发的数据链路

图1是一个智能家居物联平台的数据链路。

使用JavaScript和MQTT开发物联网应用示例解析

图1 智能家居物联平台的数据链路

一般来说,可以把IoT应用分为如图所示的四层。

  • client层:指的是IoT设备,可以是冰箱、空调,也可以是一些温湿度传感器。
  • gateway层:大多数场景中gateway是家里的WiFi路由器,也有小部分是基于Zigbee或蓝牙的网关设备。智能生活场景中的gateway数量相对于工业领域要少很多,在工业领域存在大量的边缘计算放在gateway层进行处理(雾计算)。
  • cloud云层:这里是集中处理业务的地方。
  • 应用层:这一层是直接与用户打交道的地方,可以是通过电脑的Web浏览器、手机App,也可以是有屏幕的智能设备的显示器。随着语音技术的发展,无屏设备也可以通过语音交互,作为一个应用存在于物联网的交互层。

物联设备(下文统称为client),可以是单个设备或多个设备组成的应用场景。比如冰箱把运行的功耗数据、库存数据、温度数据采集,通过gateway发送到cloud层,cloud层收集数据后进行异常判断,做智能模式推荐等业务处理后到application层进行展现和交互。用户可以通过冰箱的设备数据进行模式选择,还可以做一些与设备无关的增值服务,比如听音乐、买菜等,这就是一个智能冰箱的数据链路。还有些client是成组智能场景的,比如温湿度传感器将数据上传到cloud,经过处理和加工,动态控制家中空调的温度,调节空气净化器的运行模式等。这么描述好像没有体现出cloud层的作用,那如果运行模式是用户预先配置好的呢?如“当温度超过25度,请帮我打开空调”,这些业务都可以通过cloud层进行处理。

client层的连接方式有WiFi、Bluetooth、Zigbee,而MQTT是为了让物联网设备更加互联互通而出现的应用层数据协议。

MQTT+JavaScript

MQTT是一个长连接的通讯应用层协议,最大的特点是数据精简、消息可靠、Publish-Subscribe模式灵活易用。MQTT已经成为IoT传输的标准协议,应用非常广泛。

图2中Client指的是物联网设备。Client通过对Topic的订阅和发布数据管理应用中的数据流动,而Broker是MQTT应用中用于管理Topic的角色。Server是物联网应用中的服务端,用于处理业务逻辑。

使用JavaScript和MQTT开发物联网应用示例解析

图2 MQTT的数据链路图

MQTT被广泛使用的一个重要的原因是MQTT的生态非常完善,同时也支持JavaScript。因此图2所示的所有链路和模块,都可以通过JavaScript实现。

使用JavaScript和MQTT开发物联网应用示例解析 

图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获取数据后进行展现。

使用JavaScript和MQTT开发物联网应用示例解析

图4 “穿衣提示”业务场景框架

Broker端的实现

Broker端使用mosca,参考网页https://github.com/mcollina/mosca。

安装mosca。

nmp install mosca --save

启动mosca。这里需要注意,如果本地没有配置MongoDB,则需要把ascoltatore中的内容全部注释掉。

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获取数据。

安装koa

$ 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开发板实现了一次。

使用JavaScript和MQTT开发物联网应用示例解析
图5 Demo硬件演示

完整Demo代码已经分享在github中,大家可以输入URL下载。
https://github.com/coolnameismy/javascript-mqtt-demo-wearingTip

总结

本文和大家交流了物联网应用的一般数据链路、MQTT协议的架构,并基于MQTT实现了一个简单的物联网应用。

现在正是前端工程师的大好机会,越来越多的嵌入式设备都开始支持JavaScript,原因是现在有很多JavaScript引擎可以把JavaScript转换成各种平台的底层代码,比较有名的有Jerryscript、Duktape等。随着越来越多的JavaScript工程师进入嵌入式开发的领域,嵌入式应用开发也会出现前后端分离的情况(应用开发或是驱动开发),类似于Web开发的前后端分离。前端关注在应用、创意、数据链路、用户体现上,而后端则关心GPIO、I2C的底层数据接口和驱动,平台兼容性等方向。

到此这篇关于使用JavaScript和MQTT开发物联网应用示例解析的文章就介绍到这了,更多相关JavaScript和MQTT开发物联网应用内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
非常强大的 jQuery.AsyncBox 弹出对话框插件
Aug 29 Javascript
JavaScript 基本概念
Jan 20 Javascript
浅析Node.js 中 Stream API 的使用
Oct 23 Javascript
jquery组件WebUploader文件上传用法详解
Oct 23 Javascript
浅谈react.js 之 批量添加与删除功能
Apr 17 Javascript
关于Vue.nextTick()的正确使用方法浅析
Aug 25 Javascript
浅谈在koa2中实现页面渲染的全局数据
Oct 09 Javascript
JS实现马赛克图片效果完整示例
Apr 13 Javascript
微信小程序自定义顶部组件customHeader的示例代码
Jun 03 Javascript
JavaScript实现拖动对话框效果的实现代码
Oct 12 Javascript
微信小程序实现简单的select下拉框
Nov 23 Javascript
原生JavaScript实现随机点名表
Jan 14 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 #Javascript
浅谈javascript如何获取文件后缀名
Aug 07 #Javascript
vue 使用post/get 下载导出文件操作
Aug 07 #Javascript
基于javascript的无缝滚动动画实现2
Aug 07 #Javascript
vue 在methods中调用mounted的实现操作
Aug 07 #Javascript
javascript实现图片轮换动作方法
Aug 07 #Javascript
vue style width a href动态拼接问题的解决
Aug 07 #Javascript
You might like
php xml实例 留言本
2009/03/20 PHP
PHP n个不重复的随机数生成代码
2009/06/23 PHP
PHP Session变量不能传送到下一页的解决方法
2009/11/27 PHP
实例分析10个PHP常见安全问题
2019/07/09 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
2020/10/20 PHP
jQuery实现鼠标经过提示信息的地图热点效果
2015/04/26 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
2015/08/13 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
JavaScript中输出信息的方法(信息确认框-提示输入框-文档流输出)
2016/06/12 Javascript
JS如何生成一个不重复的ID的函数
2016/12/25 Javascript
jQuery插件HighCharts实现的2D面积图效果示例【附demo源码下载】
2017/03/15 Javascript
Express之get,pos请求参数的获取
2017/05/02 Javascript
Three.js入门之hello world以及如何绘制线
2017/09/25 Javascript
NodeJS实现视频转码的示例代码
2017/11/18 NodeJs
实例分析js事件循环机制
2017/12/13 Javascript
JS运动特效之完美运动框架实例分析
2018/01/24 Javascript
vue.js与element-ui实现菜单树形结构的解决方法
2018/04/21 Javascript
微信小程序遍历Echarts图表实现多个饼图
2019/04/25 Javascript
javascript实现点击产生随机图形
2021/01/25 Javascript
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
Python判断直线和矩形是否相交的方法
2015/07/14 Python
PYTHON压平嵌套列表的简单实现
2016/06/08 Python
Python读取mat文件,并保存为pickle格式的方法
2018/10/23 Python
Python列表切片操作实例总结
2019/02/19 Python
python将图片转base64,实现前端显示
2020/01/09 Python
eBay瑞士购物网站:eBay.ch
2018/12/24 全球购物
小米官方旗舰店:Xiaomi
2020/08/07 全球购物
教师节横幅标语
2014/10/08 职场文书
2014年党委工作总结
2014/11/22 职场文书
初中教师个人总结
2015/02/10 职场文书
民政工作个人总结
2015/02/28 职场文书
肖申克的救赎观后感
2015/06/02 职场文书
单位同意报考证明
2015/06/17 职场文书
李白经典诗之一:全文无一“月”字,却句句有月
2019/07/12 职场文书