让我们面对现实吧。如果没有互联网,我们真的不会有物联网。JavaScript,连同 HTML 和 CSS,是互联网的核心技术之一。物联网的核心是设备间通信的协议 MQTT。
在本章中,我们将把注意力从 Python 转移到使用 JavaScript 构建 JavaScript 客户机以订阅 MQTT 服务器上的主题上
本章将介绍以下主题:
我们将从创建一个连接到 MQTT 代理(服务器)的简单 JavaScript 客户机开始本章。我们将向 MQTT 代理发送一条测试消息,然后将该消息返回到我们在其上创建 JavaScript 客户端的同一页面。然后,我们将从 Raspberry Pi 向我们的 MQTT 代理发布一条消息。
完成这一章需要几个小时。
为完成本项目,需要以下各项:
让我们从提供 JavaScript 云库的背景开始。JavaScript 自互联网诞生之日起就已经存在(为了争论起见,1995 年)。它已经成为一种语言,可以将 HTML 网页转换为功能齐全的桌面应用程序。我个人认为 JavaScript 是最有用的编程语言之一(当然除了 Python 之外)。
JavaScript was released in 1995 and was designed to work with the most popular web browser at the time, Netscape Navigator. It was originally called livescript, but the name was changed to JavaScript due to the use and support of Java within the Netscape Navigator browser. Despite the similar syntax, Java and JavaScript really have nothing to do with each other—a confusing fact that continues to this day.
我们可以通过google-api-javascript-client
访问谷歌云服务。具体来说,我们可以访问谷歌计算引擎,它是谷歌云平台的一个组件。通过谷歌计算引擎,我们可以通过使用按需虚拟机访问运行 Gmail、YouTube、谷歌搜索引擎和其他谷歌服务的基础设施。如果这听起来像是一种会给朋友留下深刻印象的技术胡言乱语,那么您可能需要深入研究一下这个 JavaScript 库。你可以在这里找到更多关于google-api-javascript-client
的信息:https://cloud.google.com/compute/docs/tutorials/javascript-guide 。
Node.js 中的 AWS SDK for JavaScript 为 AWS 服务提供 JavaScript 对象。这些服务包括 amazons3、amazonec2、amazonswf 和 DynamoDB。此库使用 Node.js 运行时环境。您可以在此处找到有关此库的更多信息:https://aws.amazon.com/sdk-for-node-js/ 。
Node.js was released in May of 2009. The original author was Ryan Dhal and it is currently being developed by the company Joyent. Node.js allows for the execution of JavaScript code outside of the browser, thereby making it a JavaScript everywhere technology. This allows JavaScript to be used both on the server side and client side for web applications.
Eclipse Paho JavaScript 客户端库是一个基于 MQTT 浏览器的 JavaScript 客户端库。Paho 本身是用 JavaScript 编写的,可以很容易地插入到 web 应用程序项目中。EclipsePAHOJavaScript 客户端库使用 web 套接字连接到 MQTT 代理。在本章中,我们将在我们的项目中使用此库。
对于我们的项目,我们将构建一个 JavaScript 客户机并将其连接到 MQTT 代理。我们将发布并订阅一个名为测试的主题。然后,我们将在 Raspberry Pi 上编写一个简单的小程序,以发布到名为 test 的主题。这段代码将演示使用 MQTT 发送和接收消息是多么容易。
请看下图,了解我们将在本项目中完成的工作:
第一步是设置 MQTT 代理。我们可以通过使用 Mosquitto 平台(www.Mosquitto.org在本地安装一个。我们将使用网站www.cloudmqtt.com建立一个基于云的 MQTT 代理。
要设置帐户,请执行以下操作:
在浏览器中,导航至www.cloudmqtt.com。
单击右上角的登录。
在“创建帐户”框中,键入您的电子邮件地址:
现在我们已经设置了 CloudMQTT 帐户,是时候创建一个用于我们的应用程序的实例了:
这是我在我的帐户上设置的 T.a.R.a.S 实例的屏幕截图。请注意列表中的值。这些值来自我的实例,而您的将不同。在编写 JavaScript 客户端时,我们将使用以下值:
要编写 JavaScript 客户端代码,我们应该在 T.a.R.a.S 上使用 Raspberry Pi 以外的计算机。您可以使用您想要的任何操作系统和 HTML 编辑器。我使用 macOS 和 VisualStudio 代码编写 JavaScript 客户端代码。您还需要 Paho JavaScript 库:
导航到 Eclipse Paho 下载站点https://projects.eclipse.org/projects/technology.paho/downloads 。
单击 JavaScript 客户端链接。它将被标记为名称JavaScript client
,后跟版本号。在撰写本文时,版本为 1.03。
JavaScript 客户端库将下载为带有paho.javascript-1.0.3
的 ZIP 文件。解压缩文件。
我们需要在计算机上有一个文件夹用作项目文件夹。在您的计算机上创建一个新文件夹,并将其命名为MQTT HTML Client
。
在MQTT HTML Client
文件夹内创建名为scripts
的子文件夹。
将解压后的paho.javascript-1.0.3
文件夹拖放到MQTT HTML Client
文件夹中。
MQTT HTML Client
文件夹内的目录结构应如下所示:
现在,是时候写代码了。我们将使代码尽可能简单,以便了解 MQTT 如何使用 JavaScript。我们的客户端代码将由两个文件组成,一个 HTML 页面和一个.js
(JavaScript)文件。让我们从创建 HTML 页面开始:
index.html
的文件,并将其保存到项目根目录中。project
文件夹应如下所示:index.html
文件中键入以下内容:<!DOCTYPE html>
<html>
<head>
<title>MQTT Message Client</title>
<script src="paho.javascript-1.0.3/paho-mqtt.js" type="text/javascript"></script>
<script src="scripts/index.js" type='text/javascript'></script>
</head>
<body>
<h2>MQTT Message Client</h2>
<button onclick="sendTestData()">
<h4>Send test message</h4>
</button>
<button onclick="subscribeTestData()">
<h4>Subscribe to test</h4>
</button>
<div>
<input type="text" id="messageTxt" value="Waiting for MQTT message" size=34 />
</div>
</body>
</html>
index.html
。index.js
的文件,我们还没有创建:<script src="paho.javascript-1.0.3/paho-mqtt.js" type="text/javascript"></script>
<script src="scripts/index.js" type='text/javascript'></script>
onclick
方法设置为sendTestData
。在底部按钮上,我们将onclick
方法设置为subscribeTestData
。这些方法将在我们将编写的 JavaScript 文件中创建。为简单起见,我们不会为这些按钮分配 ID 名称,因为我们不会在 JavaScript 代码中引用它们:<button onclick="sendTestData()">
<h4>Send test Message</h4>
</button>
<button onclick="subscribeTestData()">
<h4>Subscribe to test</h4>
</button>
index.html
页面中创建的最后一个元素是文本框。我们分配了一个id
的messageTxt
和一个Waiting for MQTT message to the text box
的值:<div>
<input type="text" id="messageTxt" value="Waiting for MQTT message" size=34 />
</div>
index.html
加载到浏览器中,它将如下所示:在运行客户端代码之前,我们需要创建 JavaScript 文件,该文件将提供我们所需的功能:
index.js
的文件,并将其保存到项目目录中的scripts
文件夹中。index.js
并保存。用实例中的值替换Server
、User
、Password
和Websockets Port
(分别显示为"m10.cloudmqtt.com"
、38215
、"vectydkb"
和"ZpiPufitxnnT"
:function sendTestData() {
client = new Paho.MQTT.Client
("m10.cloudmqtt.com", 38215, "web_" +
parseInt(Math.random() * 100, 10));
// set callback handlers
client.onConnectionLost = onConnectionLost;
var options = {
useSSL: true,
userName: "vectydkb",
password: "ZpiPufitxnnT",
onSuccess: sendTestDataMessage,
onFailure: doFail
}
// connect the client
client.connect(options);
}
// called when the client connects
function sendTestDataMessage() {
message = new Paho.MQTT.Message("Hello from JavaScript
client");
message.destinationName = "test";
client.send(message);
}
function doFail() {
alert("Error!");
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
alert("onConnectionLost:" + responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
document.getElementById('messageTxt').value = message.payloadString;
}
function onsubsribeTestDataSuccess() {
client.subscribe("test");
alert("Subscribed to test");
}
function subscribeTestData() {
client = new Paho.MQTT.Client
("m10.cloudmqtt.com", 38215, "web_" +
parseInt(Math.random() * 100, 10));
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
var options = {
useSSL: true,
userName: "vectydkb",
password: "ZpiPufitxnnT",
onSuccess: onsubsribeTestDataSuccess,
onFailure: doFail
}
// connect the client
client.connect(options);
}
index.html
的浏览器来运行代码。Hello from JavaScript client
。这是我们刚才表演的魔术吗?嗯,在某种程度上,是这样的。我们刚刚在 MQTT 代理上完成了一个主题的订阅,然后发布到同一个主题,然后在同一个 JavaScript 客户端中接收一条消息。要从 MQTT 代理见证这一点,请执行以下操作:
在浏览器的另一个选项卡或窗口中,导航回 JavaScript 客户端index.html
再次单击发送测试消息按钮
导航回 CloudMQTT 页面
在“已接收消息”列表下,您应该看到一条消息:
在为 Raspberry Pi 编写代码之前,让我们看看从 java T0T 中获取的 JavaScript 代码。
我们将首先看一下订阅代码。我们用于从 MQTT 代理订阅主题的两种方法是subscribeTestData
和onsubsribeTestDataSuccess
。subscribeTestData
创建名为client
的 Paho MQTT 客户端对象。它通过使用Server
和Websockets Port
值实例化对象,使用client
对象连接到我们的 MQTT 代理(为了简单起见,我在代码中保留了我帐户中的值):
function subscribeTestData() {
client = new Paho.MQTT.Client
("m10.cloudmqtt.com", 38215, "web_" +
parseInt(Math.random() * 100, 10));
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
var options = {
useSSL: true,
userName: "vectydkb",
password: "ZpiPufitxnnT",
onSuccess: onsubsribeTestDataSuccess,
onFailure: doFail
}
// connect the client
client.connect(options);
}
然后,我们将回调处理程序设置为client.onConnectionLost
和client.onMessageArrived
。回调处理程序将 JavaScript 代码中的函数链接到来自client
对象的事件。在这种情况下,当与 MQTT 代理的连接丢失或消息从 MQTT 代理到达时。options
变量将 SSL 的使用设置为true
,设置User
和Password
设置,然后设置成功连接onsubsribeTestDataSuccess
方法和尝试连接doFail
方法失败的条件。然后,我们通过传入我们的options
变量,通过client.connect
方法连接到我们的 MQTT 代理。
成功连接到 MQTT 代理时调用onsubsribeTestDataSuccess
方法。它将client
对象设置为订阅test
主题。然后,它会创建一个带有消息Subscribed to test
的警报:
function onsubsribeTestDataSuccess() {
client.subscribe("test");
alert("Subscribed to test");
}
如果与客户端的连接不成功,则调用doFail
方法。它只是创建一个带有消息Error!
的弹出式警报:
function doFail() {
alert("Error!");
}
现在,我们了解了订阅 AutoT0}主题的代码,让我们来看看发布到“TythT1”主题的代码。
sendTestData
功能与subscribeTestData
功能非常相似:
function sendTestData() {
client = new Paho.MQTT.Client
("m10.cloudmqtt.com", 38215, "web_" + parseInt(Math.random() * 100, 10));
// set callback handlers
client.onConnectionLost = onConnectionLost;
var options = {
useSSL: true,
userName: "vectydkb",
password: "ZpiPufitxnnT",
onSuccess: sendTestDataMessage,
onFailure: doFail
}
// connect the client
client.connect(options);
}
名为client
的 Paho MQTT 客户机对象是使用subscribeTestData
函数中使用的相同参数创建的。唯一的回调处理程序集是onConnectionLost
。我们没有设置onMessageArrived
,因为我们正在发送消息而没有收到消息。options
变量的设置值与subscribeTestData
函数中使用的值相同,但onSuccess
除外,我们将其分配给sendTestDataMessage
函数。
sendTestDataMessage
函数使用Hello from JavaScript client
值创建一个新的 Paho MQTT 消息对象,并将其命名为message
。destinationName
是我们为其创建消息的主题,它被设置为test
值。然后我们用client.send
发送信息:
function sendTestDataMessage() {
message = new Paho.MQTT.Message("Hello from JavaScript client");
message.destinationName = "test";
client.send(message);
}
onConnectionLost
函数用于订阅和发布,只需创建一个警报弹出窗口,其中包含来自 JavaScript 响应对象的错误消息:
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
alert("onConnectionLost:" + responseObject.errorMessage);
}
}
现在我们已经有了 JavaScript 客户端订阅并发布到 MQTT 代理,让我们让 Raspberry Pi 参与进来。
让我们回到 Raspberry Pi(如果您一直在使用另一台计算机),并编写一些代码与我们的 MQTT 代理通信:
import paho.mqtt.client as mqtt
from time import sleep
mqttc = mqtt.Client()
mqttc.username_pw_set("vectydkb", "ZpiPufitxnnT")
mqttc.connect('m10.cloudmqtt.com', 18215)
while True:
try:
mqttc.publish("test", "Hello from Raspberry Pi")
except:
print("Could not send message!")
sleep(10)
CloudMQTT-example.py
并运行它。index.html
。您应该在文本框中看到消息Hello from the Raspberry Pi
(如果您没有看到消息,请刷新页面并再次单击 Subscribe to test):Raspberry Pi Python 代码刻意保持简单,以便理解这些概念。我们通过导入所需的库来启动代码。然后,我们创建一个 MQTT 客户机对象,我们称之为mqttc
。用户名和密码使用username_pw_set
方法设置。然后,我们通过传递Server
和Port
值,使用connect
方法连接到 MQTT 代理(对于 Python 客户端,我们使用Port
而不是Websockets Port
。在一个连续循环中,我们通过publish
方法将主题test
和消息Hello from Raspberry Pi
传递给 MQTT 代理。
在本章中,我们在使用 JavaScript 创建 MQTT 客户机之前研究了 JavaScript 库。我们建立了一个基于云的 MQTT 代理,能够使用 JavaScript 客户端和 Raspberry Pi 上的 Python 程序发布和订阅消息。
在第 18 章中我们将对本章所学内容进行扩展,并构建一个 JavaScript 客户端,可以通过互联网控制 T.a.R.a.S。
google-api-javascript-client
库访问哪些谷歌服务?有关使用基于云的 MQTT 代理的更多信息,请参阅位于的 CloudMQTT 文档 https://www.cloudmqtt.com/docs.html 。