Nuevas APIS REST Social Media

En la release 2.15 de Sofia2, se han incluido nuevas APIS que pretenden facilitar la integración con twitter como fuente de datos en la plataforma sin necesidad de acceder a la consola de Configuración.

MenuAPIREST

Al acceder a los servicios podemos ver que hay 4 nuevos diferentes:

  • Configuración de Acceso Service
  • Busqueda Twitter Service
  • Usuarios Twitter Service
  • Tendencias Twitter Service

Veamos cada uno de los servicios con algo más de detalle:

Configuración de Acceso Service : Este API REST dispone de los siguientes servicios:

ConfiguracionAccesoTwitter

  • Operación GET /configuracionRRSS/{identificacion}: Recupera la configuración de acceso con la identificación pasada por parámetro.
  • Operacion GET /configuracionRRSS: Recupera todas las configuraciones de acceso existentes en la plataforma según el usuario que lo invoque.
  • Operación POST /configuracionRRSS: Da de alta una nueva configuración de acceso.
  • Operación PUT /configuracionRRSS: Permitirá actualizar la configuración de acceso con la información pasada por parámetro.
  • Operación DELETE /configuracionRRSS/{identificacion}: Elimina la configuración de acceso con la identificación pasada por parámetro.

Usuarios Twitter Service : Este API REST dispone de los siguientes servicios:

UsuariosTwitterService

  • Operación GET /usuariosTwitter/{nombreUsuario}/{nombreConfiguracion}: Busca al usuario Twitter cuyo nombre de usuario coincide con el pasado como parámetro y obtiene su información.
  • Operación GET /usuariosTwitter/timeline/{nombreUsuario}/{nombreConfiguracion}: Obtiene el TimeLine del usuario que se le pasada como parámetro.
  • Operación POST /usuariosTwitter/{nombreUsuario}/{nombreConfiguracion}/{nombreOntologia}: Almacena en una ontología pasada como parámetro la información del usuario indicado.
  • Operación POST /usuariosTwitter/timeline/{nombreUsuario}/{nombreConfiguracion}/{nombreOntologia}: Almacena en una ontología pasada como parámetro el timeline del usuario indicado.

Busqueda  Twitter Service : Este API REST dispone de los siguientes servicios:

BusquedaTwitterService

  • Operación GET /busquedaTwitter/{textoBusqueda}/{nombreConfiguracion}: Obtiene los Tweets resultado de la búsqueda cuyo texto coincide con el pasado como parámetro. Se permite operadores lógicos.
  • Operación GET /busquedaTwitter/{textoBusqueda}/{nombreConfiguracion}/{latitud}/{longitud}/{radio}:  Obtiene los Tweets resultado de la búsqueda georeferenciada (latidud, longitud y radio), cuyo texto coincide con el pasado como parámetro. Se permite operadores lógicos.
  • Operación POST /busquedaTwitter/{textoBusqueda}/{nombreConfiguracion}/{nombreOntologia}: Almacena los Tweets resultado de la búsqueda en una ontología pasada como parámetro.
  • Operación POST /busquedaTwitter/{textoBusqueda}/{nombreConfiguracion}/{latitud}/{longitud}/{radio}/{nombreOntologia}:  Almacena los Tweets resultado de la búsqueda georeferenciada en una ontología pasada como parámetro.

Tendencias Twitter Service : Este API REST dispone de los siguientes servicios:

  • TendenciasTwitterServiceOperación GET /tendenciasTwitter/{zona}/{nombreConfiguracion}:  Obtiene los TrendingTopic de la zona pasada como parámetro.
Nuevas APIS REST Social Media

RV: ABC de Consorcios IoT

Fue de casualidad que leí este post de IAN SKERRETT sobre los consorcios actuales sobre IoT, en el que tenemos desde AllSeen Alliance, OneM2M, IoT Eclipse,…

Veamos un poco lo que nos cuenta Ian en el post…

Ian analiza varios consorcios en este reciente ámbito IoT, primero incluye en un grupo a los estándares ya establecidos (Zigbee, BT LE, uPnP+) y luego a los recién llegados y dentro de estos a:

  • Allseen Alliance,
  • OIC (Open Interconnect Consortium),
  • Thread Group,
  • IETF,
  • OASIS,
  • OMA (Open Mobile Alliance),
  • Eclipse IoT,
  • OneM2M,
  • HGI (Home Gateway Initiative),
  • Continua Alliance,
  • IEC (International Electrotechnical Commission),
  • IIC (Industrial Internet Consortium),
  • IPSO Alliance y
  • M2M Alliance.

Y el análisis lo hace en base a 3 factores:

  • Apertura: el grado de apertura de su propiedad intelectual y de sus normas
  • Disponibilidad: el consorcio tiene algo entregado?
  • Adopción: con grados de adopción.

Estos factores los evalúa Ian desde A (el mayor) a D (el menor).

Para Ian la tabla quedaría:

Apertura Disponibilidad Adopción
Estándares establecidos C B B
Allseen Alliance A- A C
OIC (Open Interconnect Consortium) A D D
Thread Group, D D D
IETF A A B-
OASIS A- A B
OMA (Open Mobile Alliance) A- A C+
Eclipse IoT A A B
OneM2M B B C
HGI (Home Gateway Initiative) B B C-
Continua Alliance ¿ A B
IEC (International Electrotechnical Commission) C+ B B
IIC (Industrial Internet Consortium) C D B
IPSO Alliance B B C-
M2M Alliance ¿ ¿ ¿

Las conclusiones de Ian (con las que coincido 100%) son que no va a haber un consorcio o estándar que domine IoT y que incluso en los próximos años aparecerán más.

De hecho yo añadiría que la adopción es aún muy pequeña en todos estos consorcios!

También concluye (y aquí estoy de acuerdo 200%) que

RV: ABC de Consorcios IoT

Creando un KP para el contenedor de KPs de Sofia2

En el siguiente post vamos a mostrar cómo crear una App Sofia2 (KP) para desplegarla en el contenedor de KPs de Sofia2.

En concreto vamos a crear una App que insertará en la plataforma información sobre las cotizaciones en bolsa de las 30 empresas que componen el índice Dow Jones. Se tratará de un KP Java, que utilizando el API de Yahoo, consultará la última cotización de cada valor y creará un fichero de mensajes interpretable por el contenedor de KPs que será quien los transforme en mensajes SSAP INSERT y los envíe al SIB. Asimismo, configuraremos el KP en el contenedor para que sea invocado periódicamente y de este modo tengamos datos de cotización actualizados.

Para ello repasaremos el flujo de trabajo típico en Sofia2, y lo extenderemos con el proceso de programación y despliegue de un KP en el contenedor de KPs.

Desarrollo:

1. Creamos una ontologia para almacenar la información: En el caso de nuestra aplicación, gestionaremos información sobre la cotización en bolsa de las empresas del índice Dow Jones devuelta por el servicio de información de Yahoo Finance. Para ello, vamos a utilizar un API web provisto por Yahoo (https://developer.yahoo.com/yql/), que nos permite lanzar queries en formato similar a SQL sobre mas de 1000 tablas de sus sistemas, incluyendo la que a nosotros nos interesa que es yahoo.finance.quote. y pudiendo recibir la respuesta tanto en formato XML como en JSON.

Para determinar que debe tener nuestra ontologia, hacemos previamente una consulta al servicio, solicitando la cotización de la empresa 3M, para la que recibimos la siguiente respuesta:

“symbol”: “MMM”,

“AverageDailyVolume”: “2925250”,

“Change”: “+0.18”,

“DaysLow”: “164.36”,

“DaysHigh”: “166.09”,

“YearLow”: “123.61”,

“YearHigh”: “166.09”,

“MarketCapitalization”: “106.0B”,

“LastTradePriceOnly”: “165.48”,

“DaysRange”: “164.36 – 166.09”,

“Name”: “3M Company Common”,

“Symbol”: “MMM”,

“Volume”: “4891344”,

“StockExchange”: “NYSE”

De esta información no quedamos con la siguiente para nuestra ontologia:

  • Symbol: Identificador de la empresa en Bolsa
  • Name: Nombre de la empresa
  • Volume: Número de acciones intercambiadas
  • StockExchange: Mercado en el que cotiza la empresa
  • Change: Variación porcentual del valor de la empresa desde el precio de cierre del dia anterior.
  • DaysLow: Precio de cotización mínima de la empresa desde el comiento del dia.
  • DaysHigh: Precio de cotización máxima de la empresa desde el comienzo del dia.
  • LastTradePriceOnly: Ultimo precio de cotización.

A la que sumaremos un timestamp con el momento en el que se ha recuperado la información.

Con todo esto determinamos que nuestra ontologia llamada StockPrice debe ser la siguiente:

{

“$schema”: “http://json-schema.org/draft-04/schema#“,

“title”: “StockPrice Schema”,

“type”: “object”,

“required”: [“StockPrice”],

“properties”: {

“StockPrice”: {

“type”: “string”,

“$ref”: “#/datos”

}

},

“datos”: {

“description”: “StockPrice”,

“type”: “object”,

“required”: [

“timestamp”,

“symbol”,

“name”,

“volume”,

“stockExchange”,

“change”,

“daysLow”,

“daysHigh”,

“lastTradePriceOnly”

],

“properties”: {

“timestamp”: {

“type”: “object”,

“required”: [

“$date”

],

“properties”: {

“$date”: {

“type”: “string”,

“format”: “date-time”

}

},

“additionalProperties”: false

},

“symbol”: {

“type”: “string”

},

“name”: {

“type”: “string”

},

“volume”: {

“type”: “string”

},

“stockExchange”: {

“type”: “string”

},

“change”: {

“type”: “string”

},

“daysLow”: {

“type”: “string”

},

“daysHigh”: {

“type”: “string”

},

“lastTradePriceOnly”: {

“type”: “string”

}

}

}

}

Y procedemos a crearla a partir de una plantilla vacía

2. Damos de alta el KP en Sofia2: Llamaremos a este KP DowJonesStockFeed

3. Programamos el KP Java que desplegaremos en el contenedor:

Como hemos dicho, utilizaremos un servicio externo, a través del API YQL de Yahoo para recibir la información de cotización de las empresas del índice Dow Jones. A este servicio externo le tendremos que pasar por cada empresa que queramos recuperar, un código o símbolo que la representa. Para ello, hemos creado una enumeración, que contiene un elemento por cada empresa, junto con su código:


package com.indra.sofia2.demos.stock.util;

/**
 * Enumeracion con las empresas del indice DowJones identificadas por su ticker o simbolo
 *
 */
public enum DowJonesStock {
 THREEM("MMM"), AMERICANEXPRESS("AXP"), ATANDT("T"), BOEING("BA"),
 CATERPILLAR("CAT"), CHEVRON("CVX"), CISCO("CSCO"), COCACOLA("KO"),
 DISNEY("DIS"), DUPONT("DD"), EXXON("XOM"), GENERALELECTRIC("GE"),
 GOLDMANSACHS("GS"), HOMEDEPOT("HD"), IBM("IBM"), INTEL("INTC"),
 JOHNSONANDJOHNSON("JNJ"), JPMORGAN("JPM"), MCDONALDS("MCD"), MERCK("MRK"),
 MICROSOFT("MSFT"), NIKE("NKE"), PFIZER("PFE"), PROCTERANDGAMBLE("PG"),
 TRAVELERS("TRV"), UNITEDTECH("UTX"), UNITEDHEALTH("UNH"), VERIZON("VZ"),
 VISA("V"), WALMART("WMT");
 
 //Este valor es lo que el API de Yahoo utiliza para localizar una empresa
 private String symbol;

 DowJonesStock(String symbol) {
       this.symbol = symbol;
 }
 
 public String getSymbol() {
      return symbol;
 }
}

A continuación creamos un Bean que nos ayudará a mapear cada cotización de una empresa recibida en la respuesta de la llamada al servicio externo, a una instancia de ontologia válida para Sofia2.

Este Bean tendrá todas las propiedades definidas en nuestra ontologia, junto con un método que nos devolverá el objeto como una instancia de ontologia lista para ser almacenada en un fichero de mensajes, que el contenedor de KPs podrá interpertar para construir un mensaje SSAP Insert:


package com.indra.sofia2.demos.stock.util;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Bean que respresenta cada una de las cotizaciones de un simbolo
 * Se utiliza para mapear desde una cotización recogida desde el API de Yahoo hacia una instancia de una ontologia
 *
 */
public class StockBean {
 
 private long timestamp;
 private String symbol;
 private String name;
 private String volume;
 private String stockExchange;
 private String change;
 private String daysLow;
 private String daysHigh;
 private String lastTradePriceOnly;
 
 
 public long getTimestamp() {
       return timestamp;
 }
 public void setTimestamp(long timestamp) {
       this.timestamp = timestamp;
 }
 public String getSymbol() {
       return symbol;
 }
 public void setSymbol(String symbol) {
       this.symbol = symbol;
 }
 public String getName() {
       return name;
 }
 public void setName(String name) {
      this.name = name;
 }
 public String getVolume() {
      return volume;
 }
 public void setVolume(String volume) {
      this.volume = volume;
 }
 public String getStockExchange() {
      return stockExchange;
 }
 public void setStockExchange(String stockExchange) {
      this.stockExchange = stockExchange;
 }
 public String getChange() {
      return change;
 }
 public void setChange(String change) {
      this.change = change;
 }
 public String getDaysLow() {
       return daysLow;
 }
 public void setDaysLow(String daysLow) {
       this.daysLow = daysLow;
 }
 public String getDaysHigh() {
       return daysHigh;
 }
 public void setDaysHigh(String daysHigh) {
       this.daysHigh = daysHigh;
 }
 public String getLastTradePriceOnly() {
      return lastTradePriceOnly;
 }
 public void setLastTradePriceOnly(String lastTradePriceOnly) {
      this.lastTradePriceOnly = lastTradePriceOnly;
 }
 
 public String getAsOntologyInstance(String ontology){
     SimpleDateFormat timestampFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
 
     StringBuilder ontologyInstance=new StringBuilder();
     ontologyInstance.append("{\"").append(ontology).append("\" :{\"StockPrice\" :{ ").
        append("\"timestamp\": {\"$date\": \"").append(timestampFormat.format(new Date(timestamp))).append("\"},").
 append("\"symbol\": \"").append(symbol).append("\",").
 append("\"name\": \"").append(name).append("\",").
 append("\"volume\": \"").append(volume).append("\",").
 append("\"stockExchange\": \"").append(stockExchange).append("\",").
 append("\"change\": \"").append(change).append("\",").
 append("\"daysLow\": \"").append(daysLow).append("\",").
 append("\"daysHigh\": \"").append(daysHigh).append("\",").
 append("\"lastTradePriceOnly\": \"").append(lastTradePriceOnly).append("\"}}}");
 
 return ontologyInstance.toString();
 }

}

El siguiente elemento que añadiremos a nuestra aplicación será una clase de utilidad, que nos proporicionará dos métodos. Uno para convertir el InputStream que se abre al conectar con el servicio externo de Yahoo, al enviar una petición de solicitud de cotizaciones, en un String con la respuesta del servicio. Y otro para permitir a nuestra App escribir ficheros con los que comunicar mensajes y logs al contenedor de KPs.


package com.indra.sofia2.demos.stock.util;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class Util {

 /**
 * Utilidad para convertir un InputStream en un String
 * @param is
 * @return
 */
 public static String getStringFromInputStream(InputStream is) {
    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();
 
    String line;
    try {
 
      br = new BufferedReader(new InputStreamReader(is));
      while ((line = br.readLine()) != null) {
        sb.append(line);
      }
 
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
       if (br != null) {
         try {
           br.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
       }
     }
 
     return sb.toString();
 }
 
 /**
 * Utilidad para crear ficheros de Mensajes o de Log
 * @param filename
 * @param lines
 * @throws IOException
 */
 public static void writeLinesInFile(String filename, String[] lines) throws IOException {
      PrintWriter pw = new PrintWriter(new FileWriter(filename));
 
       for (String line:lines) {
            pw.write(line+"\n");
       } 
       pw.close();
  }
}

La siguiente clase a programar será la que hará la petición al servicio externo de Yahoo para recibir los datos de cotizaciones. Se apoyará en la enumeración DowJonesStock para construir la query a enviar, y en la clase StockBean para una vez recibida la respuesta, mapearla a una lista de objetos con los datos recibidos por cada empresa:


package com.indra.sofia2.demos.stock.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Clase de utilidad que recubre el API de Yahoo para acceder a la información que nuestro KP necesita 
 * 
 *
 */
public class YahooApiWrapper {
 
 /**
 * Solicita al API de Yahoo las ultimas cotizaciones de las empresas del Dow Jones
 * @return
 * @throws IOException
 */
 public static List<StockBean> getDowJonesLastPrices(String yahooApiUrl) throws IOException{
   //Construye la sentencia YQL (Yahoo Query Language) que interroga a la tabla
   //de cotizaciones solititando todos los valores del Dow Jones
   StringBuilder query = new StringBuilder(
            "select * from yahoo.finance.quote where symbol in (");
 
   DowJonesStock[] stocks=DowJonesStock.values();
   for(int i=0;i<stocks.length;i++){
       DowJonesStock stock=stocks[i];
       query.append("'").append(stock.getSymbol()).append("'");
       if(i<stocks.length-1){
          query.append(","); 
       }
    }
    query.append(")");
 
   //Construye la petición HTTP al API. 
   //El resultado será una cadena JSON que incluirá un array con las cotizaciones
    String fullUrlStr = yahooApiUrl + "?q="+
               URLEncoder.encode(query.toString(), "UTF-8") +
                     "&format=json&diagnostics=true&"+
                     "env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
 
    URL fullUrl=new URL(fullUrlStr);
    InputStream is = fullUrl.openStream();
 
    String response=Util.getStringFromInputStream(is);
    is.close();
 
   //Convierte la respuesta de la petición al API en una lista de objetos StockBean,
   // cada uno representando la cotización de una empresa
   ObjectMapper mapper=new ObjectMapper();
   Map<String, Map<String, Map<String, List<Map<String, String>>>>> objResponse = 
            mapper.readValue(response, Map.class);
 
   List<Map<String, String>> result=objResponse.get("query").get("results").get("quote");
 
   List<StockBean> stocksList=new ArrayList<StockBean>();
   for(Map<String, String> stockPrice:result) {
       StockBean newStock=new StockBean();
       newStock.setTimestamp(System.currentTimeMillis());
       newStock.setSymbol(stockPrice.get("symbol"));
       newStock.setName(stockPrice.get("Name"));
       newStock.setVolume(stockPrice.get("Volume"));
       newStock.setStockExchange(stockPrice.get("StockExchange"));
       newStock.setChange(stockPrice.get("Change"));
       newStock.setDaysLow(stockPrice.get("DaysLow"));
       newStock.setDaysHigh(stockPrice.get("DaysHigh"));
       newStock.setLastTradePriceOnly(stockPrice.get("LastTradePriceOnly"));
 
       stocksList.add(newStock);
    }
 
 
    return stocksList;

 }

}

Finalmente solo falta programar el punto de entrada a nuestro KP, es decir, el método Main al que se invocará en cada ejecución, y que orquesta el flujo de trabajo para primero, invocar al servicio externo de datos programado en la clase YahooApiWrapper, y después, convertir la respuesta ya mapeada a una lista de objetos de tipo StopBean, en un fichero con mensajes en formato ontológico que el contenedor de KPs deberá enviar al SIB.


package com.indra.sofia2.demos.stock;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import com.indra.sofia2.demos.stock.util.StockBean;
import com.indra.sofia2.demos.stock.util.Util;
import com.indra.sofia2.demos.stock.util.YahooApiWrapper;

/**
 * Punto de entrada a nuestra App
 * Controla la ejecución del KP 
 *
 */
public class StockEntryPoint {
 
   //Nombre de la propiedad que nos dará la url del servicio externo de la que recuperamos
   //la información de cotización
   private final static String YAHOO_API_URL="yahooApiUrl";
 
   //Nombre de nuestra ontologia
   private final static String ONTOLOGY_NAME="StockPrice";
 
   //Prefijo de ficheros indicado en la consola de Administración para
   //que el contenedor pueda localizar los ficheros de mensajes 
   private final static String MESSAGE_FILES_PREFIX="DowJonesMessages";
 
   //Prefijo de ficheros indicado en la consola de Administración para
   //que el contenedor pueda localizar los ficheros de log
   private final static String LOG_FILES_PREFIX="DowJonesLog";
 
   public static void main(String args[]){
       try{
         //Carga las propiedades del programa
         Properties prop = new Properties();
         InputStream input = new FileInputStream("DowJonesDataFeed.properties"); 
         prop.load(input);
 
         //Recupera del servicio web los ultimos valores de cotización 
         //para las empresas del Dow Jones
         List<StockBean> lastStockPrices=
            YahooApiWrapper.getDowJonesLastPrices(prop.getProperty(YAHOO_API_URL));
 
         //Convierte dichas cotizaciones en instancias de nuestra ontologia
         String[] messages=new String[lastStockPrices.size()];
         int i=0;
         for(StockBean stockPrice:lastStockPrices){
             messages[i++]=stockPrice.getAsOntologyInstance(ONTOLOGY_NAME);
         }
 
         //Crea un fichero con dichas instancias de nuestra ontologia para
         // que el contenedor de KPs los envie al SIB
         String filename=MESSAGE_FILES_PREFIX+((int)(Math.random()*10000));
         Util.writeLinesInFile(filename, messages);
 
       }catch(Exception e){
            try {
                Util.writeLinesInFile(LOG_FILES_PREFIX, 
                       new String[]{"Error in programm: "+e.getMessage()});
            } catch (IOException e1) {
            }
      }
 }
 
 
 
}

4. Empaquetado del KP:

Al tratarse de una App Java, el contenedor necesita que sea empaquetado como un fichero JAR ejecutable. Esto es, todas las clases que no formen parte del Runtime de Java y que sean necesarias para la ejecución del programa deben incluirse dentro del propio fichero JAR, así como un fichero MANIFEST.MF indicando el punto de entrada (Clase con el método Main).

En el caso de nuestra App, ominitiendo las clases de las librerías de terceros utilizadas, la estructura sería la siguiente:

5. Despliegue en Contenedor de KPs:

Finalmente daremos de alta el KP en el contenedor de KPs. Para ello es necesario ser administrador de Sofia2 o solicitar el despliegue a un administrador.

Una vez autenticados en la consola de administración, elegimos la opción de menú Contenedor de KPs/Apps > Crear KPs/Apps en contenedor. E introducimos la siguiente información:

  • KP: DowJonesStockFeed (Creado en paso 2).
  • Instancia de KP: DowJonesDataFeed (podría ser cualquier otro)
  • Token: El que tenemos dado de alta para el KP.
  • Tipo de KP: Temporizado
  • Cron: 0 0/1 * 1/1 * ? * (Cada minuto, podría ser cualquier otra expresión en función de nuestras necesidades)
  • Lenguaje: Java
  • Programa: Subimos desde nuestra máquina el fichero JAR que empaquetamos en el paso 4.
  • Nombre de programa: DowJonesDataFeed (podría ser cualquier otro)
  • Timeout: 5sg (Daremos algo de margen al tener que invocar a un servicio externo sujeto a retrasos)
  • Prefijo de ficheros de mensajes: DowJonesMessages (Es el prefijo que utilizamos en nuestro código para generar este tipo de ficheros).
  • Perfijo de ficheros de Log: DowJonesLog (Es el prefijo que utilizamos en nuestro código para generar este tipo de ficheros).

  • Descripción: Texto Libre
  • Propiedades: Damos de alta la propiedad yahooApiUrl con la url del API al que haremos las consultas de cotización, que recuperamos en el programa.

6. Comprobación del estado del KP en el contenedor:

Una vez desplegado el KP en el contenedor, podemos monitorizar su estado para ver que está arrancando e insertando información correctamente desde la opción Visualizar:

Así como consultar a la BDTR para consultar las cotizaciones insertadas:

Creando un KP para el contenedor de KPs de Sofia2

Contenedor de KPs en Sofia2

El contenedor de KPs de Sofia2 consiste en un nuevo módulo de la plataforma que permite el despliege de Apps Sofia2, gestionando su ejecución y encargándose del envio al SIB de la información generada por el mismo.

Un programador que desee desplegar sus KPs en el contenedor de Sofia2 deberá realizar una serie de consideraciones durante la programación de los mismos para conseguir una integración plena con el contenedor, y posteriormente deberá registrarlo desde la consola de administración, donde podrá subir el código de su KP al contenedor, así como configurar ciertos aspectos.

A continuación vamos a dar mayor información acerca de los tipos de KPs soportados por el contenedor, así como ciertas consideraciones que deberá cumplir un KP para integrarse con el contenedor. Para mayor información se puede consultar la guía Sofia2-Contenedor de KPs

Tipos de KPs:

Actualmente el contenedor de KPs soporta 3 tipos de KPs:

  • KPs Python: Scripts en lenguaje de programación Python.
  • KPs Java: Ficheros jar comprimidos como jar ejecutables.
  • KPs URL: URL accesible desde el contenedor de KPs (internet o intranet) que ante una petición HTTP devuelva uno o varios mensajes a enviar al SIB.

La ejecución de un KP consiste en invocaciones periodicas programadas mediante una expresión CRON. Una vez se cumple la condición temporal del CRON, el contenedor invoca al KP para su ejecución. Una vez finaliza la ejecución un KP, el contenedor procede a recuperar los mensajes generados y los envía al SIB.

Un KP de tipo Python o Java se despliega físicamente en el contenedor de en un directorio propio donde puede crear ficheros (logs y mensajes) y leer recursos (properties).

Mensajes generados y forma de envio al SIB:

Un Kp administrado en el contenedor de KPs generará mensajes para enviar a un SIB, pero será contenedor de KPs quien envie los mensajes generados por los KPs al SIB.

El contenedor implementando toda la lógica de persistencia de mensajes para evitar la perdida de mensajes en caso de que el SIB no se encuentre disponible. De manera que el programador de un KP deberá delegar el envio de mensajes al contenedor, siendo el contenedor quien asegure el envío al SIB.

Los mensajes recogidos por el contenedor serán enviados en nombre del KP al SIB. Esto es, a efectos de autenticación/autorización se utilizarán las credenciales del propio KP.

Los mensajes se informan al SIB tras la ejecución de la siguiente manera:

  • KPs Java y Python: Creando el propio KP uno o varios ficheros de mensajes, que el contenedor identificará por el nombre, ya que durante el alta del KP en la consola de administración, se informará el prefijo en el nombre de estos ficheros.
  • URL: Devolviendo en el cuerpo de la respuesta HTTP el listado de mensajes a enviar al SIB.

En el caso de mensajes informados por ficheros, será el propio contenedor de KPs quien borre tales ficheros una vez haya leído los mensajes y persistido para su envío al SIB.

Cada mensaje generado por un KP tras su ejecución para ser recogidos por el contenedor de KPs, tendrá el siguiente formato de objeto JSON, siendo el contenedor quien construya y envíe al SIB un mensaje SSAP INSERT con la información del mensaje:

{<ontologia>:{<instancia_ontologia}}

Por ejemplo el siguiente objeto representaria un mensaje SSAP INSERT sobre la ontologia SensorTemperatura:

{“SensorTemperatura”:{ “Sensor”: { “geometry”: { “coordinates”: [ 40.512967, -3.67495 ], “type”: “Point” }, “assetId”: “S_Temperatura_00066”, “measure”: 25, “timestamp”: { “$date”: “2014-04-29T08:24:54.005Z”}}}}}

Dependiendo del tipo de KP, los mensajes serán informados al contenedor de una forma u otra:

  • KPs Java y Python: Se utilizaránficheros de texto donde cada línea contiene un objeto JSON representando un mensaje. Tras finalizar la ejecución del KP, el contenedor leerá el fichero de texto generado línea a línea, construyendo un mensaje SSAP INSERT con cada una. En un mismo fichero es posible generar mensajes haciendo referencia a diferentes ontologías. Por ejemplo, el siguiente fichero seria un fichero válido:

{“SensorTemperatura”:{ “Sensor”: { “measure”: 25, “timestamp”: { “$date”: “2014-04-29T08:24:55.005Z”}}}}

{“SensorTemperatura”:{ “Sensor”: { “measure”: 24, “timestamp”: { “$date”: “2014-04-29T08:25:25.005Z”}}}}

{“SensorTemperatura”:{ “Sensor”: { “measure”: 25, “timestamp”: { “$date”: “2014-04-29T08:25:55.005Z”}}}}

{“SensorTemperatura”:{ “Sensor”: { “measure”: 26, “timestamp”: { “$date”: “2014-04-29T08:26:25.005Z”}}}}

{“SensorTemperatura”:{ “Sensor”: { “measure”: 27, “timestamp”: { “$date”: “2014-04-29T08:26:55.005Z”}}}}

{“SensorTemperatura”:{ “Sensor”: { “measure”: 26, “timestamp”: { “$date”: “2014-04-29T08:27:25.005Z”}}}}

  • KPs URL: Respuesta HTTP de tipo mime application/json conteniendo en el cuerpo de la misma un Array JSON con cada uno de los objetos respresentando un mensaje a enviar al SIB. Por ejemplo, el siguiente Array JSON en el cuerpo de la respuesta seria una respuesta válida:

[

{“SensorTemperatura”:{ “Sensor”: { “measure”: 25, “timestamp”: { “$date”: “2014-04-29T08:24:55.005Z”}}}},

{“SensorTemperatura”:{ “Sensor”: { “measure”: 24, “timestamp”: { “$date”: “2014-04-29T08:25:25.005Z”}}}},

{“SensorTemperatura”:{ “Sensor”: { “measure”: 25, “timestamp”: { “$date”: “2014-04-29T08:25:55.005Z”}}}},

{“SensorTemperatura”:{ “Sensor”: { “measure”: 26, “timestamp”: { “$date”: “2014-04-29T08:26:25.005Z”}}}},

{“SensorTemperatura”:{ “Sensor”: { “measure”: 27, “timestamp”: { “$date”: “2014-04-29T08:26:55.005Z”}}}},

{“SensorTemperatura”:{ “Sensor”: { “measure”: 26, “timestamp”: { “$date”: “2014-04-29T08:27:25.005Z”}}}}

]

Codigos de retorno de un KP al finalizar su ejecución:

Un KP ejecutado en el contenedor de KPs debe finalizar siempre su ejecución tras un tiempo determinado. En caso de no finalizar en el tiempo que tenga asignado, será el contenedor de KPs quien aborte su ejecución.

Los códigos de respuesta válidos interpretables por el contenedor de KPs son:

  • KPs Java y Python: Finalizarán su ejecución devolviendo en la función main un entero interpretable por el contenedor de KPs:
    • 0 (EXIT_SUCCESS): Finalización satisfactoria. El contenedor de KPs contabilizara la ejecución como satisfactoria y procederá a leer los ficheros de mensajes generados para generar los mensajes de INSERT.
    • 1 (EXIT_FAILURE_WITH_MESSAGES): Finalización errónea pero con mensajes. El contenedor de KPs contabilizará la ejecución como errónea, pero considerará que los ficheros de mensajes generados contienen mensajes a enviar al SIB y procederá a su lectura.
    • 2 (EXIT_FAILURE_DISCARDING_MESSAGES): Finalización errónea. El contenedor de KPs contabilizará la ejecución como errónea y descartará los ficheros de mensajes generados por el KP durante la ejecución.
  • KPs URL: Devolverán un código HTTP de respuesta:
    • 200 (HTTP_OK): Finalización satisfactoria. El contenedor de KPs contabilizará la ejecución como satisfactoria y leerá el cuerpo de la respuesta para generar los mensajes de INSERT.
    • Otro código: Finalización errónea. El contenedor de KPs contabilizará le ejecución como errónea y no generará mensajes de INSERT.

Programa Ejecutable del KP:

Los Kps Python y Java necesitan la subida al contenedor de un fichero ejecutable, de manera que debe cumplir ciertas características para poder ser ejecutado por el Runtime correpondiente.

  • KPs Java: Deben ser empaquetados en un fichero JAR autoejecutable. Esto es:
    • Dentro del JAR se deben incluir todas aquellas clases necesarias para la ejecución del KP que no estén incluidas en las librerías de la JRE del contenedor.
    • Debe incluirse un punto de entrada al programa. Esto es, una clase con un método main que controla el inicio y finalización del programa.
    • Debe indicarse el punto de entrada al programa en un fichero MANIFEST.MF indicando la clase donde está el método main mediante la propiedad Main-Class:

Main-Class: com.indra.kp.Main

Por ejemplo, un KP java a desplegar en el contenedor tendría esta estructura:

Donde:

Main.class: Clase que contiene el método main que actua de punto de entrada al programa Java.

MANIFEST.MF: Descriptor del ejecutable Java:

Manifest-Version: 1.0

Class-Path: .

Main-Class: com.indra.kp.Main

  • KPs Python: Deben ser desplegados como scripts Python. Esto es, Deben desplegarse en un fichero que contenga una función main que actue de punto de entrada al programa e incluir todos los import y funciones necesarias para su ejecución.

Propiedades durante la ejecución

Durante el alta de un KP en el contenedor de KPs es posible registrar en la consola de administración un conjunto de propiedades que podrá leer el KP durante su ejecución.

En función del tipo de KP de que se trate, las propiedades serán interpretadas por el contenedor de una forma o otra:

  • KPs Java y Python: El contenedor de KPs creará en el directorio de ejecución del KP un fichero que contendrá todas las propiedades registradas en formato:

<nombre_propiedad>=<valor>

Por ejemplo:

Propiedad1=valor1

Propiedad2=valor2

Propiedad3=valor3

De manera que el programador del KP podrá leer dichas propiedades leyendo el fichero de propiedades creado por el KP en su directorio de ejecución.

El contenedor de KPs creará el fichero de propiedades con el mismo nombre que el KP, pero con extensión .properties

  • KPs URL: En este tipo de KPs se diferencian dos tipos de propiedades:
    • Argumentos de Cabecera: El contenedor de KPs añadirá a la cabecera de la petición HTTP las propiedades de este tipo.
    • Argumentos de Consulta: El contenedor de KPs añadirá a la URL los parámetros indicados de este tipo.

Gestion de KPs en el Contenedor de Sofia2

La gestión de los KPs en el contenedor de Sofia2, se realiza desde la consola de administración de Sofia2

Para dar de alta un nuevo KP en el contenedor de KPs de Sofia2 se dispone en la consola de administración la opción: Contenedor KP’s/APPs > Crear KPs/APPs en contenedor

En esta pantalla es necesario especificar información acerca del KP que se va a dar de alta.

La información común independientemente del tipo de KP es:

  • KP: Identificador del KP registrado en Sofia2 al que pertenece el KP a registrar en el contenedor.
  • Instancia de KP: Identificador de KP a registrar en el contenedor
  • Tipo de contenedor de KP: En la versión actual todos son los KPs son temporizados y se lanzan periódicamente conforme a la expresión CRON.
  • Lenguaje: Lenguaje de programación del KP, permite al contenedor seleccionar el runtime con el que lanzar el KP.
  • Timeout: Tiempo en segundos que el contenedor asigna al KP para completar su ejecución. Si el KP no finaliza en dicho tiempo, el contenedor aborta la ejecución.
  • Descripción: Descripción informativa del contenedor.

En función del lenguaje elegido será necesario informar también:

  • Lenguaje Java o Python:
    • Programa: Fichero ejecutable con el código del programa a ejecutar por el contenedor.
    • Nombre del programa: Nombre que el contenedor dará al programa en el contenedor.
    • Prefijo de ficheros de mensajes: Prefijo que tendrán los ficheros de mensajes generados por el fichero ejecutable. Será lo que el contenedor utilice para
    • Propiedades: Pares de clave-valor con las propiedades que necesita el programa. Estas propiedades se utilizan por el contenedor de KPs para crear un fichero en el directorio de ejecución con dichas propiedades. El fichero de propiedades tendrá el mismo nombre que el programa junto con la extensión .properties.

De este modo si se definen para el programa MiPrograma las siguientes propiedades:

El contenedor creará el fichero MiPrograma.properties en su directorio de ejecución con el siguiente contenido:

Propiedad2=valor2

Propiedad3=valor3

Propiedad1=valor1

  • Lenguaje de tipo URL:
    • URL: Dirección a la que el contenedor hará las peticiones HTTP GET cada vez que se ejecute.
    • Parámetros Cabecera HTTP: Lista de pares clave-valor a incluir en la cabecera de la petición HTTP GET.
    • Parámetros de la petición HTTP: Lista de pares clave-valor con los query param a añadir a la petición HTTP.

Para consultar el listado de KPs en el contenedor de KPs de Sofia2 se dispone en la consola de administración la opción: Contenedor KP’s/APPs > Mis KPs/APPs en Contenedor

Desde esta pantalla es posible buscar filtrando por nombre e identificador de instancia, la lista de KPs que tenemos registrados en el contenedor de KPs.

Asimismo, desde la lista de KPs tenemos acceso a las opciones de Consulta, Actualización y borrado de un KP en el contenedor.

Para consultar el detalle de un KP, desde la pantalla de listado es posible visualizar un KP con el estado actual de todas sus propiedades:

Así como administrar ciertos aspectos de su ejecución tales como:

  • Logs: Es posible descargar en un fichero zip los ficheros de logs generados por un KP así como borrarlos.
  • Mensajes Erroneos: Son mensajes generados por el KP y que tras intentar su envio al SIB como un mensaje de tipo INSERT, el contenedor de KPs ha descartado por alguna razón Es posible tanto descargar en un fichero estos mensajes, como borrarlos.
  • Estado: Es posible detener la ejecución de un KP de manera que mientras se encuentre detenido, el contenedor de KPs no procederá ejecutarlo aunque se cumplan las condiciones especificadas en la expresión CRON.

Y monitorizar la ejecución del KP obteniendo la siguiente información:

  • Número total de ejecuciones.
  • Número de ejecuciones abortadas por el contenedor
  • Número de ejecuciones finalizadas devolviendo un código de error.
  • Tiempo total de ejecución consumido por el KP en el contenedor.
  • Tiempo médio de cada ejecución.
  • Número de mensajes enviados satisfactoriamente al SIB.
  • Número de mensajes leidos por el contenedor y almacenados para envio al SIB.
  • Número de mensajes erroneos tras su envio al SIB

Contenedor de KPs en Sofia2

PUBLICADA RELEASE 2.15.0 DE SOFIA2

Ya está disponible la release 2.15.0 deSOFIA2, esta release también se ha disponibilizado en la Plataforma de Experimentación SOFIA2 CloudLab.

Ver todas las releases

Esta versión añade a la Plataforma las siguientes funcionalidades:

· Certificación de la Plataforma Sofia2 en MongoDB

Tras varios meses de trabajo hemos completado el proceso de certificación de Sofia2 como solución MongoDB Enterprise 2.6 en el ámbito M2M/IoT.

· Integración de la Plataforma con Ruoter Cisco:

Durante esta release ingenieros de Indra y Cisco han trabajado mano a mano para integrar sus modelos Cisco 819 con la Plataforma Sofia2.

La integración de ambas soluciones aporta de forma conjunta:

– Procesamiento lo más cerca posible del sensor, conocida como Fog Computing. Esto permite, entre otras, la toma de decisiones inmediata (ya que los datos no viajan a través de la WAN) y el filtrado de información (reduciendo el consumo de ancho de banda de la solución global).

– Procesamiento agregado de la información recibida de los Cisco 819 en Sofia2, permitiendo ejecución de reglas en tiempo real en función de la información recibida (incluso combinándola con aquella de otros actores), análisis Big Data de la información recibida, publicación de la información a través de nuestro API Manager o compartida con el resto de KPs/APPs de Sofia2, etc.

La integración se ha realizado de manera bidireccional, permitiendo tanto la transmisión de información sensórica desde el router hacia Sofia2, como la configuración de reglas desde Sofia2 hacia el router (a modo push).

· Contenedor de KPs V2:

Se ha extendido el módulo Contenedor de KPS incluyendo entre sus nuevas características:

– Soporte de ejecución de KPs gestionados y embebidos en el contenedor en otros lenguajes:

Soportándose ahora la ejecución Java de KPs gestionados programados en Java o de tipo URL, en este tipo se informa al contenedor una URL así como los parámetros de la query y de la cabecera de la petición. La ejecución del KP consistirá en una petición HTTP GET por parte del contenedor a dicha URL y la respuesta se transformará en los mensajes INSERT a enviar al SIB.

– Nuevas opciones de administración de KPs contenidos permitiendo:

Posibilidad de Arrancar y Detener la ejecución de un KP.

Descarga de mensajes erróneos que han sido descartados para su envío por el contenedor.

Monitorización de la ejecución del KP

· API iOS:

Esta API era una de las más esperadas por la comunidad de desarrolladores Sofia2. Este API implementada por nuestro colaborador Carlos Romero (gracias!) está escrita en lenguaje ObjectiveC y se comunica con el SIB vía WebSockets.

Se ha usado XCode 6.1.1 y se soporta el Deployment target es 7.1 en adelante

Testeada para soportar dispositivos iPad.

Para instalarlo basta descargar el paquete desde la sección de Desarrollo en e importarlo en nuestro XCode.

El API iOS incluye un ejemplo donde se ejemplifica el uso de los comandos del protocolo SSAP mediante una interfaz que muestra el protocolo Sofia2.:

· Sistema de Caché en API Manager

Esta versión incorpora un sistema de caché en el módulo API-Manage que permite cachear las llamadas a las APIs.

Seleccionado la opción Cachear Resultados se introduce un valor en minutos de tiempo de Cacheo de los resultados de peticiones al API.

Dicho tiempo de cache debe estar entre los límites permitidos (configurable por administrador).

· Despliegue configurable del API Manager

A partir de la versión 2.15 de Sofia2 el API Manager puede desplegarse en modo StandAlone (no requiere de un SIB) o bien asociado a un SIB (delega las peticiones al SIB).

Puede configurarse el modo de despliegue con una propiedad.

#sibapi.deployment=SIB_CONNECTED

sibapi.deployment=STAND_ALONE

· Diversas mejoras en API Manager

Además de las funcionalidades ya mencionadas se han incorporado mejoras en el API Manager a nivel de performance, soporte APIs con otros formatos de respuesta, ejemplos,…

· Certificación del despliegue de la Plataforma sobre WAS 8.5

Desde esta release WebSphere 8.5 es una de las plataformas certificadas para sofia2, esto permite desplegar Sofia2 sobre WAS 8.5 con soporte.

· API REST Social Media

En la release 2.15 de Sofia2 se han incluido APIS REST que permiten explotar las capacidades Social Media sobre Twitter sin necesidad de acceder a la consola Web.

· Mejoras y optimizaciones en Arquitectura KP Modelo

En esta release se han realizado nuevas pruebas de estress ante situaciones no óptimas y se ha optimizado el comportamiento de la infraestructura.

· Solución de incidencias y mejoras

Siguiendo con el compromiso y el nivel de soporte del equipo Sofia2 se han solucionado incidencias que se han disponibilizado en parches (incluido en el entorno CloudLab).

PUBLICADA RELEASE 2.15.0 DE SOFIA2

SOFIA2 RELEASE 2.15.0 PUBLISHED

Sofia2 new release 2.15.0 is now available. This release has also been deployed in the experimentation platform Sofia2 CloudLab.

See all releases

This new version adds the following features to the platform:

· Certification Process of Sofia2 Platform as MongoDB Enterprise Solution

After a few months of work Sofia2 certification process was completed as MongoDB Enterprise 2.6 solution in the area M2M / IoT.

· Platform Integration with Cisco Ruoter:

During this release Indra and Cisco engineers have worked closely to integrate Cisco 819 models with Sofia2 Platform.

The integration of the solutions combines the advantages of:

– Processing close to the sensor, known as Fog Computing. This allows the immediate decision-making (data do not travel through the WAN) and filtering information (by reducing the bandwidth consumption of the overall solution).

– Aggregated processing of information received from the Cisco 819 on Sofia2, allowing execution of rules in real time according to the information received (even combining it with other information), Big Data analysis of the information received, publication of information through our API Manager or shared with other KPs / APPs of Sofia2, etc.

Integration has done in both directions, allowing transmission of the sensor information from the router to Sofia2 and rule configuration from Sofia2 to the router (push mode).

¡Un gran trabajo conjunto de dos grandes empresas del sector!

· KPs Container V2:

The KP Container module has been extended including among its new features:

– Support execution of managed and embedded KPs in the container in other languages:

We support now the execution ok managed KPs developed on Java or URL-type, for this kind of KP it is necessary to indicate an URL and its query and header parameters if they are required. The execution of the KP will be a HTTP GET request to the URL from the KPs Container and the response will be transformed into the INSERT messages to be sent to the SIB.

-New management features for contained KPs

Starting and Stopping the execution of a KP.

Downloading of wrong messages discarded by the container to be sent to the SIB.

KP execution monitoring.

· iOS API:

This API was one of the most desired API by the developer community Sofia2. This API has been implemented by our collaborqtor Carlos Romero (thanks!), is written in Objective-C language and communicates with the Sofia2 SIB by WebSockets.

It has been developed with XCode 6.1.1 and supports the target Deployment from 7.1.

To install it just download the package from the Development section and import it into your XCode.

The iOS API includes an example with an interface that shows the Sofia2 protocol:

· API-Manager Cache System

A new cache system has been added to the API-Manager module.

The period of cache configuration is done in the creation/modification API screen. A new section includes :

If the Caching Results option is selected, you can specify a value in minutes of Caching.

This value cache must be between the permissible range (configurable by admin) .

· API Manager configurable Deployment:

In this new version the API Manager module allows StandAlone or SIB-associated deployment modes.

To set the operating mode , there is a new property:

#sibapi.deployment=SIB_CONNECTED

sibapi.deployment=STAND_ALONE

· Various improvements Manager API

In addition to the features mentioned we have incorporated improvements at performance, APIs support with other response formats, examples, …

· Platform deployment certificated on WAS 8.5

From this release WebSphere 8.5 is one of the certified Sofia2 platforms, this allows deploy Sofia2 on WAS 8.5 with support.

· REST API Social Media

In Sofia2 release 2.15 we have included REST APIs that allow use the Social Media capabilities on Twitter without access the Web console.

· Improvements and optimizations on KP Model Architecture

On this release we have made new stress tests on non-optimal situations and optimized the infrastructure performance.

· Several bugs and improvements fixings

With the Sofia2 engagement and support we have solved incidents and deployed patches (including the CloudLab environment).

SOFIA2 RELEASE 2.15.0 PUBLISHED