Control remoto – Lógica de comunicación

Existen dos maneras de controlar de forma remota un sistema de automatización de edificios Loxone. La primera opción es a través de peticiones HTTP. La segunda opción, y la más cómoda, es la comunicación a través de WebSockets. Mientras que en la primera opción se consulta el valor actual de cada entrada y salida a través de peticiones HTTP, en la opción de control remoto a través de WebSocket, los cambios de estado se envían automáticamente.

 

Petición HTTP

En la versión de petición HTTP, el procedimiento es el siguiente:

  • Version Check
  • Si es necesario, descargar el archivo de estructura
  • Comandos de comunicaciones

Los comandos se anexarán en la URL. Si se quiere, por ejemplo, consultar la versión del archivo de estructura, el comando sería el siguiente:

http://user:[email protected]/dev/sps/LoxAPPversion

Las respuestas de esta petición serían las siguiente:

http-request-variante

El comando recibido se especifica en el atributo “Control”, “Value” contiene el valor actual y el “Code” indica si el comando es correcto. Los comandos correctos se confirman con el código “200”. Todos los demás códigos significan que ha habido un problema y el comando no se pudo procesar. En el ejemplo anterior, la versión del archivo de estructura se encuentra en el atributo «value» de la respuesta. Las respuestas a las solicitudes de control contendrán el nuevo valor de la salida o de entrada que se haya establecido como forma de confirmación.

Para modificar un comando es necesario el comando básico. Este se encuentra en las funciones y en los bloques de funciones, en el elemento “action” que es generado por el UUID(dev/sps/[uuid]).  Se tienen que anexar las operaciones deseadas a este comando. Esto variará dependiendo del tipo de función o bloque. Para obtener más información, consulte los comandos de la sección.

 

Comunicación Websocket

Aquí puede ver una secuencia de construcción típica de una conexión WebSocket junto con la descarga del archivo de estructura, el envío de comandos (switch) y la recepción de notificaciones de la actualización de estado. El formato de los comandos y notificaciones de estado se explicará con más detalle en la sección de comandos.

websocket-kommunikation

 

Paso 1: Establecer la conexión websocket

Un WebSocket es un socket común, que hace que el Miniserver (GET /ws) se conecte con el puerto HTTP (estándar: 80). Esto se reforzará a través de un “Handshake” a un Websocket. Este “Handshake” contiene los datos del usuario ya que la actualización a un Websocket solo se permite a los usuarios autorizados. La secuencia de carácteres que contiene el nombre de usuario y la contraseña separados por dos puntos (por ejemplo: “usuario:contraseña”) está codificada en Base64 y se inserta en el Handshake.

Los Websockets se abren con Javascritp y no se puede enviar ninguna credencial del usuario ni ninguna cookie, se tiene que usar una URL con al última cookie que se ha enviado (GET/ws/devs_cookie).

Desde que Javascript no puede procesar datos binarios, todos los comandos tienen que empezar con jdev en vez de dev. Esto se aplica en todas las respuestas que se envíen con el formato JSON. El resultado de cualquier evento asíncrono también se tiene que enviar en formato JSON en vez de formato binario.

<script type=»text/javascript»>
function ReadCookie(strCookieName)
{ var strName = strCookieName + «=»;
var strCookies = document.cookie.split(‘;’);
var strValue;
for (var i = 0; i < strCookies.length; i++)
{ var strCookie = strCookies[i];
while (strCookie.charAt(0) == ‘ ‘)
strCookie = strCookie.substring(1,c.length);
if (strCookie.indexOf(strName) == 0)
return strCookie.substring(strName.length,strCookie.length); }
return null;
}
var cookie = ReadCookie(«devs»);
var host = «ws://» + window.location.hostname + «/ws/» + cookie;
var ws = new WebSocket(host); </script>

 

JSON status

Json
Nombre del Campo
Descripción
u UUID
t Texto
v Valor
i Icono UUID
e Número de entradas del temporizador
n Temporizador: Número de entrada
m Modo calendario
f Tiempo en minutos desde la medianoche
t Tiempo en minutos hasta la medianoche
a La entrada del temporizador requiere ser activada con el trigger

 

Paso 2 – Comprobar versión del archivo de programa

Una vez la conexión se ha actualizado para ser una conexión con Websocket, se puede empezar a enviar mensajes Websocket al Miniserver. Estos mensajes empiezan con el byte “/x00” y terminan con el bite “/ xFF”.

Para evitar la sobrecarga durante la carga del archivo de estructura es mejor guardar de forma local el archivo de estructura. De todos modos si el archivo es guardado de forma local es muy importante saber si la versión local actual está actualizada. Hay una forma muy fácil de comprobar la versión usando el comando: “dev/sps/LoxAPPversion”.

La respuesta a este comando, que vendrá en formato Websocket, es una marca de tiempo que tiene el Miniserver. Comparando esta marca de tiempo con la marca de tiempo que se obtuvo cuando el archivo de estructura se grabó localmente hace posible determinar  si el archivo de estructura (y todos los recursos, imágenes, etc..) tiene que descargarse otra vez.

 

Paso 3 – Descargar el archivo de programa

Si no tiene una copia local del archivo de estructura o el archivo de estructura que tiene esta obsoleto, se tiene que volver a solicitar de nuevo del Miniserver. Esto se hace mediante el comando “LoxAPP.xml”, que se transmite como mensaje Websocket. Como respuesta se obtendrá el archivo de estructura actual en formato binario. En el momento de la aplicación de esta transferencia de datos no hay ninguna norma establecida para la transmisión de datos binarios a través de WebSockets, por lo tanto, introducimos un simple protocolo propio.

Para indicar que está llegando un dato binario vía WebSocket, el primer byte será “/x03”, seguido de “/x01”. A estos dos bytes les seguirán dos bytes más que están reservados para futuros usos. Ahora mismo no les haga caso. Los 4 siguientes bytes vuelven a ser importantes. Estos 4 bytes representan un valor “entero sin signo” que indica lo grande que es el subsiguiente archivo, es decir, cuántos bytes llegaran via Websocket hasta que el archivo se haya transferido completamente.

La descarga de archivos de imágenes, cuyos comandos se pueden encontrar al principio del archivo de estructura, siguen el mismo procedimiento que la transferencia del archivo de estructura.

Para Javascript, el comando /jdev/sps/getloxapp se tiene que usar para cargar el archivo de estructura como texto. Las imágenes se tienen que enviar mediante URL del navegador normal y no por conexión Websocket.

 

Paso 4 – Comprobar el mecanismo de actualización de estado

La mayor ventaja de la comunicación Websocket a comparación de las peticiones HTTP es que la aplicación cliente recibirá automáticamente una notificación cuando cambie algún estado del Miniserver. Esto se tiene que activar explícitamente, porque el Websocket también se puede usar solo para descargar imágenes o similares y de esta forma las actualizaciones serían perjudiciales.

Para activar el mecanismo de actualización de estado asíncrono también denominado suscripción de evento, se envía el comando “dev/sps/enablestatusupdate” como mensaje Websocket al Miniserver. El Miniserver responderá a esto enviando una tabla de eventos completa, que contendrá todos los estados actuales de las entradas y salidas, A partir de este punto cualquier cambio que ocurra será enviado como tabla de evento parcial mediante e conexión Websocket.

Las tablas de eventos se transfieren como archivos con formato binario, como el archivo de estructura, pero el segundo byte es “/x02” (en lugar de “/x01) indica que esta transmisión no es un archivo, sino una tabla de eventos. Una tabla de eventos consiste en filas de eventos . A su vez cada evento consiste de un UUID y un valor “doble”, que representa el estado actual. El UUID determina qué salida o entrada les corresponde al evento. Usando UUIDs en el archivo de estructura, es posible asociar eventos a las funciones o los bloques de funciones que le permitirán tomar las medidas que quiera en el cliente, como por ejemplo, actualizar la interfaz de usuario.

El tamaño de cada evento está fijado en 24 bytes, de estos los bytes 5-8 de la cabecera, se pueden usar para proporcionar el tamaño de la tabla de eventos, es decir, el número de filas o el número de eventos. Una excepción a las actualizaciones de valores simples que son enviadas mediante eventos son los “eventos de texto”.

Estos se envían como “tablas de eventos de texto” y de nuevo en formato binario, la diferencia es que el segundo byte es “/x03” (en lugar de “x/01”) e indica una tabla de evento de texto.

Una tabla de evento de texto consiste en filas de textos de eventos. Un texto de evento, a su vez, consiste en un UUID, un UUID para un símbolo, una longitud de texto (entero sin signo, 4 bytes, little endian) y un texto que representa el estado actual. El primer UUID determina para qué objeto (función o bloque de función) es este evento. El segundo especifica un símbolo de estado y después ya está el texto, con las funciones que le permitirán tomar las medidas que quiera en el cliente, como por ejemplo, actualizar la interfaz de usuario.

Cabe señalar que el tamaño de un evento de texto es siempre un múltiplo de 4!

 

Paso 5 – Enviar comandos de control

El archivo de estructura muestra los comandos para cada función y bloque de función. Esto depende del tipo de función o del tipo de bloque de función y permite el control de estas funciones y bloques mediante mensajes Websocket al Miniserver. Enviando uno de estos comandos se activa la función correspondiente y reconoce el comando. Si se ha subscrito a eventos, llegará una tabla de eventos con los valores cambiados.

Una cosa importante a señalar en este punto es que el Miniserver evalúa su lógica interna basada en la frecuencia que se establezca en la configuración. Esto quiere decir que si se envían múltiples comandos dentro de un ciclo de evaluación, es posible que los comandos se pierdan.

Para evitar esto, es recomendable usar mecanismos cuyos comandos estén retrasados a propósito como por ejemplo un interruptor, el cual primero envía un comando de encendido y cuando se libera envía un comando de apagado.

 

Paso 6 – Notificaciones de cambios de estado

El estado de la funciones o de los bloques de funciones del Miniserver no sólo cambian como resultado directo de los comandos de controles remotos, sino también pueden ocurrir mediante el cambio de los valores de los sensores (temperatura, viento, movimiento..), también es posible que estén conectados simultáneamente a diferentes controles remotos.

En la versión de petición HTTP se tiene que recargar constantemente con el fin de percibir tales cambios en el control remoto. En la variante Webservice estos cambios se notifican automáticamente en forma de eventos, suponiendo que el mecanismo de actualización de estado haya sido activado.

 

Paso 7 – Cerrar una conexión websocket

El final de una conexión Websocket se señaliza en la secuencia binaria con “/xFF/x00”. Este mensaje se puede enviar ya sea por un software de control remoto o por el Miniserver. Pero si no hay conexión entre el Miniserver y el Websocket durante 5min, la conexión terminará automáticamente.

 

Comandos

Puede encontrar una lista con los comandos del Webservice en www.loxone.com en la tabla de abajo estan los comandos específicos del Websocket, respuestas y formatos binarios con más detalle.

Descripción Excplicación
Actualizar Handshake GET /ws HTTP/1.1<CR><LF>
Upgrade: WebSocket<CR><LF>
Connection: Upgrade<CR><LF>
Authorization: Basic YWRtaW46YWRtaW4=<CR><LF>
<CR><LF>Se envía desde la aplicación de control remoto al Miniserver. Se remplaza «YWRtaW46YWRtaW4» por la particular cadena codificada de autentificación Base64.
Actualizar Response HTTP/1.1 101 Web Socket Protocol Handshake<CR><LF>
Upgrade: WebSocket<CR><LF>
Connection: Upgrade<CR><LF>
<CR><LF> Respuesta del Miniserver si se ha ejecutado el Handshake correctamente
WebSocket-Mensaje \x00LoxAPP.xml\xffEn lugar de LoxAPP.xml, cualquier comando codificado UTF-8 está disponible: «dev / sps / LoxAPPversion» o «dev/sps/io/EEE0000000AA.VI35/on»
Notificación cerrando conexión \xff\x00Notificación de que la conexión está cerrada, se puede hacer ya sea desde la aplicación de control remoto o desde el Miniserver.
Encabezamiento binario #define DT_FILE 0x01 // Archivo solicitado
#define DT_EVENT 0x02 // Datos del evento
#define DT_EVENTTEXT 0x03 // Datos del evento de texto
#define DT_DAYTIMER 0x04 // Datos del tiempotypedef struct {
BYTE cBinType; // fix 0x03
BYTE cDataType; // DT_FILE or DT_EVENT OT DT_EVENTTEXT
BYTE cReserved1;
BYTE cReserved2;
UINT nLen; // 32-bit value (little endian)
} PACKED WsBinHdr;Después de “WsBinHdr” se añadirán los datos de longitud “nLen”.
Notificación de actualización de estado (Evento) Los datos de eventos se envían como una tabla EvData con la siguiente estructura. typedef struct _UUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} PACKED PUUID;typedef struct {
PUUID uuid;
double dVal;
} PACKED EvData;typedef struct {
PUUID uuid; // starts at multiple of 4
PUUID uuidIcon; // uuid of icon
unsigned long nLen; // length of text (no trailing 0)
// text follows here if text length is not a multiple of
// 4 then skip padding bytes
} PACKED EvDataText;typedef struct {
int nMode; // number of mode
int nFrom; // time from in minutes since midnight
int nTo; // time to in minutes since midnight
int bNeedActivate; // need activate (trigger)
double dValue; // value if analog daytimer
} PACKED EvDataDaytimerEntry;typedef struct {
PUUID uuid; // starts at multiple of 4
double dDefValue; // actual analog default value
int nEntries; // number of following entries
// entries (EvDataDaytimerEntry) follows here
} PACKED EvDataDaytimer;
Convertir el UUID a una cadena:
CStringA str;
str.Format(«x-x-x-xxxxxxxx»,
uuid.Data1,uuid.Data2,uuid.Data3,uuid.Data4[0],uuid.Data4[1],uuid.Data4[2],
uuid.Data4[3],uuid.Data4[4],uuid.Data4[5],uuid.Data4[6],uuid.Data4[7]);

 

Esquema URL de la App Loxone

Con estos comandos puede usted navegar a una posición deseada de la App.

ESQUEMA APP:

loxone://   abre la App Loxone

EJEMPLOS:

loxone://ms?mac=<MAC>
loxone://ms?host=<IP>
loxone://ms?host=<IP>&usr=<USER>&pwd=<PASSWORD>
loxone://ms?host=<URL>&usr=<USER>
loxone://ms?host=<IP>&usr=<USER>&pwd=<PASSWORD>&loc=favorites
loxone://ms?mac=<MAC>&loc=home
loxone://ms?host=<MAC>&loc=weather
loxone://ms?mac=<MAC>&loc=room%2F<roomUUID>
loxone://ms?host=<MAC>&loc=category%2F<categoryUUID>
loxone://ms?host=<MAC>&loc=control%2F<controlUUID>

NOTAS:

Miniserver Host (= azul)
Miniserver User (= verde)
Miniserver Password (= rojo)
Información de navegación App (= naranja)

ms?host=<HOST>
ms?mac=<MAC>(User+PW no es necesario)
ms?host=<HOST>&usr=<USER>
ms?host=<HOST>&usr=<USER>&pwd=<PASSWORD>
ms?host=<HOST>&usr=<USER>&pwd=<PASSWORD>&loc=<LOCATION>
ms?mac=<MAC>&loc=<LOCATION>

<HOST>   Dirección IP o nombre del Host de los Miniservers
<MAC>    Dirección MAC del Miniserver (El Miniserver ha de estar grabado en la App)

 

INFORMACIÓN DE NAVEGACIÓN EN APP:

ms?host=<HOST>&loc=<LOCATION>

  • Tener en cuenta URL Encoding: “/” → “%2F”

<LOCATION> Opciones:

Para navegar a una página determinada:

home – Página principal
weather – Página del tiempo
favorites – Página favoritos
room – Vista de habitación
category – Vista de categoría
menu – Menü
taskrecorder – Grabador de tareas

Navegar a una habitación:
room%2F<roomUUID>

Navegar a una categoría:
category%2F<categoryUUID>

Navegar a un comando:
control%2F<controlUUID>

Los UUIDs los encontrará en el archivo de estructura LoxAPP3.json. Para abrir dicho archivo:

«Miniserver IP»/data/LoxAPP3.json