实时设备状态监控与MQTT协议应用

在物联网(IoT)时代,各种设备如智能设备、服务器甚至Web会话的数量激增,实时监控这些设备的在线状态变得尤为重要。本文将介绍如何构建一个小型Web应用程序,用于跟踪登录用户的在线状态。为了简化演示,将在同一页面内创建3个不同的连接。值得注意的是,这种技术不仅限于Web应用,它底层使用的是MQTT协议,因此所有描述的代码都可以轻松地用C/C++编写,并在低内存集成板上运行。

在本教程中,将使用名为emitter.io的服务来处理在线状态。该服务的在线状态功能贯穿整个服务,对用户来说是透明的。在emitter中,有两种方式可以检索在线状态信息,它们的性质是互补的:

  1. 检索当前在线设备的列表,这是一个请求/响应风格的API调用,返回一个状态消息,描述订阅者的数量和他们的客户端标识符。
  2. 加入/离开更新通知,这是服务每次有设备订阅或取消订阅特定MQTT通道或通配符时推送的。

emitter.io是一个分布式的发布-订阅MQTT代理。在本文中,假设读者对MQTT有基本的了解,不会详细讨论协议的规范以及如何使用它。然而,这里有一些重要的点需要了解:

  1. 在MQTT中,客户端可以订阅主题(通道),这些主题由层次结构的字符串表示(例如:sensor/1/temperature/)。
  2. 客户端可以向这些通道发布任意二进制数据。
  3. MQTT数据包的头部只有2个字节,并且存在多种客户端库。

假设有多个MQTT客户端(连接)订阅了特定的通道。在演示中,通道是"presence-demo/" + Math.random().toString(16).substr(2, 8),这为每个人创建了一个隔离的演示。将检索:

  1. 订阅该通道的客户端。
  2. 当新客户端订阅该通道或现有客户端从该通道取消订阅时的通知。

在示例中,首先创建一个主连接,它将订阅通知。注意,在这里使用了secure: true参数,因为希望设备通过TLS/SSL连接。 var client0 = emitter.connect({ secure: true }); 一旦客户端连接上并想要监控在线状态,查询通道的在线状态。 client0.on('connect', function() { // Query the presence state client0.presence({ key: key, channel: channel }); }); 当第一次调用presence()函数时,收到的响应格式如下,告诉目前没有人订阅: {event: "status", channel: "presence-demo/8758f6d3/", occupancy: 0, time: 1471850444, who: []} 由于没有特别指定,client0也订阅了该通道的加入/离开推送通知,emitter代理将转发此类事件。

接下来,创建一些要测试的客户端。最初,这些连接是禁用的。 var client1 = null; var client2 = null; 将切换这些连接的开关,以模拟设备连接和断开连接。在这里,name参数实际上设置了MQTT的clientId选项,允许识别各种设备。由于控制了clientId,也可以将任何状态与它们关联。在示例中,简单地给用户一些名字,但理想情况下,会使用一个唯一的标识符,如GUID/UUID或强伪随机字符串。

当一个客户端加入时,收到一个subscribe事件,其中包含当前占用率、时间戳(UNIX时间)和客户端ID。在这个演示中,将客户端ID设置为用户名,但理想情况下,会有一个GUID/UUID,如前所述。 {event: "subscribe", channel: "presence-demo/8758f6d3/", occupancy: 1, time: 1471850449, who: "Alan"} 另一个用户可能会订阅,会收到另一个事件。 {event: "subscribe", channel: "presence-demo/8758f6d3/", occupancy: 2, time: 1471850450, who: "Margaret"} 当用户取消订阅时,会收到一个unsubscribe事件,以及当前的占用率。 {event: "unsubscribe", channel: "presence-demo/8758f6d3/", occupancy: 1, time: 1471850453, who: "Alan"}

现在,订阅了在线事件的客户端/设备将接收并处理各种通知。参见下面的代码片段,它相当直接。在这种情况下,它使用vuejs数据绑定更新UI。 // on every presence event, print it out client0.on('presence', function(msg){ console.log(msg); var users = vue.$data.users; switch(msg.event){ case 'status': for(var i = 0; i < msg.who.length; ++i){ users.push({ name: msg.who[i] }); } break; case 'subscribe': users.push({ name: msg.who }); break; case 'unsubscribe': vue.$data.users = users.filter(function( obj ) { return obj.name !== msg.who; }); break; } // Also, set the occupancy vue.$data.occupancy = msg.occupancy; });

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485