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

RestaurantWatcher - 使用 Azure 的 IoT 项目

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2015年2月26日

CPOL

7分钟阅读

viewsIcon

17306

通过 Azure 将 Intel RealSense 设备连接到远程用户。

引言

本文阐述了通过云端应用程序(基于Azure)使用“事物”向第三方传递信息的一种方式。具体的实现方式可能有所不同,但它展示了一个通用的模式,这种模式在许多实现中都会出现。

背景

在我为英特尔RealSense(tm) 2014挑战赛撰写参赛作品时,我意识到一个问题:我将项目设想为一个三层系统,其中连接其他两层的组件将托管在IIS上。然而,这将需要一个比评审员熟悉的更复杂的安装过程。

所以我决定研究云解决方案。由于我已经在用C#和Visual Studio 2013社区版,我好奇将我最初的想法迁移到Azure托管的Web服务上会有多容易。

结果非常容易。

Using the Code

项目分为三个部分

  1. Garcon:使用英特尔RealSense(tm)设备检测不同的动作(语言和视觉)。每当检测到动作时,Garcon就会向中央组件(Azure上的工作流服务)发送信号。在下面的图片中,可以看到Garcon的主视图(当然不包含摄像头本身)。

    Main Garcon view

  2. Maitre:两个工作流,嵌入在Azure工作流服务中。它们跟踪桌子的当前状态,如果检测到有效更改或出现适当情况,它们会向Watcher发送信号。 

    Waiter States Diagram

    转换(例如“客户呼叫”)包含远程客户端(“事物”)和工作流之间的交互点。这些需要通过使用可调用接口来定义。

    Transition Properties view

    为了保留上下文,这些接口会传入一个输入参数,当在关联定义中使用时,它将帮助工作流使用正确的实例。 

    CorrelatesOn Definition

  3. Watcher:只显示它接收到的信息。同样,由于其简单性,它可以很容易地适应任何平台。例如,智能手机可以订阅该服务并向携带它的服务员显示消息,提醒他他负责的餐桌上的情况,而不是Windows Forms应用程序。

     

正如我在引言中提到的,我的第一个任务是将工作流服务转换为Azure平台。这个任务实际上非常简单。我打开项目,选择菜单项目->转换为Microsoft Azure云服务项目

Convert to Cloud Service

这会在解决方案中生成一个云服务项目,右键单击该项目可以将其打包或直接发送到您的Azure云。

Uploading Service

要上传您的服务,您需要创建一个新的Azure Web服务(接下来的两张图片)

Create Service

Creating Service, continued

完成以上步骤后,您的云服务已创建。现在您可以访问您的Azure门户下载Azure SDK以调试和使用您的Azure站点。您的CloudService的登陆页面应类似于下图所示

Azure Toolset

使用“安装Windows Azure SDK”链接下载工具。安装完成后,您可以右键单击Azure服务项目并选择“调试”来调试项目。这将启动Azure模拟器(计算和存储模拟器)。

Azure Debug Launch

在图片中,您会注意到我的项目实际上是在端口81上启动的(而不是通常的端口80)。原因是我在我的机器上运行着IIS,这会阻止模拟器在默认端口上启动。如果您正在运行IIS或者您正在使用端口80进行其他类型的部署(例如Apache HTTP服务器),您应该注意这一点,以便相应地更改客户端的配置。

为了能够快速从生产配置切换到调试配置,我在客户端的App.config中添加了如下部分(当前显示Azure生产配置为活动状态)


<!-- localhost Azure debugging -->
      <!--
        <client>
          <endpoint address="https://:81/MyService.xamlx" binding="basicHttpBinding"
             bindingConfiguration="BasicHttpBinding_IStartTable" contract="MaitreService.IStartTable" 
             name="BasicHttpBinding_IStartTable"/>
         </client>
       -->

      <!-- Azure -->
      <client>
        <endpoint address="http://example.cloudapp.net/MyService.xamlx"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IStartTable"
          contract="MaitreService.IStartTable" name="BasicHttpBinding_IStartTable" />
      </client>

尽管在配置之间切换很容易,但重要的是要记住,根据您正在工作的环境,您客户端的连接点需要进行切换。

我实现的工作流包含接收活动,这些活动在工作流上暴露了依赖于外部输入的点。引用依赖于保持关联的活动,我通过将初始工作流ID发送回调用方(使用发送活动)并将其用作每次调用工作流的参数来实现这一点。(该过程在MSDN网站上的“创建带有消息活动的工作流服务”教程中有很好的文档记录。)

Interface to Activity

为了将正确的服务引用导入我的Garcon项目,我使用了项目“添加->服务引用”右键菜单中的“服务引用”选项。您输入的地址应与您将项目加载到Azure云时指定的地址相对应。

Adding Service References

按下“确定”会创建到Azure工作流服务的引用类。如前所述,您必须检查App.config文件以验证生产和调试引用是否等效。除此之外,调用适当的类就变成了一项简单的任务。在我的例子中,例如,连接的摄像头(“Thing”)一旦其前端启动就会启动一个新的工作流。

MaitreService.StartTableClient startProxy = new StartTableClient();
p_tableId = startProxy.StartTableService(0, GetMyIpAddress().ToString());

Front end starts workflow

这让我可以在需要时立即开始检测事件,并简化了与后端通信所需的代码。例如,宣布新客人的代码减少为

MaitreService.GuestsArriveClient guestServiceProxy = new GuestsArriveClient();
guestServiceProxy.GuestsArriveAsync(p_tableId, DetectedFaces);

并由摄像头的面部检测线程触发。

我还必须考虑MaitreServiceWorkflow)和前端(Watcher)之间的交互。正如我在引言中提到的,这是一个简单的观察者模式。为了将观察者(Watcher)与主题(MaitreService)通信,我使用了WCF-双工服务实现。

  1. 在Garcon(“Thing”)程序的生命周期开始时,我会在一个可观察的“Subjects”表中进行注册。
  2. 当一个Watcher启动时,它会请求一个“Subjects”列表,然后用户从中选择一个。
  3. 从那时起,Maitre会将所有可报告的通知发送给“Subjects”(Garcon)的所有已注册ObserversWatcher)。

我选择手动启动 Maitre Service 的 WCF-Service 端。它看起来像这样

NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ReceiveTimeout = new TimeSpan(12, 0, 0);
RoleInstanceEndpoint externalEndPoint =
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["example"];
string endpoint = String.Format("net.tcp://{0}/example",
    externalEndPoint.IPEndpoint);
host = new ServiceHost(typeof(TableReporter), new Uri[] { new Uri(endpoint) });
host.AddServiceEndpoint(typeof(ITableReports), binding, endpoint);

此配置使我能够控制可见端点的生命周期,从而确保在没有活动Garcon时没有可见端点。

关注点

我在测试项目时检测到的主要问题是所选平台各方面的一些意外超时配置。例如,工作流被配置为具有默认配置,该配置在一分钟后卸载它们。由于我的工作流基本上是按照图形设计界面中看到的那样运行的,所以我决定修改它们在相应的Web.config中的卸载/持久化参数。

<workflowIdle timeToUnload="24:00:00" timeToPersist="10:00:00"/>

另一方面,Watchers 在 4 分钟后停止接收更新。对 Azure 参考文档的一些深入研究表明,负载均衡器有一个 4 分钟的空闲超时(不可配置)。我选择了实现链接文章中提到的第一个解决方案,即

引用

[1] - 确保 TCP 连接不空闲。为了保持 TCP 连接活跃,在 240 秒内持续发送一些数据。这可以通过分块传输编码实现;发送一些数据或者只发送空行以保持连接活跃。

这种方式甚至帮助我改进了我的实现,让Watcher有理由每220秒询问被监视的Subject是否仍然活跃。

我在调试环境中的经验告诉我,Azure 本地调试环境的行为几乎与云上的实际暂存区域完全相同。但是,有一些需要注意的地方

  • 地址显然不同,一些配置文件(App.configWeb.config等)的调试和生产值将根据场景而改变。
  • 一些超时,比如我上面提到的那些,不适用于本地(调试)场景,这可能导致只有在服务上传到Azure后才会出现的bug。我建议您在发布服务之前直接在云上调试它。

    Deployment options

    您不应将此选项保持开启,因为它不是任何项目的最佳配置,但它应该有助于您捕获本地调试可能隐藏的任何问题。这样做的好处是能够远程连接到您的云服务,并且仍然可以设置断点、监视和其他您习惯的调试配置,而只需最少的努力。

历史

  • 2015-02-22:初稿完成
  • 2015-03-09:改进了格式,修正了一些语法错误,并调整了图像宽度
© . All rights reserved.