65.9K
CodeProject 正在变化。 阅读更多。
Home

物联网的增强现实

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.05/5 (8投票s)

2015年3月23日

CPOL

7分钟阅读

viewsIcon

19949

downloadIcon

185

物联网设备需要具备增强其周围环境的能力,即使它们使用的传感器发生故障。

引言

我们试图解决的问题是增强物联网设备的感官感知能力,当一个传感器退役或发生故障时,对其进行补充。一个可能的例子是,当我们使用手机作为办公室大楼内的主要定位器时。当我们放错手机时,我们识别的位置就不准确了(例如,一个位于手机所在位置的基于物联网的咖啡机,会突然启动为我们冲咖啡,但我们已经不在那个位置了)。然而,通过使用增强现实的物联网平台,物联网设备将能够利用先验知识和其他物联网设备提供的感官感知来识别我们的位置。

为了解决这个问题,我们将使用 Azure 基础设施作为 PaaS(平台即服务)来构建一个为连接到该平台的物联网设备提供增强感官感知的平台。

背景

对微处理器和 Azure 平台的背景了解将有助于理解此参考架构教程的核心。本教程尽可能地简化,以便读者能够掌握构建物联网设备 PaaS 解决方案的基础知识。

使用代码

解决方案文件中提供的代码是 PaaS 参考架构的代码。这是一个 POC(概念验证),用于构建一个物联网 PaaS 平台,通过预测性分析来增强传感器数据。

基于 Arduino 的传感器网络

对于这个 POC,我们将使用基于 Arduino 的网络和运动传感器。每个收发器在下面的 Arduino 草图中都通过 CHILD_ID 分配了一个唯一的 ID。

使用 Nrf24l01 无线收发器

用于运动传感器的 Arduino 草图,通过 HC-SR501 运动传感器捕捉位置。有关连接传感器的详细信息,请参阅 http://www.mysensors.org/build/motion

#include 
#include 

unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds)
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID 1   // Id of the sensor child

MySensor gw;
// Initialize motion message
MyMessage msg(CHILD_ID, V_TRIPPED);

void setup()  
{  
  gw.begin();

  // Send the sketch version information to the gateway and Controller
  gw.sendSketchInfo("Motion Sensor", "1.0");

  pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
  // Register all sensors to gw (they will be created as child devices)
  gw.present(CHILD_ID, S_MOTION);
  
}

void loop()     
{     
  // Read digital motion value
  boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
        
  Serial.println(tripped);
  gw.send(msg.set(tripped?"1":"0"));  // Send tripped value to gw 
 
  // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
  gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME);
}

基于 Arduino 的控制器网关

传感器网络通过 RF 与控制器网关通信,消息包从控制器网关发布到托管在 Azure 上的 MQTT。为了实现这一点,我们使用了托管在 https://github.com/FotoFieber/MySensors/blob/mqttclient/libraries/MySensors/examples/MQTTClientGateway/MQTTClientGateway.ino 上的 mqttclientgateway。

Raspberry PI 上的 Node.js MQTT

在 Raspberry PI 上安装 Node.js,并在 Raspberry PI 上安装 MQTT 服务器。

请参阅以下博文:http://workingmatt.blogspot.com/2014/05/install-nodejs-on-raspberry-pi.html

通过运行以下命令在 Node.js 中安装 MQTT:

npm install mosca

npm install mqtt

var mqtt    = require('mqtt');
var client  = mqtt.connect('mqtt://127.0.0.1');
 
client.on('connect', function () {
  client.subscribe('MySensor');
  client.publish('MyMQTT/#', '');
});
 
client.on('message', function (topic, message) {
  // message is Buffer 
  // call rest api - to post location
  client.end();
});

用于增强传感器的 Azure PaaS 平台

MDM(移动设备管理)

该平台 MDM 用于维护设备及其配置文件信息,分析操作可以使用这些信息来增强传感器数据。

事件摄入

事件摄入通过 PaaS 解决方案公开的 REST API 来实现,以实现平台独立性。REST API 层名为 mlidynamics.iot.io,这是一个发布到 Azure 并托管的 Web API 2.0。

我已经将 API 托管在 http://mlidynamics-iot.azurewebsites.net/Help。我们将从我们的解决方案发布到 Azure 订阅中 -

mlidynamics.iot.io.publish.part_1

因此,我们需要连接到互联网的物联网设备来访问此 API 并发布事件。示例文本格式如下:

{
  "DeviceId": "90bec401-36da-4750-a07e-7c666767190f",
  "Channel": "sample string 2",
  "Location": 3,
  "Temperature": 4.1,
  "Humidity": 5.1,
  "PresenceDetected": 6
}

然后,事件被发布到也托管在 Azure 上的事件中心。设备通过 MDM 中注册的设备 ID 进行保护。安全性对于用于患者监护的物联网设备至关重要,本架构在设计时已考虑了这一点。附加解决方案中的代码已简化,以便广大读者能够阅读本文。可以根据实现域的需求扩展该解决方案。

[Route("Publish")]
        public async Task Publish(TelemetryModel message)
        {
            // do processing here
            var jsonString = JsonConvert.SerializeObject(message);

            _client.Send(new EventData(Encoding.UTF8.GetBytes(jsonString))
            {
                PartitionKey = "0"
            });

            return Ok();
        }

已在 Azure 上设置通知中心,该中心能够摄入数百万个事件。根据本文档,事件由托管在 Raspberry PI 上的 Node.js 生成,该 Raspberry PI 是物联网传感器设备的控制器。

引用

通知中心消除了一个主要复杂性:您不必处理推送通知的挑战。相反,您可以使用通知中心。通知中心使用一个全多平台、大规模的推送通知基础设施,并大大减少了在应用程序后端运行的特定于推送的代码。通知中心实现了推送基础设施的所有功能。

使用事件中心的好处

  • 每秒记录数百万个事件
  • 简单的授权机制
  • 基于时间的事件缓冲
  • 弹性扩展
  • 可插入其他云服务的适配器


使用事件中心的缺点

  • 没有 Service Bus Topic 的所有功能(但可以接受)
  • 事件数据的大小限制为 256KB(大小非常合适)
  • 分区数量最多限制为 32

Microsoft 网站上有关于设置 Azure 通知中心的充足文档。在此,我设置了一个名为“mlidynamics-iot-telemetry”的通知中心。这是 REST API 发布事件的中心。

private readonly EventHubClient _client =
            EventHubClient
                .CreateFromConnectionString(ConfigurationManager.AppSettings[@"Microsoft.ServiceBus.ConnectionString"],
                    "mlidynamics-iot-telemetry");

一旦这些事件发布到通知中心,我将使用流分析(另一个 Azure 组件)来近乎实时地处理事件,并将其暂存到 Azure SQL 数据库。

引用

流分析提供与事件中心的即时集成,能够每秒摄入数百万个事件。事件中心和流分析共同使您能够处理海量的实时数据,从而能够实时做出业务决策。

为这个 POC 编写了一个简单的流查询,以创建由连接到 RF 发射器和接近传感器的 Arduino 发送的远程 IoT 传感器发送的位置信息。此查询将创建当有人靠近传感器时传感器触发的频率计数。

SELECT 
    DeviceId, Location, DateAdd(minute,-15,System.TimeStamp) as WinStartTime,
    System.Timestamp as WinEndTime, Count(*) as EventCount
    FROM [telemetry-input]
    group by TumblingWindow( minute , 15 ), DeviceId, Location

流分析将聚合结果并将其存储在 Azure SQL 存储中。用于捕获聚合的架构,

USE [mlidynamics-iot]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[LocTelemetry] (
    [DeviceId]     CHAR (54)     NULL,
    [Location]     BIGINT        NULL,
    [WinStartTime] DATETIME2 (6) NULL,
    [WinEndTime]   DATETIME2 (6) NULL,
    [EventCount]   BIGINT        NULL
);


GO
CREATE CLUSTERED INDEX [LocTelemetry]
    ON [dbo].[LocTelemetry]([DeviceId] ASC);

Azure ML(机器学习)用于预测分析

使用 Azure ML(Azure 机器学习)根据流分析生成的时间序列传感器数据中的位置来预测最近的位置。机器学习预测特定时间窗口内的最近位置。在此 POC 中,我将时间窗口细分为 15 分钟间隔。特征是基于一周、分钟的计划构建的,以满足机器学习算法所需的训练集。当有人靠近时,流分析会创建传感器触发次数的频率计数。构建的分析是细分为 15 分钟间隔的时间序列。利用时间和位置,我们可以预测一个人的最近位置,该人的时间表已用于训练。利用机器学习,我们通过预测位置来增强传感器数据。传感器没有位置的概念,只有事件是否发生的概念。

Azure ML 公开的 REST API

 https://ussouthcentral.services.azureml.net/workspaces/84c646bc34b0432d82f03dd5c236b66f/services/79793a0a274b44a7b74aa6336dacefaf/execute?api-version=2.0&details=true
    

在 POST REST API 调用中使用的请求 JSON

    {
  "Inputs": {
    "input1": {
      "ColumnNames": [
        "wk",
        "hr",
        "loc",
        "closest loc"
      ],
      "Values": [
        [
          "0",
          "0",
          "value",
          "value"
        ],
        [
          "0",
          "0",
          "value",
          "value"
        ]
      ]
    }
  },
  "GlobalParameters": {}
}

从 REST API 调用获得的响应 JSON

{
  "Results": {
    "output1": {
      "type": "DataTable",
      "value": {
        "ColumnNames": [
          "wk",
          "hr",
          "loc",
          "Scored Labels",
          "Scored Probabilities"
        ],
        "ColumnTypes": [
          "Numeric",
          "Numeric",
          "String",
          "String",
          "Numeric"
        ],
        "Values": [
          [
            "0",
            "0",
            "value",
            "value",
            "0"
          ],
          [
            "0",
            "0",
            "value",
            "value",
            "0"
          ]
        ]
      }
    }
  }
}

可用于通过调用 Azure ML 公开的 REST API 来预测位置的示例代码

// This code requires the Nuget package Microsoft.AspNet.WebApi.Client to be installed.
// Instructions for doing this in Visual Studio:
// Tools -> Nuget Package Manager -> Package Manager Console
// Install-Package Microsoft.AspNet.WebApi.Client

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace CallRequestResponseService
{

    public class StringTable
    {
        public string[] ColumnNames { get; set; }
        public string[,] Values { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            InvokeRequestResponseService().Wait();
        }

        static async Task InvokeRequestResponseService()
        {
            using (var client = new HttpClient())
            {
                var scoreRequest = new
                {

                    Inputs = new Dictionary () { 
                        { 
                            "input1", 
                            new StringTable() 
                            {
                                ColumnNames = new string[] {"wk", "hr", "loc", "closest loc"},
                                Values = new string[,] {  { "0", "0", "value", "value" },  { "0", "0", "value", "value" },  }
                            }
                        },
                                        },
                                    GlobalParameters = new Dictionary() {
}
                };
                const string apiKey = "abc123"; // Replace this with the API key for the web service
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", apiKey);

                client.BaseAddress = new Uri("https://ussouthcentral.services.azureml.net/workspaces/84c646bc34b0432d82f03dd5c236b66f/services/79793a0a274b44a7b74aa6336dacefaf/execute?api-version=2.0&details=true");
                
                // WARNING: The 'await' statement below can result in a deadlock if you are calling this code from the UI thread of an ASP.Net application.
                // One way to address this would be to call ConfigureAwait(false) so that the execution does not attempt to resume on the original context.
                // For instance, replace code such as:
                //      result = await DoSomeTask()
                // with the following:
                //      result = await DoSomeTask().ConfigureAwait(false)


                HttpResponseMessage response = await client.PostAsJsonAsync("", scoreRequest);

                if (response.IsSuccessStatusCode)
                {
                    string result = await response.Content.ReadAsStringAsync();
                    Console.WriteLine("Result: {0}", result);
                }
                else
                {
                    Console.WriteLine("Failed with status code: {0}", response.StatusCode);
                }
            }
        }
    }
}

测试该网络服务,以根据我们拥有的时间序列数据预测位置。在此测试中,我们试图在周的第一周、第一个小时和第 30 秒找到位置,假设此时研究中的传感器被触发,并且最接近的位置是卧室。

结果表明,根据传感器读数,客厅是最近的位置。

关注点

大多数 Azure 组件都是预览版本,并且有其不足之处。本文侧重于使用 Azure 中现成的组件来完成本文所描绘的 POC。特别是,本文档力求简洁,并提供了构建自定义物联网 PaaS 解决方案的指导要点。管理数百万个物联网消息并处理数据流总是具有挑战性的。重点在于指出构建物联网 PaaS 平台所需的组件。Azure 等云服务有助于快速创建平台。

历史

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.