Interfaz con fonera pra robot automower


Hoy todo el mundo tiene un Wi-Fi (WLAN)-router en casa conectado a Internet. Por lo tanto, parece natural para supervisar y controlar el robot Automower a través de la interfaz de radio WLAN: esto es ahora posible!
La base de hardware de la WLAN-Modul es un mini router «Fonera 2.0», tipo 2200 o 2100. Los routers  se han distribuido por cientos de miles a través de la «red FON comunidad» hasta 2008, ver http://fr.wikipedia.org/wiki/FON . Es muy fácil de encontrar en una tienda de segunda mano (ebay …)
El router Fonera se integrará dentro del robot Automower, ya sea bajo el teclado robot como en el siguiente video o cerca de la rueda derecha. Será completamente protegido del calor lluvia, la suciedad y también. Debido a su antena WiFi externo, tiene un alcance de radio muy bueno para bajo consumo de energía: 3W 150mA a 20V es aceptable en comparación con 27W consumidos por el robot en el trabajo.
Basta con echar un vistazo al siguiente video para ver lo fácil que es configurar la interfaz en pocos minutos:


La pequeña caja redonda gris la imagen siguiente es la fuente de alimentación de la fonera que está conectado con el robot a través del conector blanco de la placa madre (esta conexión es totalmente equivalente al puerto serie externo en el botom del robot, pero el conector aquí en la placa madre tiene una mejor protección contra el polvo y la humedad):

Si lo desea, también puede poner la fonera bajo el capó verde, cerca del botón de parada, de esta manera sigue siendo accesible y también se puede ver a los pequeños leds verdes por el poder y WLAN.

Para aquellos que quieren poner la fonera en la parte delantera del robot, también es posible:

Para la parte de software, todo funciona ahora como si el robot sería un elemento de la red IP. Esto significa que el robot será accesible a través de su propia dirección IP y un puerto específico en IP que se enlaza a su interfaz de serie. Por tanto, el robot se hace accesible desde cualquier lugar! Desde un PC local en el país, desde una PDA, un teléfono inteligente conectado a Internet en el otro extremo del planeta!
Vamos a empezar con el caso más simple: un seguimiento directo del robot a través de un PC local en el país. Para utilizar PC-software que controla el robot a través de una interfaz serial real, sólo tenemos que instalar el software gratuito Puerto Perle Verdadero.
Este software emula un puerto serie del PC local. Está disponible para sistemas Windows y Linux. Este puerto serie virtual será el puerto en serie del robot exactamente como si el robot se conecta directamente al PC a través de un cable serie local. En la configuración, sólo será necesario indicar la IP robots (en este caso 192.168.1.10 en el exemple) y el IP-puerto (2001).




Tan pronto como el puerto serie virtual se establece (aquí COM5), se puede probar el enlace con el robot a través de un pequeño software que muestra la temperatura y la tensión de la batería. También es posible dar algunas órdenes al robot, por ejemplo, «ir a casa!» o «ir a trabajar». Este es el ejemplo más simple de control del robot. Por supuesto, también puede controlar el robot en tiempo real si tienes una webcam fija en el robot, vea este video:http://www.youtube.com/watch?v=MqIHruVACj0 .

En lugar de verdadero puerto Perle, también puede utilizar el software libre . HW VSP3 En ese caso la configuración es aún más fácil, sólo tiene que indicar la dirección IP (192.168.1.200 en el ejemplo siguiente) y el puerto IP (2001):

Una tercera posibilidad libre e incluso con más funciones potentes parece ser EMULADOR VIRTUAL SERIAL PORT de Eterlogic, pero yo no lo he probado.

Más información aqui

Licencia Creative Commons
solo-electronicos por Carlos Rodriguez Navarro se encuentra bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0 Unported.

Un termostato inteligente en la nube de Azure


Dispositivos conectados se va a ser un gran negocio, y la comprensión de estos dispositivos va a ser muy importante para los desarrolladores .
 En la edición de junio de MSDN Magazine ( msdn.microsoft.com/magazine/jj133825 ), se explicó una serie de consideraciones y esbozó una arquitectura para la forma de gestionar los flujos de eventos y comandos desde y hacia  los dispositivos que usan Windows Azure Servicio Bus.
En este artículo,se va  a tomar las cosas un paso más allá  mostrando  el código que crea y asegura los flujos de eventos y mando.
Dado que  una comprensión real de los dispositivos integrados requiere mirar uno,  se va a construir uno y después la conexion  que hasta el bus  de servicio de Windows Azure para que pueda enviar eventos relacionados con su estado actual y controlar de forma remota a través de mensajes a través de la nube de Windows Azure.
 Hasta hace sólo unos pocos años atrás, para la construcción de un pequeño dispositivo con una fuente de alimentación, un microcontrolador y un conjunto de sensores  era  necesario un poco de habilidad en el diseño de hardware electrónico, así como para poner todo junto, por no hablar de buen dominio de la soldador. 

Pero debido a la aparición de plataformas de prototipado como Arduino / o Netduino. Gadgeteer NET, se puede poner ahora juntos en un pequeño dispositivo completamente funcional, aprovechando las habilidades existentes de programación.

 En este articulo se trata de diseñar un «acondicionador de aire» en la forma de un ventilador controlado por termostato, donde el ventilador es la parte menos interesante desde el punto de vista eléctrico.

 Los componentes del proyecto se basan en el modelo Gadgeteer NET, implicando una placa base con un microcontrolador, una memoria y una variedad de módulos conectables .


La placa base para el proyecto es un tablero de GHI Electronics Araña FEZ con los módulos de ampliación siguientes:

  •  De GHI Electronics Ethernet J11D módulo para proporcionar una red cableada (un módulo Wi-Fi existe) DP
  •  Módulo USB Client como fuente de alimentación y puerto USB para la implementación Joystick para el control directo del dispositivo 
  • Desde Studio Seeed Sensor de temperatura y humedad Relés para cambiar el ventilador encendido o apagado
  •  Pantalla OLED para mostrar el estado actual 



En conjunto, estas piezas cuestan alrededor de $ 230. Eso es obviamente más que soldar componentes equivalentes sobre un tablero,
 Además, este es un mercado que está empezando a ponerse en marcha, por lo que esperan que los precios bajan como la base amplía.
 Para hacer que los componentes cobren vida se necesitara  Visual C # 2010 Express (versión gratuita completamente funcional de VStudio  c#), el. NET Micro Framework SDK y el SDK Gadgeteer de GHI Electronics o Seeed.

Figura 1 Diseño del dispositivo en el Gadgeteer. NET

 La figura 1 muestra la vista de diseño del programa Gadgeteer. NET en Visual Studio.   El archivo con la extensión. Gadgeteer contiene un modelo XML que es visualizado en el editor. Desde ese archivo XML, la herramienta Gadgeteer genera automáticamente una clase del Programa parcial con contenedores para cada uno de los módulos conectados a la placa base.
Su código se encuentra en el programa. cs celebrar otra parte de la clase de programas, al igual que el modelo de código subyacente que está familiarizado con entre sí. API NET.

 Se utiliza el. NET Micro Framework con estos dispositivos. Es una versión de código totalmente abierto de la plataforma Microsoft. NET Framework que se ha creado específicamente para dispositivos pequeños con limitado poder de cómputo y memoria no mucho.

Debido a que el marco es una capa sobre el hardware nativo del dispositivo y el dispositivo no es un ordenador de propósito general con un sistema operativo que maneja toda la abstracción de hardware (en realidad no hay OS aquí), la versión del marco se puede utilizar con un dispositivo depende del fabricante de la placa de soporte de los requisitos previos, lo cual es, obviamente, muy diferente de la experiencia de una PC regular, donde particularidades de hardware están muy lejos de las cosas como de alto nivel como el Marco. NET.

 Hay varias otras diferencias en comparación con el normal. NET, y la plataforma PC en general, que son-procedente de un PC de fondo inicialmente sorprendente. Por ejemplo, el dispositivo aquí no tiene una batería de a bordo.

 Como no hay batería para el buffer de reloj,  el dispositivo no tiene idea de la hora real  cuando se despierte.

 A falta de un sistema operativo, y con una pantalla de extensión de otro fabricante, el dispositivo también no tiene fuentes a bordo que puede utilizar para dibujar cadenas para mostrar. Si desea mostrar una cadena, usted tendrá que agregar una fuente a hacerlo.

 Del mismo modo, el dispositivo no tiene predefinido, Windows Update mantenido almacén de certificados. Si desea validar los certificados SSL / TLS, que tendrá que desplegar al menos los certificados de CA raíz en el transcurso del dispositivo y de que va a también tiene que tener la hora actual para comprobar la validez del certificado.

 Como ya has adivinado podría, el manejo de los certificados representa un poco de un obstáculo para estos dispositivos, así como los requisitos para la criptografía SSL / TLS son tan importantes en términos de cálculo esfuerzo, el consumo de memoria y huella de código que no todos los dispositivos pueden apoyarlos. Sin embargo, porque la seguridad es claramente cada vez más importante, incluso en este espacio como los dispositivos deben comunicarse a través de Internet, la versión 4.2 del Framework. NET Micro aporta mejoras significativas para SSL / TLS para dispositivos que tienen recursos suficientes para manejar la situación.


. Termostato Funciones Implementar la funcionalidad termostato local para esta muestra es bastante sencillo. Voy a comprobar la temperatura y la humedad en una programación con el sensor y cambiar el ventilador conectado a través de uno de los puertos de relé apagado o encendido cuando la temperatura cae por debajo o por encima de un determinado umbral. El estado actual se visualiza en la pantalla OLED y la palanca de mando permite ajustar la temperatura objetivo manualmente. Mientras comienzo del dispositivo, voy a cablear eventos a un temporizador para activar las lecturas de temperatura y para leer los eventos de la palanca de mando.

Cuando se presiona la palanca de mando, voy a suspender el temporizador, comprobar la temperatura objetivo de acuerdo con la posición del joystick , solicite inmediatamente una nueva lectura de temperatura del sensor y reanudar el temporizador. cuando finaliza la lectura de temperatura, el evento se TemperatureHumidityMeasurementComplete planteada por el sensor. entonces a almacenar las lecturas actuales y ajustar el estado del relé para conmutar el ventilador si necesario. Esa es la medida de la lógica de termostato, que se muestra en parte en la Figura 2.

 Figura 2 Lectura de Temperatura y Humedad

  1.  
  2.           void WireEvents()
  3. {
  4.   this.InitializeTemperatureSensor();
  5.   this.InitializeJoystick();
  6. }
  7. void InitializeTemperatureSensor()
  8. {
  9.   this.temperatureCheckTimer = new Timer(5000);
  10.   this.temperatureCheckTimer.Tick += (t) =>
  11.     this.temperatureHumidity.RequestMeasurement();
  12.   this.temperatureCheckTimer.Start();
  13.     this.temperatureHumidity.MeasurementComplete 
  14.     += this.TemperatureHumidityMeasurementComplete;
  15. }
  16. void InitializeJoystick()
  17. {
  18.   this.joystick.JoystickPressed += this.JoystickPressed;
  19. }
  20. void JoystickPressed(Joystick sender, Joystick.JoystickState state)
  21. {
  22.   this.temperatureCheckTimer.Stop();
  23.   var jStick = this.joystick.GetJoystickPostion();
  24.   if (jStick.Y < .3 || jStick.X < .3)
  25.   {
  26.     settings.TargetTemperature -= .5;
  27.     StoreSettings(settings);
  28.   }
  29.   else if (jStick.Y > .7 || jStick.X > .7)
  30.   {
  31.     settings.TargetTemperature += .5;
  32.     StoreSettings(settings);
  33.   }
  34.   this.RedrawDisplay();
  35.   this.temperatureHumidity.RequestMeasurement();
  36.   this.temperatureCheckTimer.Start();
  37. }
  38. void TemperatureHumidityMeasurementComplete(TemperatureHumidity sender, 
  39.   double temperature, double relativeHumidity)
  40. {
  41.   var targetTemp = settings.TargetTemperature;
  42.   this.lastTemperatureReading = temperature;
  43.   this.lastHumidityReading = relativeHumidity;
  44.   this.relays.Relay1 = (lastTemperatureReading > targetTemp);
  45.   this.RedrawDisplay();
  46. }
  47.       



 Cada vez que ajuste la temperatura deseada en el método JoystickPressed, se guarda el valor nuevo en el campo de la clase Program ‘ajustes y llamar StoreSettings. El campo de configuración es de tipo applicationSettings, una clase serializable en el código de dispositivo que mantiene todo el equipo necesario recordar a través de las renovaciones y los ciclos de potencia.

Para almacenar persistentemente los datos, el Marco. NET Micro se reserva algunas páginas de almacenamiento en la memoria no volátil del dispositivo y permite el acceso a este almacenamiento a través de la clase ExtendedWeakReference
. No creo que sea intuitivo hasta que reconozcas que es ante todo un mecanismo para intercambiar datos de la memoria principal a presión, y convenientemente se dobla como una función de almacenamiento. La clase contiene referencias débiles a objetos, tal como el WeakReference regular lo hace en el marco. NET, sino que intercambiar los datos para el almacenamiento no volátil en lugar de descartarlo una vez que el recolector de basura, vuelve.

Dado que los datos se intercambian fuera de la memoria principal, tiene que ser serializado para el almacenamiento, lo que explica por qué la clase applicationSettings (que veremos más tarde se utiliza cuando hablamos de aprovisionamiento) necesita ser serializable. Recuperación de un objeto a partir de su lugar de almacenamiento o la creación de una ranura de almacenamiento nuevo con el método RecoverOrCreate requiere especificar un identificador único. Sólo tengo un objeto de almacenar, así que voy a usar un identificador fijo (cero).
 Después de que el objeto se ha almacenado y una vez recuperado, las actualizaciones deben ser obligados a regresar a almacenamiento mediante el método PushBackIntoRecoveryList en la instancia ExtendedWeakReference, así que eso es lo que hago en StoreSettings para eliminar los cambios, como se muestra en la figura 3.

  1.           static ApplicationSettings GetSettings()
  2. {
  3.   var data = ExtendedWeakReference.RecoverOrCreate(
  4.     typeof(ApplicationSettings),
  5.     0,
  6.     ExtendedWeakReference.c_SurviveBoot | 
  7.     ExtendedWeakReference.c_SurvivePowerdown);
  8.   var settings = data.Target as ApplicationSettings;
  9.   if (settings == null)
  10.   {
  11.     data.Target = settings = ApplicationSettings.Defaults;
  12.   }
  13.   return settings;
  14. }
  15. static void StoreSettings(ApplicationSettings settings)
  16. {
  17.   var data = ExtendedWeakReference.RecoverOrCreate(
  18.     typeof(ApplicationSettings),
  19.     0,
  20.     ExtendedWeakReference.c_SurviveBoot | 
  21.     ExtendedWeakReference.c_SurvivePowerdown);
  22.   data.Target = settings;
  23.   data.PushBackIntoRecoverList();
  24. }
  25.         

 Figura 3 Actualización de los datos almacenados Poner en funcionamiento


 En el principio, el dispositivo está en «nueva de fábrica» ​​estado del código de dispositivo se ha desplegado el dispositivo, pero todavía no se ha inicializado y por lo tanto no tiene ninguna configuración actual.
 Se puede ver este estado se refleja en el método GetSettings cuando el objeto de configuración sigue siendo nula y por tanto se inicializa con la configuración predeterminada.

 Porque quiero dejar que el aparato se comunican con Internet ya través de una infraestructura de Windows Azure Service Bus-Necesito equipar el dispositivo con un conjunto de credenciales para hablar con esa infraestructura y también decir que los recursos con quien hablar.

 Ese primer paso de la creación de un dispositivo de nueva fábrica con la configuración de red necesaria y la creación de los recursos correspondientes en el lado del servidor se conoce como el aprovisionamiento, me referí a la modelo arquitectónico básico para ello en el artículo anterior.
 En el código de dispositivo Voy a ser bastante estricto acerca de cómo obtener el dispositivo aprovisionado correctamente e iniciará los pasos de aprovisionamiento cada vez que el dispositivo se conecta a la red y no tiene una configuración válida.
 Por eso, mantener una bandera booleana en los valores que me diga si he tenido éxito anterior. Si el indicador no está definido, expido la llamada al servicio de aprovisionamiento alojado en Windows Azure. El servicio de aprovisionamiento es responsable de verificar la identidad del dispositivo utilizando su identificador de dispositivo único, el cual fue registrado en un per-lista mantenida por el servicio cuando se haya producido.
 Una vez que el dispositivo está activado, se elimina de la per-lista. Para mantener las cosas simples razonable para este artículo, sin embargo, voy a omitir la aplicación de la gestión permitir-lista. Una vez que el dispositivo se considera legítimo, la asigna provisión de servicios, siguiendo el modelo establecido en el artículo anterior, el dispositivo a una determinada unidad de escala y en particular, fan-out tema dentro de esa unidad de escala
. Por ejemplo, yo Voy a mantenerlo simple y crear una suscripción para un solo tema fijo llamado dispositivos que sirve como canal de comando de la nube en el dispositivo, y por un tema llamado eventos para recabar información de los dispositivos.
 Además de crear la suscripción y asociar el dispositivo con el tema, yo también voy a crear un servicio de identidad para el dispositivo en el Servicio de Control de Acceso (una característica de Windows Azure Active Directory) y concede que la identidad de los derechos necesarios para enviar mensajes al tema Eventos y recibir los mensajes de la suscripción de nueva creación para el Tema dispositivos. El dispositivo puede realizar exactamente esas dos operaciones en Windows Azure Servicio de Bus-nada más. La figura 4 muestra el núcleo del servicio de aprovisionamiento.
Este servicio depende del Windows Azure Service Bus API de administración (el NamespaceManager) encontrada en el conjunto del núcleo Microsoft.ServiceBus.dll que se incluye como parte del SDK de Windows Azure o vía Nuget. También se basa en una biblioteca de ayuda para la gestión de las cuentas de control de acceso y permisos disponibles como parte de la muestra Autorización para bus de servicios y, por supuesto, también se incluyen en el código descargable de este artículo


Figura 4 muestra el núcleo del servicio de aprovisionamiento.El servicio depende de la gestión de Windows Azure Service Bus API (el NamespaceManager) se encuentra en el núcleo del conjunto de Microsoft.ServiceBus.dll que se incluye como parte de Windows Azure SDK o a través de NuGet. También depende de una biblioteca de ayuda para administrar las cuentas de control de acceso y permisos disponibles como parte de la muestra de autorización para el servicio de autobuses y, por supuesto, también incluido en el código descargable para este artículo.
Figura 4 el servicio de aprovisionamiento


  1. namespace BackendWebRole



  2. {



  3.   using System;



  4.   using System.Configuration;



  5.   using System.Linq;



  6.   using System.Net;



  7.   using System.ServiceModel;



  8.   using System.ServiceModel.Web;



  9.   using Microsoft.ServiceBus;



  10.   using Microsoft.ServiceBus.AccessControlExtensions;



  11.   using Microsoft.ServiceBus.Messaging;



  12.   [ServiceContract(Namespace = "")]



  13.   public class ProvisioningService



  14.   {



  15.     const string DevicesTopicPath = "devices";



  16.     const string EventsTopicPath = "events";



  17.     static readonly AccessControlSettings AccessControlSettings;



  18.     static readonly string ManagementKey;



  19.     static readonly string NamespaceName;



  20.     static Random rnd = new Random();



  21.       static ProvisioningService()



  22.       {



  23.         NamespaceName = ConfigurationManager.AppSettings["serviceBusNamespace"];



  24.         ManagementKey = ConfigurationManager.AppSettings["managementKey"];



  25.         AccessControlSettings = new AccessControlSettings(



  26.           NamespaceName, ManagementKey);



  27.       }



  28.       [OperationContract, WebInvoke(Method = "POST", UriTemplate = "/setup")]



  29.       public void SetupDevice()



  30.       {



  31.         var rcx = WebOperationContext.Current.OutgoingResponse;



  32.         var qcx = WebOperationContext.Current.IncomingRequest;



  33.         var id = qcx.Headers["P-DeviceId"];



  34.         if (this.CheckAllowList(id))



  35.         {



  36.           try



  37.           {



  38.             var deviceConfig = new DeviceConfig();



  39.             CreateServiceIdentity(ref deviceConfig);



  40.             CreateAndSecureEntities(ref deviceConfig);



  41.             rcx.Headers["P-DeviceAccount"] = deviceConfig.DeviceAccount;



  42.             rcx.Headers["P-DeviceKey"] = deviceConfig.DeviceKey;



  43.             rcx.Headers["P-DeviceSubscriptionUri"] =



  44.               deviceConfig.DeviceSubscriptionUri;



  45.             rcx.Headers["P-EventSubmissionUri"] = deviceConfig.EventSubmissionUri;



  46.             rcx.StatusCode = HttpStatusCode.OK;



  47.             rcx.SuppressEntityBody = true;



  48.           }



  49.           catch (Exception)



  50.           {



  51.             rcx.StatusCode = HttpStatusCode.InternalServerError;



  52.             rcx.SuppressEntityBody = true;



  53.           }



  54.         }



  55.         else



  56.         {



  57.           rcx.StatusCode = HttpStatusCode.Forbidden;



  58.           rcx.SuppressEntityBody = true;



  59.         }



  60.       }



  61.       static void CreateAndSecureEntities(ref DeviceConfig deviceConfig)



  62.       {



  63.         var namespaceUri = ServiceBusEnvironment.CreateServiceUri(



  64.           Uri.UriSchemeHttps, NamespaceName, string.Empty);



  65.         var nsMgr = new NamespaceManager(namespaceUri,



  66.           TokenProvider.CreateSharedSecretTokenProvider("owner", ManagementKey));



  67.         var ruleDescription = new SqlFilter(



  68.           string.Format("DeviceId='{0}' OR Broadcast=true",



  69.             deviceConfig.DeviceAccount));



  70.         var subscription = nsMgr.CreateSubscription(



  71.           DevicesTopicPath, deviceConfig.DeviceAccount, ruleDescription);



  72.         deviceConfig.EventSubmissionUri = new Uri(



  73.           namespaceUri, EventsTopicPath).AbsoluteUri;



  74.         deviceConfig.DeviceSubscriptionUri =



  75.           new Uri(namespaceUri,



  76.             SubscriptionClient.FormatSubscriptionPath(



  77.               subscription.TopicPath,



  78.               subscription.Name)).AbsoluteUri;



  79.         GrantSendOnEventTopic(deviceConfig);



  80.         GrantListenOnDeviceSubscription(deviceConfig);



  81.       }



  82.       static void GrantSendOnEventTopic(DeviceConfig deviceConfig)



  83.       {



  84.         var settings = new AccessControlSettings(NamespaceName, ManagementKey);



  85.         var topicUri = ServiceBusEnvironment.CreateServiceUri(



  86.           Uri.UriSchemeHttp, NamespaceName, EventsTopicPath);



  87.         var list = NamespaceAccessControl.GetAccessControlList(topicUri, settings);



  88.         var identityReference =



  89.           IdentityReference.CreateServiceIdentityReference(



  90.             deviceConfig.DeviceAccount);



  91.         var existing = list.FirstOrDefault((r) =>



  92.           r.Condition.Equals(identityReference) &&



  93.           r.Right.Equals(ServiceBusRight.Send));



  94.         if (existing == null)



  95.         {



  96.           list.AddRule(identityReference, ServiceBusRight.Send);



  97.           list.SaveChanges();



  98.         }



  99.       }



  100.       static void GrantListenOnDeviceSubscription(DeviceConfig deviceConfig)



  101.       {



  102.         var settings = new AccessControlSettings(NamespaceName, ManagementKey);



  103.         var subscriptionUri = ServiceBusEnvironment.CreateServiceUri(



  104.           Uri.UriSchemeHttp,



  105.           NamespaceName,



  106.           SubscriptionClient.FormatSubscriptionPath(



  107.             DevicesTopicPath, deviceConfig.DeviceAccount));



  108.         var list = NamespaceAccessControl.GetAccessControlList(



  109.           subscriptionUri, settings);



  110.         var identityReference = IdentityReference.CreateServiceIdentityReference(



  111.           deviceConfig.DeviceAccount);



  112.         var existing = list.FirstOrDefault((r) =>



  113.           r.Condition.Equals(identityReference) &&



  114.           r.Right.Equals(ServiceBusRight.Listen));



  115.         if (existing == null)



  116.         {



  117.           list.AddRule(identityReference, ServiceBusRight.Listen);



  118.           list.SaveChanges();



  119.         }



  120.       }



  121.       static void CreateServiceIdentity(ref DeviceConfig deviceConfig)



  122.       {



  123.         var name = Guid.NewGuid().ToString("N");



  124.         var identity =



  125.           AccessControlServiceIdentity.Create(AccessControlSettings, name);



  126.         identity.Save();



  127.         deviceConfig.DeviceAccount = identity.Name;



  128.         deviceConfig.DeviceKey = identity.GetKeyAsBase64();



  129.       }



  130.         bool CheckAllowList(string id)



  131.       {



  132.         return true;



  133.       }



  134.   }



  135. }








El servicio consta de un único recurso HTTP, llamado /setup, implementado mediante la Web de Windows Communication Foundation (WCF) operación SetupDevice, que acepta solicitudes POST. Usted notará que el método es sin parámetros y también no vuelve a la carga de una entidad. No es casualidad. En lugar de utilizar un cuerpo de entidad HTTP en XML, JSON o forma de codificación para transportar información de solicitud y respuesta, estoy haciéndolo muy simple para el dispositivo y colocar las cargas en los encabezados HTTP personalizados. Esto elimina la necesidad de un analizador específico analizar la carga y mantiene la huella de código pequeño. El cliente HTTP ya sabe cómo analizar encabezados, y para lo que quiero hacer aquí, es abundante.Se muestra el código de dispositivo correspondiente llamando el recurso HTTP en figura 5, y es difícil imaginar hacer que llame a todo más sencillo que esto. El identificador del dispositivo se envía en un encabezado y la configuración post-provisioning igualmente se devuelve a través de cabezales. No hay malabarismo de arroyos, no analizar, cliente HTTP de pares clave-valor simple fácilmente entiende.


Figura 5 Configuración del dispositivo


  1.  



  2.           bool PerformProvisioning()



  3. {



  4.   [ ...



  5.           display status ...



  6.           ]



  7.   try



  8.   {



  9.     var wr = WebRequest.Create(



  10.       "http://cvdevices.cloudapp.



  11.           net/Provisioning.svc/setup");



  12.     wr.Method = "POST";



  13.     wr.ContentLength = 0;



  14.     wr.Headers.Add("P-DeviceId"this.deviceId);



  15.     using (var wq = (HttpWebResponse)wr.GetResponse())



  16.     {



  17.       if (wq.StatusCode == HttpStatusCode.OK)



  18.       {



  19.         settings.DeviceAccount = wq.Headers["P-DeviceAccount"];



  20.         settings.DeviceKey = wq.Headers["P-DeviceKey"];



  21.         settings.DeviceSubscriptionUri = new Uri(



  22.           wq.Headers["P-DeviceSubscriptionUri"]);



  23.         settings.EventSubmissionUri = new Uri(



  24.           wq.Headers["P-EventSubmissionUri"]);



  25.         settings.NetworkProvisioningCompleted = true;



  26.         StoreSettings(settings);



  27.         return true;



  28.       }



  29.     }



  30.   }



  31.   catch (Exception e)



  32.   {



  33.     return false;



  34.   }



  35.   return false;



  36. }



  37. void NetworkAvailable(Module.NetworkModule sender,



  38.   Module.NetworkModule.NetworkState state)



  39. {



  40.   ConvertBase64.ToBase64String(ethernet.NetworkSettings.PhysicalAddress);



  41.   if (state == Module.NetworkModule.NetworkState.Up)



  42.   {



  43.     try



  44.     {



  45.       Utility.SetLocalTime(NtpClient.GetNetworkTime());



  46.     }



  47.     catch



  48.     {



  49.       // Swallow any timer exceptions



  50.     }



  51.     if (!settings.NetworkProvisioningCompleted)



  52.     {



  53.       if (!this.PerformProvisioning())



  54.       {



  55.         return;



  56.       }



  57.     }



  58.     if (settings.NetworkProvisioningCompleted)



  59.     {



  60.       this.tokenProvider = new TokenProvider(



  61.         settings.DeviceAccount, settings.DeviceKey);



  62.       this.messagingClient = new MessagingClient(



  63.         settings.EventSubmissionUri, tokenProvider);



  64.     }



  65.   }



  66. }



  67.         




Si la configuración indica que el aprovisionamiento es necesaria, el realizar­Provisioning método es invocado desde la función NetworkAvailable, que se activa cuando la red está arriba y el dispositivo se asigna una dirección IP mediante DHCP. Una vez finalizada la provisioning, la configuración se utiliza para configurar el token proveedor y el cliente de mensajería para hablar con un Bus de servicio de Windows Azure. También observará un cliente NTP de llame. NTP significa «network time protocol» y he tomado un simple, con licencia BSD cliente NTP escrito por Michael Schwarz para habilitar la muestra para obtener la hora actual, que necesita si desea comprobar la caducidad de certificado SSL.
Como puede ver en figura 4, SetupDevices llama a la comprobación de simulacro en el CheckAllowList de la lista de admitidos y, si es exitosa, entonces llamadas CreateServiceIdentity y CreateAndSecureEntities. El método CreateServiceIdentity crea una nueva identidad de servicio junto con una clave secreta en el espacio de nombres de Control de acceso asociado con el espacio de nombres de Windows Azure Service Bus configurado para la aplicación. El método CreateAndSecureEntities crea una nueva suscripción para la entidad en los dispositivos de tema, configuración de la suscripción con una regla SQL que permite enviar mensajes en el tema de destino o la suscripción específica incluyendo una propiedad DeviceId en el nombre de la cuenta del dispositivo, o todas las suscripciones al incluir una propiedad de emisión con un valor booleano true. Después de haber creado la suscripción, el método llama a los métodos GrantSendOnEventTopic y GrantListenOnDeviceSubscription que conceden los permisos necesarios en las entidades a la nueva identidad de servicio utilizando la biblioteca de controles de acceso.
Una vez que todos los que se ha ejecutado correctamente, los resultados de las operaciones de aprovisionamiento se asignan a los encabezados en la respuesta HTTP de la solicitud y regresó con un código de estado OK, y el dispositivo almacena los resultados en memoria no volátil y establece la bandera para NetworkProvisioningCompleted.

Enviar eventos y recibir comandos

Con provisioning completado, el dispositivo está ahora listo para enviar eventos a los eventos de Windows Azure Service Bus tema y recibir comandos de su suscripción a los dispositivos de tema. Pero antes de irme de allí, tengo que discutir una cuestión delicada: la seguridad.
Como mencioné anteriormente, SSL/TLS es un conjunto de protocolos caro para pequeños dispositivos. Es decir, algunos dispositivos no nunca será capaces de soportar SSL/TLS, o podrían apoyar sólo en forma limitada debido a las limitaciones de memoria o capacidad de cómputo. De hecho, aunque en el momento de escribir este artículo la placa base GHI electrónica FEZ Spider basada en el .net Micro Framework 4.1 estoy usando aquí puede hablar nominalmente SSL/TLS y HTTPS, su firmware SSL/TLS aparentemente no encajan con la cadena de certificado presentada por Bus de servicio de Windows Azure o el servicio de Control de acceso. Como se actualiza el firmware para estos dispositivos a la nueva versión 4.2 de la Micro de .net Framework, estas limitaciones desaparecerán para este dispositivo en particular, pero el problema que algunos dispositivos son simplemente demasiado limitado tratar con SSL/TLS sigue siendo cierto en principio, y hay discusión activa en la comunidad de dispositivo incrustado en las opciones de protocolo apropiado que no son bastante como peso pesado.
Así, a pesar de que el dispositivo tiene ahora una cuenta adecuada, no se puede obtener un token desde el servicio de Control de acceso porque mediante HTTPS es un prerrequisito para hacerlo. Lo mismo es cierto para el envío de un mensaje en Windows Azure Service Bus, que obliga a HTTPS para todas las solicitudes que requieren pasar un token de acceso, incluyendo todas las interacciones con las colas y temas.Además, si esta muestra código de producción, por supuesto, tengo que exponer el extremo de aprovisionamiento a través de HTTPS para proteger la clave secreta que se devuelve al dispositivo.
¿Y ahora qué? Bueno, «lo que ahora» es en última instancia acerca de cómo hacer el equilibrio adecuado y esto sin duda incluyen dinero — en la fabricación, las diferencias de precio de unos céntimos suman cuando se hacen millones de un tipo de dispositivo. Si el dispositivo no es capaz de manejar un protocolo de seguridad requeridas, las preguntas son cuánto daño puede ser causado por no tener ese protocolo y cómo cerrar la brecha entre la falta del dispositivo de características necesarias y las demandas de infraestructura.
Lo que debe quedar claro es que cualquier secuencia de datos que no está cifrado y firmado es susceptible de espionaje y manipulación. Cuando un dispositivo informa sólo datos del sensor, vale la pena considerar si una manipulación de man-in-the-middle en dicha ruta de red es concebible valiosa para cualquier persona o podría detectarse analíticamente. A veces, el resultado podría ser que los datos de la clara están aceptar el envío. Rutas de comando y control son un asunto diferente; tan pronto como el comportamiento de un dispositivo puede accionarse a través de una red, no puedo pensar en un caso donde no quiero tener esa ruta de comunicación protegida por lo menos con una firma de integridad. El valor de la privacidad para comando y control depende del caso de uso. Si hay mitigación contra la manipulación en su lugar, ajuste la temperatura del termostato de destino no parece digno de mucho esfuerzo de cifrado.
El código de ejemplo que acompaña este artículo incluye dos variaciones del flujo de comunicación desde el dispositivo a la nube. El primero es un muy simplificado Windows Azure Bus API de servicio que requiere HTTPS y hace el saludo ordinario de adquirir un testigo de Control de acceso y hablando directamente al Bus de servicio de Windows Azure.
La segunda ruta utiliza la misma forma general del protocolo HTTP de Bus de servicio de Windows Azure para enviar y recibir mensajes, pero crea una firma HMACSHA256 sobre el mensaje usando la clave secreta que posee. Esto no protege el mensaje de espionaje, pero proteger el mensaje de manipulación y permite detectar ataques de repetición cuando incluyendo un id de mensaje. Las respuestas se firmará con la misma clave. Porque el Bus de servicio todavía no es compatible con este modelo de autenticación — a pesar de que este artículo es un buen indicador que Microsoft está pensando activamente este problema — la ruta utiliza un servicio de puerta de enlace personalizada alojado junto con el servicio de aprovisionamiento. La puerta de enlace personalizada comprueba y tiras de la firma y pasa el mensaje restante al Bus de servicio de Windows Azure. Usando un gateway personalizado para la traducción de protocolo también es generalmente el modelo correcto si necesita el sistema de nubes a hablar uno de los protocolos de innumerables dispositivo patentado. Pero una cosa a tener en cuenta sobre el enfoque de puerta de enlace personalizada es que hay que ampliar el número de dispositivos que al mismo tiempo enviar mensajes, así haciendo que el gateway capa muy delgada y apátridas es una buena idea.
Finalmente se hace la distinción entre los dos trazados por el servicio de aprovisionamiento que cualquiera se distribuye HTTP o HTTPS URIs. En el código de dispositivo, la diferencia es manejada por el TokenProvider. En el caso HTTPS, los dispositivos hablan directamente al Bus de servicio de Windows Azure, Considerando que en el caso HTTP, el servicio de aprovisionamiento habla a la puerta de enlace personalizada. El supuesto aquí es que para el caso HTTP, se preprovisioned los dispositivos sin exponer la clave secreta en una ruta de comunicación de Internet no protegida. En otras palabras, el servicio de aprovisionamiento se ejecuta en la fábrica, no en Windows Azure.
El código de dispositivo tiene dos interacciones con un Bus de servicio de Windows Azure: enviar eventos y recibir comandos. Voy a enviar un evento una vez cada minuto, después se hace una nueva lectura de la temperatura, y también usaré esa oportunidad para agarrar cualquier comandos pendientes y ejecutarlas. Hacer que voy modificar el método de TemperatureHumidityMeasurementComplete se muestra en la figura 2y agregar llamadas a SendEvent y ProcessCommands para ser procesados una vez cada minuto, como se muestra en la figura 6.
Figura 6 enviar eventos y recibir comandos

  1.  

  2.           void TemperatureHumidityMeasurementComplete(TemperatureHumidity sender,

  3.   double temperature, double relativeHumidity)

  4. {

  5.   [...] (see Figure 2)

  6.   if (settings.NetworkProvisioningCompleted &&

  7.     DateTime.UtcNow - settings.LastServerUpdate >

  8.       TimeSpan.FromTicks(TimeSpan.TicksPerMinute))

  9.   {

  10.     settings.LastServerUpdate = DateTime.UtcNow;

  11.     SendEvent(this.lastTemperatureReading, this.lastHumidityReading);

  12.     ProcessCommands();

  13.   }

  14. }

  15. void SendEvent(double d, double lastHumidityReading1)

  16. {

  17.   try

  18.   {

  19.     messagingClient.Send(new SimpleMessage()

  20.       {

  21.         Properties = {

  22.           {"Temperature",d},

  23.           {"Humidity", lastHumidityReading1},

  24.           {"DeviceId", settings.DeviceAccount}

  25.         }

  26.       });

  27.   }

  28.   catch (Exception e)

  29.   {

  30.     Debug.Print(ethernet.ToString());

  31.   }

  32. }

  33. void ProcessCommands()

  34. {

  35.   SimpleMessage cmd = null;

  36.   try

  37.   {

  38.     do

  39.     {

  40.       cmd = messagingClient.Receive(TimeSpan.Zero, ReceiveMode.ReceiveAndDelete);

  41.       if (cmd != null && cmd.Properties.Contains("Command"))

  42.       {

  43.         var commandType = (string)cmd.Properties["Command"];

  44.         switch (commandType)

  45.         {

  46.           case "SetTemperature":

  47.             if (cmd.Properties.Contains("Parameter"))

  48.             {

  49.               this.settings.TargetTemperature =

  50.                 double.Parse((string)cmd.Properties["Parameter"]);

  51.               this.RedrawDisplay();

  52.               this.temperatureHumidity.RequestMeasurement();

  53.               StoreSettings(this.settings);

  54.             }

  55.             break;

  56.         }

  57.       }

  58.     }

  59.     while (cmd != null);

  60.   }

  61.   catch (Exception e)

  62.   {

  63.     Debug.Print(e.ToString());

  64.   }

  65. }

  66.         


El método SendEvent utiliza al cliente de mensajería, que obtiene inicializado una vez que la conectividad de red está disponible. El cliente de mensajería es una pequeña versión de la API Windows Azure servicio de Bus que es capaz de enviar y recibir mensajes a y desde el servicio de autobús colas, temas y suscripciones. El ProcessCommands método utiliza al mismo cliente para buscar comandos desde la suscripción del dispositivo y procesa. Por ahora, el dispositivo sólo entiende el comando SetTemperature con un parámetro que indica la temperatura absoluta para establecer como un valor numérico (en grados Celsius, por cierto). Tenga en cuenta que ProcessCommands especifica un tiempo de espera de TimeSpan.Zero para recibir mensajes de la suscripción del Bus de servicio de Windows Azure, indicando que no está dispuesto a esperar a que lleguen los mensajes. Quiero agarrar un mensaje sólo si hay uno disponible y en caso contrario se baje inmediatamente. Reduce el tráfico por la puerta de enlace personalizada (debo utilizar HTTP y tener uno en su lugar) y no me exigen mantener un lazo de recepción abierta en el dispositivo. El equilibrio es la latencia.En el peor de los casos, los comandos tienen una latencia de un minuto. Si eso es un problema, puede utilizar un timeout largo que hace mucho tiempo de votación (que apoya a la biblioteca) y, con ese, disminuir de latencia de comando a unos pocos milisegundos.
El lado del servidor correspondiente, para recibir eventos y enviar comandos a todos los dispositivos registrados por colocar mensajes en el tema, simplemente sigue las reglas normales de la API de Windows Azure servicio Bus y es parte del código de ejemplo que se puede descargar, 

Clemens Vasters es el líder técnico principal del equipo del bus de servicios de Windows Azure. Vasters ha sido en el equipo desde la primeras etapas de incubación y obras en la hoja de ruta de característica técnica para Windows Azure Service Bus, que incluye las notificaciones push y alta escala para Web y dispositivos de señalización. También es una frecuente conferenciante y autor de conocimientos de arquitectura. Puede seguir a Clemens por Twitter en twitter.com/clemensv.

.

 Fuente Original aquí
Licencia Creative Commons
solo-electronicos por Carlos Rodriguez Navarro se encuentra bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 3.0 Unported.