Como Desarrollar un nuevo Gateway de protocolo para la plataforma Sofia2

Una de las características técnicas más destacables de la plataforma Sofia2 es que los protocolos físicos de comunicación soportados (TCP, MQTT, Ajax-push…), y sobre los que se envían mensajes SSAP desde los KPs, no están ligados al proyecto core de Sofia2, sino que son creados y desplegados en forma de Plugins.

De este modo, en cada instalación de Sofia2, es posible desplegar únicamente aquellos protocolos que se van a usar, sin necesidad de añadir el resto.

Asimismo, es posible desarrollar nuevos Gateways y desplegarlos de manera sencilla sin tener que añadirlos al core de la plataforma. Basta con desarrollarlos de manera separada, compilarlos como un Jar de Java y añadirlos al directorio de Plugins para que la plataforma los arranque durante el despliegue. De manera que la plataforma tiene la versatilidad de poder ser extendida con nuevos protocolos necesarios para un proyecto concreto, sin necesidad de solicitar una ampliación de la misma.

El funcionamiento de carga de Plugins en Sofia2 es el siguiente:

· Mediante un parámetro se indica a la plataforma el directorio donde se van a desplegar los ficheros Jar con plugins.

· Durante el arranque de la plataforma, Sofia2 escanea el directorio de plugins y carga las clases y el contexto Spring de cada uno de los Jar.

· Cada Gateway es manejado a través de un Bean de Spring instanciado durante la carga de clases del paso anterior.

Para ilustrar como desarrollar un nuevo Gateway, vamos a basarnos en el Gateway Websocket que estará disponible a partir de la release 2.10 de Sofia2, y que se ha creado utilizando el framework Atmosphere(ver http://unpocodejava.wordpress.com/2014/07/25/creando-websockets-de-manera-sencilla-con-atmosphere/)

· El primer paso es crear un nuevo proyecto en el que desarrollar el Gateway y configurar y añadir las dependencias de Sofia2 al pom.xml del proyecto.

Para configurar el proyecto tendremos en cuenta:

1. Todos los gateways de Sofia2 pertececen al grupo com.indra.sofia2.plugin.gateway Por lo que habrá que incluir la siguiente entrada en el pom.xml indicando el artifact padre del Gateway que vamos a crear:

Siendo la versión, la versión de la última distribución de Sofia2.

2. Configuramos nuestro proyecto como perteneciente al grupo de gateways y le damos un nombre y versión:

3. Incluimos las dependencias de Sofia2 que necesitaremos durante el desarrollo del plugin:

4. Añadimos el resto de dependencias. Que para nuestro ejemplo de Gateway websocket será el runtime de atmosphere

· Una vez configurado el proyecto, lo siguiente es pasar al desarrollo del plugin. Como hemos dicho, cada Gateway es manejado mediante un Bean de Spring, que Sofia2 carga durante el arranque de la plataforma. Por lo que será necesario que declaremos ese Bean, bien en un fichero de contexto, bien mediante una anotación de tipo @Component. De este modo el Bean será el punto de arranque de nuestro Gateway.

· A su vez, el core de Sofia2 proporciona la clase abstracta GatewayToExtendImpl con las utilidades que los Gateways necesitan para una vez recibido un mensaje SSAP por su protocolo físico correspondiente, elevarlo al SIB para su procesado y recepción de la respuesta a devolver al cliente.

Esta clase obliga a implementar los siguientes métodos:


@Override

public GatewayProtocol getProtocol() {//TODO Tipo de protocol implementado}

@Override

public void onStart() {//TODO Acciones a realizar al arrancar el Gateway }

@Override

public void onStop() {//TODO Acciones realizar al detener el Gateway}

Y proporciona el método:


public SSAPMessage process(SSAPMessage mensaje, ClientGatewayData client)

A través del que se elevará al SIB para su procesado un mensaje SSAP recibido desde un cliente. El otro argumento es un objeto de tipo ClientGatewayData utilizado para auditoria y recoge información de la conexión del cliente.

Siguiendo con el ejemplo del Gateway WebSocket los pasos descritos se traducen en:

1. Creamos la clase del Gateway WebSocket como un Bean de Spring, que implementa GatewayToExtendImp:


@Component("GatewayWebSockets")

public class GatewayWebSockets extends GatewayToExtendImpl

2. Creamos el manejador del protocolo Websocket mediante un manejador del framework Atmosphere(ver http://unpocodejava.wordpress.com/2014/07/25/creando-websockets-de-manera-sencilla-con-atmosphere/). En este caso, es el framework Atmosphere mediante esta clase, quien gestiona todos los aspectos relativos al protocolo físico Websocket, e invocando al método onTextMessage cuando recibe un mensaje a través del protocolo:


@WebSocketHandlerService(path = "/api_websocket", broadcaster = SimpleBroadcaster.class)

public class WebSocketsProtocolAdapter extends WebSocketHandlerAdapter {

//Logger

private static final Log logger = LogFactory.getLog(WebSocketsProtocolAdapter.class);

private GatewayWebSockets gatewayWebSockets;

@Override

public void onOpen(WebSocket webSocket) throws IOException {

logger.info("New websocket connection added: "+webSocket.resource().getRequest().getRemoteAddr());

webSocket.resource().addEventListener(new WebSocketEventListenerAdapter() {

@Override

public void onDisconnect(AtmosphereResourceEvent event) {

try {

logger.info("Disconnecting websocket connection");

event.getResource().close();

} catch (IOException e) {

logger.error("Error closing websocket connection: "+e.getMessage());

}

}

@Override

public void onClose(AtmosphereResourceEvent event) {

logger.info("Closing websocket connection");

super.onClose(event);

}

});

}

@Override

public void onTextMessage(WebSocket webSocket, String message) throws IOException {

AtmosphereResource resource = webSocket.resource();

logger.info("Gateway WebSocket receive SSAP message: "+message);

String response=getGatewayWebSockets().process(message, resource);

logger.info("Gateway WebSocket response SSAP message: "+response);

Broadcaster b = resource.getBroadcaster();

b.broadcast(response, resource);

}

Como vemos en el código, cuando se recibe un mensaje SSAP a través del manejador, este mensaje se pasa al Gateway de Websockets a través del método process, siendo ya esta clase quien eleve el mensaje al SIB al extender GatewayToExtendImpl

3. Al utilizar Atmosphere como framework para Websockets, nos encontramos con el problema de que este framework carga los manejadores de Websocket durante el arranque del contenedor Web, en un punto donde Sofia2 todavía no ha cargado las clases de los plugins, y por tanto el manejador desarrollado en el punto anterior (WebSocketsProtocolAdapter), al no estar cargado en el classpath, no ha sido descubierto por Atmosphere y no se encuentra disponible. Para resolver este problema, lo que hacemos es registrarlo explicitamente durante el arranque del Gateway en el método onStart():


@Override

public void onStart() {

//Registra el Adaptador de WebSockets ya que Atmosphere hace el escaneo de clases anotadas antes de que SOFIA registre los plugins

Map<Class<? extends Annotation>, Set<Class<?>>> annotations = (Map<Class<? extends Annotation>, Set<Class<?>>>)

servletContext.getAttribute(DefaultAnnotationProcessor.ANNOTATION_ATTRIBUTE);

Set<Class<?>> setAnotations=annotations.get(org.atmosphere.config.service.WebSocketHandlerService.class);

if(setAnotations==null){

setAnotations=new HashSet<Class<?>>();

annotations.put(org.atmosphere.config.service.WebSocketHandlerService.class, setAnotations);

}

setAnotations.add(com.indra.sofia2.sib.gateway.implementations.websockets.WebSocketsProtocolAdapter.class);

}

· Con lo visto hasta ahora, ya podemos registrar nuestro Gateway para que la plataforma lo arranque, elevar mensajes SSAP al SIB recibidos por el protocolo físico y recibir la respuesta desde el SIB para devolverla por el protocolo físico. Lo que falta es implementar la parte en la que el SIB pueda enviar notificaciones de suscripción a un KP (mensajes SSAP de tipo INDICATION).

Para esto, nuestro Gateway tiene que registrar un listener en el core de Sofia2, mediante el que recibir las notificaciones desde el motor de suscripciones y después enviarlas por la conexión del protocolo físico.

El listener que tenemos que registrar debe implementar la clase MessageSuscriptor:


public interface MessageSuscriptor {

public void onMessage(SSAPMessage message);

}

De manera que el SIB notificará este tipo de mensajes invocando al método onMessage del listener, pasándoles el mensaje SSAP a enviar al KP.

El registro del listener debe hacerse en un Bean Spring del core de Sofia2 llamado subscriptionEngine perteneciente a la clase SubscriptionEngine. De manera que nuestro Gateway deberá recuperar este Bean, y registrar su propio Listener:


@Autowired

private SubscriptionEngine subscriptionService;

·····························

subscriptionService.addMessageSubscriptor(sessionKey, new MessageSuscriptor() {

@Override

public void onMessage(SSAPMessage message) {

String toNotify=message.toJson();

//TODO notificar mensaje a través de protocolo físico

}

});

Continuando con el ejemplo del Gateway Websocket, una vez recibido el mensaje SSAP de notificación, la comunicación al KP cliente se hará a través de la conexión gestionada por Atmosphere en un objeto del tipo AtmosphereResource:


subscriptionService.addMessageSubscriptor(sessionKey, new MessageSuscriptor() {

@Override

public void onMessage(SSAPMessage message) {

String toNotify=message.toJson();

ClientGatewayData client =new ClientGatewayData(remoteAddress, remotePort, ClientGatewayType.WEB);

auditPluginManager.audit(message, listenerCipherKey, Calendar.getInstance().getTime(), client, AuditDirection.TO_CLIENT);

Broadcaster broadcaster=resource.getBroadcaster();

broadcaster.broadcast(toNotify, resource);

}

});

Como Desarrollar un nuevo Gateway de protocolo para la plataforma Sofia2

¿Qué es Fog Computing?

Este término creado por Cisco se refiere al mundo IoT y por tanto es de aplicación al mundo Sofia2.

Estamos cerca de ver como Internet of Things proveerá conectividad a billones de dispositivos que estarán volcando información compartida a la nube para una analítica Big Data.

Imaginemos que mi casa está volcando información de los consumos, temperatura,… cada 5 segundos, que mi coche hace lo mismo, o mi móvil o las medidas biométricas de un paciente remotamente gestionado por un hospital…

Toda este Tsunami de datos IoT puede llevar a colapsar las redes del operador o a simplemente que sea muy costoso almacenarlo y procesarlo.

En este ámbito Fog Computing se refiere al proceso de tomar decisiones tan pegados al dato como sea posible, esto permite que no todos los datos tengan que viajar por la red, sólo será necesario volcar datos procesados en algunos casos o ninguno en la mayoría (necesito por ejemplo conocer la temperatura de mi casa cada 5 segundos o me valdría con salvo que haya existido un pico tener una media de la temperatura cada hora del día?).

Sofia2 soporte el desarrollo de clientes inteligentes (KPs) siguiendo este concepto, aunque lo deja a decisión del proveedor, que puede delegar las reglas, disparadores,… al nodo centrl (SIB) o bien ejecutarlo en local. Para eso además provee la infraestructura de KP Modelo que de una forma muy sencilla permite crear estas aplicaciones, con reglas y persistencia locales, con gestión de la configuración y el despliegue centralizados, reconexión automática,…

Leer más

¿Qué es Fog Computing?

Automatización solicitud de paso a colaborador de la plataforma

Cuando un usuario se registra en Sofia2 InCloud se le asigna el rol USUARIO, que permite utilizar la plataforma en modo consulta (puede suscribirse a ontologías y crear clientes).
Si quiere publicar datos en la plataforma y en general utilizar las capacidades avanzadas de la plataforma (como el motor scripting o CEP) necesita tener un rol COLABORADOR.
Con esta funcionalidad el usuario puede solicitar desde la propia consola el paso a COLABORADOR.

PasoAColaborador

El administrador podrá validar cada petición respondiendo de forma positiva o rechazándolas explicando los motivos y si se requiere más información.

Automatización solicitud de paso a colaborador de la plataforma

Ampliación de la gestión de Assets

Entre todas las novedades introducidas en la versión 2.9 de Sofia2 se añade a la lista la ampliación de la gestión de Assets. Con esta funcionalidad podemos, de manera opcional, localizar los Assets además de por su posición geográfica por un nodo, siendo un nodo una sede física en la que puede ubicarse un Asset.

Los nodos a su vez pueden estar localizados o asociados a otros nodos, de esta manera un Asset puede estar ubicado en la oficina A de la planta 3 del edificio 4, siendo la oficina A, la planta 3 y el edificio 4 nodos.

Para poder dar de alta un nodo en Sofia2, tendremos que ir a la opción de Assets y dentro de ella a la opción “Crear Nodo”

assetsmenu

En esta pantalla deberemos informar los datos del nodo, entre los que se incluyen los datos geográficos (longitud y latitud) y TAGs o etiquetas de búsqueda.

 

arbol

Con el nodo dado de alta en la plataforma podremos asociar los Assets al mismo.

Con esta mejora podremos hacer búsquedas de Assets dentro de árboles de nodos y por etiquetas (TAGs) de búsqueda.

Ampliación de la gestión de Assets

Ayuda contextual para usuarios de la plataforma

En la versión 2.9.0 de Sofia2 se ha introducido una nueva página de bienvenida en la consola que sirve como resumen del estado actual de nuestro trabajo con la plataforma.
De un simple vistazo podremos ver y recorrer las ontologías a las que estamos suscritos, los KPs asociados a las mismas y acceder además a sus tokens de seguridad.

Para los nuevos desarrolladores sirve como una pequeña guía que describe los primeros pasos para trabajar con Sofia2, sirviendo de orientación en una primera toma de contacto ágil.

El usuario podrá acceder a más o menos información disponible en función de los pasos ya completados.

A continuación podemos ver cómo un usuario va completando los pasos sugeridos por la plataforma y los datos de sus suscripciones, Kps y tokens se van actualizando:

Partiendo de cero:

Una vez se ha suscrito a una ontología:

Y una vez dado de alta un KP para dicha ontología (por defecto al dar de alta un KP se crea un token ya activo listo para su uso)

La página se completa incluyendo además links a un ejemplo de kp java y otro javascript como punto de partida.

Estos ejemplos están listos para funcionar con unas mínimas modificaciones que consisten en ajustar los datos de la ontología y token con los que se desea trabajar.

Por último se mostrará también desde esta página la información dinámica sobre los mensajes procesados por la instancia Sofia2 InCloud

Ayuda contextual para usuarios de la plataforma

Reglas Scripting/CEP

Con la liberación de la versión 2.9.0 de Sofia2 se ha dotado al motor de ejecución de Script de un nuevo modelo de parametrización.

Hasta esta versión, solamente podíamos asociar una única Ontología o un Temporizador que desencadenase la ejecución de un Script. Ahora esta limitación desaparece, pudiendo asociar varias Ontologías a un único Script, también se permite asociar Ontologías Padre, lo que permite que los desencadenantes también sean todas las Ontologías que heredan de estas Ontologías. Y por último se permite asociar Reglas CEP como origen de la ejecución de los Script.

tiposcript

 

Este último tipo de Script son los que centran la atención de este Artículo, por dos importantes características.

  • Son un nuevo modelo de ejecución de Reglas Script que difiere del modelo de trabajo basado en ontologías
  • Permite integrar los Dos motores principales de procesamiento de los mensajes en Sofia2, el Motor Cep y el Motor Script.

El Motor CEP nos permite evaluar la información de todas las Instancias de una o varias Ontología junto a la variable tiempo, lo que nos permite establecer condiciones complejas que son procesadas de una manera óptima.

ReglaCep

 

Si bien el Motor CEP evalúa todas las Instancias de las Ontologías asociadas, únicamente desencadena la ejecución de los Script cuando se cumple la condición que este evalúa.

La principal diferencia con el modelo de Script Basado en Ontologías es que al Motor Script no le llega la infancia de la Ontología que ha desencadenado el Evento Cep, si no  el resultado de este. Para el ejemplo anterior nos llegará una ontología con la siguiente información

{“Ontology”:”SensorTemperatura”,”Subscription”:”alarmatemperatura”,”inEvents”:{“medida”:51.0}}

Donde nos indica la ontología que ha desencadenado este evento, en este caso SensorTemperatura, la Regla Cep que lo ha desencadenado, alarmatemperatura y en un atributo denominado inEvents , los valores almacenados, en este caso únicamente almacenábamos la medida y la insertábamos en un atributo llamado de la misma forma.

Throwable error

String ontology

String ontologyName

List<String>ontologyId

String typeMessage

String sessionKey

String scriptName

String cepData

String cepName

String scriptType

La estructura de información con la que podremos trabajar dentro del Script, en cualquier de los bloques es la que se detalla en el punto anterior, donde destacan los siguientes atributos, que reitero, están disponibles en todos los Script Cep.

  • cepData, que es la ontología resultante de la Regla Cep.
  • cepName, el nombre de la Regla Cep.
  • ontologyName, el nombre de la ontología que ha desencadenado la regla Cep.
  • ScriptName, el nombre del Script que se está ejecutando.
  • scriptType tipo de Script que puede tomar los valores ONTOLOGY, CEP o QUART.

Una peculiaridad de los Script CEP es que al ser desencadenados estos por una condición previa, que se cumpla la Regla Cep!, no tenemos la obligación de definir una condición If, por lo que podemos únicamente establecer el código para el bloque Then.

Thennoif

En este caso el bloque Then obtiene el valor de la propiedad inEvents.medida, y lo evalúa, de forma que si es menor o igual de 50 envía un correo de Alarma Naranja y si es mayor de Alarma roja por Alta temperatura.
Esto podríamos haberlo echo usando el bloque if para establecer la condición
if
Y en los bloques Then y Else cada uno de los procesos específicos.
then
else
Reglas Scripting/CEP

Visor Sofia2 Geographics

Sofia2 Geographics es una demo para mostrar las capacidades de Sofia2 a la integradas sobre un interfaz dinámico con acceso a datos en soft real time.

Se puede encontrar en la web de Sofia2 la sección desarrollador:

http://sofia2.com/Examples/Geographics.html

Funcionalidades del Visor

Autobuses Coruña y Gijón, en Tiempo Real

El SIB Sofia2 es alimentado con datos a tiempo real de los ayuntamientos de La Coruña y Gijón. El visor consulta la plataforma para actualizar un mapa con las posiciones de los autobuses.

Posibilita la selección de rutas de autobuses mediante la banda a la izquierda. Estas rutas quedan resaltados en el mapa:

Al seleccionar cada autobús ofrece información acerca de la línea, tipo, última parada y la hora a la que pasó y la próxima parada.

Antenas de Rivas Vaciamadrid

El SIB Sofia2 es alimentado con datos a tiempo real de las antenas de recogida de información distribuidas por el ayuntamiento de Rivas.

La ventana de información de las antenas da los datos de identificación, ubicación, temperatura media y una muestra del histórico de las temperaturas recogidas en las últimas horas hasta el momento actual.

Buscador de Tweets

El visor posibilita la búsqueda de Tweets geolocalizados mediante un buscador de área y palabras clave.

Se escribe una palabra y la plataforma Sofia2, mediante el API de Twiter, devuelve los tweets filtrados en el área de búsqueda.

La información de un tweet incuye la foto, usuario, fecha, mensaje, retweets, url origen y una valoración positiva/negativa/neutral realizada en la plataforma Sofia2 del mensaje.

Un click en la foto abrirá una página hacia el perfil del usuario en twitter.com

También se mostrará una banda de estadísticas relacionadas con la búsqueda.

Características Tecnológicas del Visor

  • Multidispositivo (basado en HTML, CSS, Document Object Model (DOM) y Javascript)
  • Utiliza el Canvas de HTML5 junto con las APIs de animación EASELJS y TWEENJS
  • Capacidades de consulta a KPs de Sofia2 mediante DWR Ajax
  • Posicionamiento de datos en el API Google Maps
  • Graficas mediante Open source HTML5 chartjs

Infraestructura de las Vistas

Para el diseño de la infraestructura gráfica se ha utilizado el IDE Flash CC Professional de Adobe. Ofrece un entorno de creación de contenido multimedia y diseños web interactivos. En sus últimas versiones de soporte para diseños sobre el Canvas de HTML5.

El visor Sofia2 Geographics aprovecha la funcionalidad a alto nivel del IDE para la elaboración del interfaz e interacciones con el usuario.

Geolocalizaciones con Google Maps

Google Maps API es una colección de utilidades y herramientas provistas por Google.

Permite construir visores geográficos basados en Google Maps, asi como acceder a sus servicios.

Overlapping Marker Spiderfier para Google Maps

Complemento para el API de google maps que separa los apilamientos de markers en radios, facilitando la selección de uno de ellos.

TimeCircles

TimeCircles es un plugin de jquery que permite de un modo sencillo y flexible introducir un contador temporal.

ChartJS

Es una librería que permite la construcción de graficas. Tiene un set de componentes muy completo que permiten mostrar graficas con multiples orígenes, dinámicas, animadas…

Visor Sofia2 Geographics