Windows Azure

CyberNanny:通过分布式组件实现远程访问

Angel Hernandez Hernandez

下载代码示例

这篇文章是关于应用程序调用 CyberNanny,其中最近写,请允许我以远程查看我的宝贝女儿米兰达在家里从任何地方的任何时候。 它写在 Visual c + + (MFC),它包括不同的技术,如 Kinect 和 SDK,Windows Azure、 Web 服务和通过 Outlook 的办公自动化。 该项目位于 CodePlex (cybernanny.codeplex.com),您可以在签出代码或对它作出贡献。

我进入螺母和螺栓的应用程序之前,我来简要地解释来建造它所采用的技术。

C + + 已 — — 仍然是 — — 在许多软件商店健将。 新的标准 c + + 11 说,将语言带到一个新的水平。 三个词来描述它会是现代、 优雅和速度极快。 此外,MFC 是仍左右,微软已被升级它的每个新版本的 Visual c + + 编译器。

Kinect 技术很神奇,至少可以说,; 它改变我们与游戏和计算机进行交互的方式。 而微软为开发商提供一个 SDK,一个新世界的机会就亮相创建需要的人机交互的软件。 有趣的是,虽然 Kinect SDK 基于 COM (以及新的编程模型,在 Windows 8,称为 Windows 运行时,通常缩写为 WinRT)。 此外可以使用 Microsoft.net 框架语言 SDK。

Windows Azure 是作为一种服务 (PaaS) 的 Microsoft 平台,提供的已有几年。 它提供了一系列的服务,使建筑物在其上 (如计算和存储) 的解决方案。 我在 CyberNanny 的要求之一就是通过一个高度可用的队列,消息的可靠的传递和 Windows Azure 提供的。

可以使用 Windows Web 服务 API (WWSAPI),是推出 Windows 7 的本机使用与 Web 服务的消费。 我有一篇博客文章 (bit.ly/LiygQY),描述了 Windows 的演示文稿基础 (WPF) 应用程序实现使用 WWSAPI 的本机组件。 很重要,何况 WWSAPI 内置于操作系统,所以无需下载或安装任何事,除了 Windows SDK (对于页眉和 lib 文件)。

何必要从头开始呢? 其中一项规定 CyberNanny 是发送带附带照片的电子邮件的能力,所以而不是写我自己的电子邮件类,我倾向于重用此任务的 Outlook 提供的功能。 这让我专注的主要目标:建立分布式应用程序照顾我的孩子。

这篇文章分为四个主要部分:

  1. 一般建筑解决方案的概述
  2. Kinect 的体系结构
  3. 本地部署的组件 (本机)
  4. 云托管组件 (托管)

一般建筑解决方案的概述

CyberNanny 概念很简单 (如中所示图 1),但它也有一些感人的作品。 它可以简要描述为写在 Visual c + +,捕获帧通过 Kinect 传感器的胖客户端中。 以后可以作为图片附加到新的电子邮件,通过自动化组成在 Outlook 中使用这些帧。 应用程序通知的产卵的计时器,轮询队列寄宿在 Windows Azure 触发一个线程挂起的请求有关。 请求插入到该队列通过 ASP.NET Web 页中。

CyberNanny Architecture
图 1 CyberNanny 体系结构

请注意,为了运行和测试的解决方案,您必须:

  • Kinect 传感器 (我用我在 Xbox 360 上的一个)
  • Windows Azure 订阅
  • Kinect SDK

Kinect 体系结构

有的东西是如何工作和如何实施好建筑了解至关重要的发展项目,而在这种情况下 Kinect 也不例外。 微软为托管代码和本机代码的开发人员提供了一个 SDK。 我将描述 Kinect 建成后,该体系结构,如中所示图 2

Kinect for Windows Architecture
图 2 Kinect Windows 体系结构

图 2 中圆圈中的数字对应于以下内容:

  1. Kinect 硬件:硬件组件,包括 Kinect 和通过该传感器连接到计算机的 USB 集线器。
  2. Kinect 的驱动程序:Windows 驱动程序的 Kinect,其中作为 SDK 安装过程的一部分进行安装,这篇文章中所述。 Kinect 驱动程序支持:
    • 作为一个内核模式的音频设备,您可以通过在 Windows 中的标准音频 Api 访问的 Kinect 麦克风阵列。
    • 音频和视频流的流音频和视频 (颜色、 深度和骨架) 的控件。
    • 使应用程序可以使用多个 Kinect 的设备枚举函数。
  3. 音频和视频组件:Kinect 自然用户界面 (NUI) 为骨架的跟踪、 音频、 颜色和深度成像技术。
  4. DirectX 媒体对象 (DMO):这是麦克风阵列波束形成和音频源定位。
  5. Windows 7 标准 API:音频、 演讲和媒体在 Windows 7 中,Windows 7 SDK 和 Microsoft 语音 SDK 中所述的 Api。

我将演示如何我用于视频组件捕获的帧,然后将保存为 JPEG 文件的电子邮件的目的。 捕获的帧的呈现方式是通过 Direct2D 完成的。

Nui_Core 类写了一个类名为 Nui_Core,其中封装我从 Kinect 传感器所需的功能。 有此对象在应用程序中的单个实例。 通过 INuiSensor,它表示的物理设备连接到计算机的类型的成员与传感器,该应用程序进行交互。 它是重要的是要记住 Kinect SDK 是基于 COM 的因此,上述的界面 — — 以及一切其他 COM 接口用于整个应用程序 — — 由智能指针 (例如,CComPtr <INuiSensor> m_pSensor;)。

要启动与传感器捕获帧的步骤如下:

  1. 请检查是否有可用的传感器通过调用 NuiGetSensorCount。
  2. 通过调用 NuiCreateSensorByIndex 创建的 Kinect 传感器的实例。
  3. 工厂为创建对象的 Direct2D 资源创建通过调用 D2D1CreateFactory。
  4. 创建所需的应用程序的每个流的事件。
  5. 通过调用 NuiImageStreamOpen 打开流。
  6. 将捕获的数据 (帧) 的过程。

一旦 Nui_Core 实例的设置,您可以轻松地图片对采取需求通过调用 TakePicture 方法,如中所示图 3

图 3 TakePicture 方法

void Nui_Core::TakePicture(std::shared_ptr<BYTE>& imageBytes, int& bytesCount) {
  byte *bytes;
  NUI_IMAGE_FRAME imageFrame;
  NUI_LOCKED_RECT LockedRect;
  if (SUCCEEDED(m_pSensor->NuiImageStreamGetNextFrame(m_hVideoStream,
    m_millisecondsToWait, &imageFrame))) {
    auto pTexture = imageFrame.pFrameTexture;
    pTexture->LockRect(0, &LockedRect, NULL, 0);
    if (LockedRect.Pitch != 0) {
      bytes = static_cast<BYTE *>(LockedRect.pBits);
      m_pDrawColor->Draw(bytes, LockedRect.size);
    }
    pTexture->UnlockRect(0);
    imageBytes.reset(new BYTE[LockedRect.size]);
    memcpy(imageBytes.get(), bytes, LockedRect.size);
    bytesCount = LockedRect.size;
    m_pSensor->NuiImageStreamReleaseFrame(m_hVideoStream, &imageFrame);
  }
}

注意您通过将图像,以及将被复制到它的字节数的字节存储的智能指针,然后使用此信息来手工你位图。

这是重要的是要提到一旦您已经使用传感器完,它必须通过调用 NuiShutdown,关闭和被使用的句柄需要释放。

DrawDevice 类如先前所述,由 Direct2D ; 提供呈现功能 这就是为什么支持另一类是需要与 Nui_Core 一起使用。 此类是负责确保有资源可供捕获的帧,如位图,在这种情况下。

初始化、 绘制和 EnsureResources 的三种主要方法。 我将描述每个。

初始化:这是负责设置三种类型的成员的 DrawDevice。 应用程序有三个选项卡上,使用选项卡控件,所以有成员,每个选项卡 (颜色、 Skeletal 和深度视图)。 每个选项卡是一个窗口,则负责呈现其相应的框架。 下面的代码所示的 InitializeColorView 是一个好例子的调用初始化方法:

bool Nui_Core::InitializeColorView() {
  auto width = m_rect.Width();
  auto height = m_rect.Height();
  m_pDrawColor = std::shared_ptr<DrawDevice>(new DrawDevice());
  return (m_pDrawColor.get()->Initialize(m_views[TAB_VIEW_1]->m_hWnd,
  m_pD2DFactory.p, 640, 320, NULL));
}

绘制:这将呈现正确选项卡上的帧。 它作为参数的字节 * 由传感器捕获。 就像电影、 动画的影响来自静态帧的连续呈现。

EnsureResources:这是负责创建一个位图时绘制方法请求的。

本地部署的组件 (本机)

CyberNanny 项目包括以下内容:

  • 应用程序
    • CCyberNannyApp (CWinApp 从继承)。 应用程序具有与传感器进行交互的单个成员的类型 Nui_Core。
  • UI 元素
    • CCyberNannyDlg (主窗口,从 CDialogEx 继承)
    • CAboutDlg (关于对话框,从 CDialogEx 继承)
  • Web 服务客户端
    • 对一项服务,Web 服务描述语言 (WSDL) 执行 WSUTIL 后自动生成的文件。 这些文件包含邮件、 结构和 WCF Web 服务所公开的方法。
  • Outlook 对象类
    • 为了操纵某些 Outlook 对象,您必须将其导入到您的项目通过从 ActiveX 控件向导中选择"添加 MFC 类"。 在此解决方案中使用的对象在应用程序中,附件,邮件项目和 Namespace。
  • 代理
    • 这是一个封装的与 WWSAPI 进行交互所需的对象创建的自定义类。
  • 帮助器类
    • 这些类用于支持功能的应用程序,例如将位图转换为 JPEG 来减小文件大小,提供一个包装要发送的电子邮件和交互方式使用 Outlook,等等。

当应用程序启动时,会发生以下事件:

  1. 新窗口消息是通过调用登记册 WindowMessage 定义的。 这是用于将项添加到事件处理请求时的列表。 这是必需的因为您不能直接修改从不同的 UI 线程的线程的 UI 元素,或者你会招致非法的跨线程调用。 这是由 MFC 消息基础结构管理。
  2. 您初始化您的 Nui_Core 成员,并设置几个计时器 (一个用于更新状态栏,另一种的序幕轮询队列,以检查是否存在挂起的请求的线程的当前时间)。
  3. Kinect 传感器启动捕获的帧,但应用程序不会照一张相,除非有一个请求在队列中。 ProcessRequest 方法负责拍照,序列化到磁盘,事件查看器写入和开球 Outlook 自动化,如中所示的图片图 4

图 4 ProcessRequest 方法调用

void CCyberNannyDlg::ProcessRequest(_request request) {
  if (!request.IsEmpty) {
    auto byteCount = 0;
    ImageFile imageFile;
    std::shared_ptr<BYTE> bytes;
    m_Kinect.TakePicture(bytes, byteCount);
    imageFile.SerializeImage(bytes, byteCount);
    EventLogHelper::LogRequest(request);
    m_emailer.ComposeAndSend(request.EmailRecipient,
    imageFile.ImageFilePath_get());
    imageFile.DeleteFile();
  }
}

最初由 Kinect 捕获的帧是一个约 1.7 mb 大小 (这不方便用电子邮件发送,因此需要转换为 JPEG 图像) 中的位图。 它也是上行下来,所以 180 ° 旋转是必需的。 这是通过使对 GDI + 调用几个。 此功能是在 ImageFile 类中封装的。

ImageFile 类用作包装器,用于执行使用 GDI + 的操作。 这两个主要方法是:

  1. SerializeImage:此方法采用这样 <BYTE>,其中包含已捕获帧作为图像,要序列化的字节数以及的字节的计数。 通过调用 RotateFlip 方法还旋转图像。
  2. GetEncoderClsid:如所述,图像的文件大小是太大了,作为附件使用 — — 因此,它需要被编码为较小的占地面积 (例如 JPEG) 格式。 GDI + 提供了一个 GetImageEncoders 函数,可以让你发现哪些编码器是系统中可用的。

到目前为止,我已经介绍应用程序如何利用 Kinect 传感器和如何使用捕获的帧创建为用电子邮件发送图片。 接下来,我将介绍如何调用 Windows Azure 上主持的 WCF 服务。

WWSAPI,介绍了在 Windows 7 中,允许本机开发人员消耗 Web 或 WCF 服务以方便快捷的方式,而无需担心通信 (套接字) 的详细信息。 消费服务的第一步是要有一个 WSDL 中使用的 WSUTIL,进而将产生的服务代理,它是服务所需的数据结构的代码生成器的 C 代码。 那里是称为卡萨布兰卡的替代方法 (bit.ly/JLletJ),它支持基于云计算的客户端-服务器通信在本机代码中,但当我写 CyberNanny 时,它并不是可用。

这是普遍获得 WSDL,并将它保存到磁盘,并作为输入 WSUTIL,然后使用 WSDL 文件和相关的架构文件。 需要考虑的一个方面是架构。 他们必须下载和 WSDL,否则 WSUTIL 会抱怨时生成的文件。 通过检查中的 WSDL 文件的架构部分的.xsd 参数,您可以轻松确定所需的架构:

wsutil /wsdl:cybernanny.wsdl /xsd:cybernanny0.xsd cybernanny1.xsd cybernanny2.xsd cybernanny3.xsd /string:WS_STRING

生成的文件可以添加到解决方案,,然后你继续通过代码生成器文件调用您的服务。 四个主要对象都需要与 WWSAPI 一起使用:

  1. WS_HEAP
  2. WS_ERROR
  3. WS_SERVICE_PROXY
  4. WS_CHANNEL_PROPERTY

这些对象允许在客户端和服务之间的相互作用。 我把在一起放在调用代理类中的服务的功能。

大部分的 WWSAPI 函数返回 HRESULT,因此调试错误可以是一个具有挑战性的任务。 但怕未必,因为您可以启用从 Windows 事件查看器跟踪并查看给定的函数失败的确切原因。 要启用跟踪,请导航到应用程序和服务日志 |微软 |Web 服务 |跟踪 (右键单击它,使它)。

这差不多覆盖了该解决方案的本机组件。 有关详细信息,请参阅上述 CodePlex 网站上的源代码。 下一节是关于解决方案的 Windows Azure 组件。

云托管组件 (托管)

请注意这不是广泛的教程,Windows Azure,但相当的 CyberNanny 中的 Windows Azure 组件的说明。 深入、 详细的详细信息,请参阅 Windows Azure Web 站点 windowsazure.com。 Windows Azure 平台 (图 5) 包括以下服务:

  • Windows Azure 计算
  • Windows Azure Storage
  • Windows 天青 SQL 数据库
  • Windows Azure AppFabric
  • Windows 天青市场
  • Windows 天蓝色的虚拟网络

Windows Azure Platform Services
图 5 Windows 天青平台服务

CyberNanny 仅有一个已分配两个内核,以保证高可用性的 Web 角色。 如果其中一个节点出现故障,该平台将切换到健康节点。 ASP.NET 应用程序,网站角色,它只插入一个队列的邮件项目。 这些消息从 CyberNanny 然后弹出。 另外还有一个 WCF 服务,它是负责处理该队列的 Web 角色的一部分。

注意 Windows Azure 角色是云计算的每个实例与相对应的乌云中运行的虚拟机 (VM) 实例的单个组件。 然后,在 CyberNanny 的情况下,我已经分配两个虚拟机。

CyberNanny 有一个是 (无论它是只 ASPX 页或 WCF 服务) 的 Web 应用程序的 Web 角色在 IIS 上运行。 它是可通过 HTTP/HTTPS 终结点进行访问。 也有另一种类型的角色,被称为一个工人的角色。 这是处理应用程序 (例如,对于财务计算),背景和它还能够公开面向 Internet 的和内部的终结点。

此应用程序还利用提供的 Windows Azure 存储,从而允许可靠的存储和传递的邮件的队列。 您不必编写任何专门的代码,以利用它美丽的队列。 既不是你负责设立的具有特定结构的数据存储,类似于一个队列,因为这所有的功能都现成的平台提供的。

高可用性和可扩展性,除了 Windows Azure 平台所提供的优点之一就是开发、 测试和部署 Windows Azure 解决方案从 Visual Studio 中,以及作为共同语言了.net 等事情要生成的解决方案的共性。

有爱运动检测和语音识别等将添加到 CyberNanny,其他一些很酷的功能。 如果您想要使用本软件或对该项目作出贡献,请随时自由地这样做。 所采用的技术目前可用,即使它们看上去"不同的",他们可以进行互操作,并与另一个很好地发挥。

祝您工作愉快!

Angel Hernandez Matos 是 Avanade 澳大利亚在企业应用程序团队经理。他设在悉尼,澳大利亚,但最初是从委内瑞拉的加拉加斯。他已连续八年被 Microsoft MVP 奖得主,目前在 Visual c + + 中的 MVP。他一直在写软件由于他 12 岁那年,认为自己"生存的狂人"。

衷心感谢以下技术专家对本文的审阅:斯科特 · 贝瑞、 圣地亚哥 Dagum、 Yonghwi Kwon 和 Nish Sivakumar