FIWARE Core Context Management NGSI v2

Description: Este es un Tutorial Introductorio a la Plataforma FIWARE. Empezaremos con los datos del buscador de tiendas de una cadena de supermercados y crearemos una aplicación muy sencilla "Powered by FIWARE" pasando la dirección y ubicación de cada tienda como datos de contexto al agente de contexto FIWARE.

El tutorial usa comandos cUrl en el, pero también está disponible como documentación Postman

Ejecutar en Postman


Arquitectura

Nuestra aplicación de demostración sólo hará uso de un componente FIWARE - el Orion Context Broker. El uso del Orion Context Broker es suficiente para que una aplicación califique como "Powered by FIWARE".

Actualmente, el Orion Context Broker se basa en la tecnología de código abierto MongoDB para la persistencia de los datos de contexto que contiene. Por lo tanto, la Arquitectura constará de dos elementos:

  • El Orion Context Broker quien recibirá las peticiones usando NGSI
  • La base de datos que hay por debajo MongoDB :
    • Utilizada por el Orion Context Broker para mantener información de datos de contexto como los datos de las entidades, suscripciones y registros

Dado que todas las interacciones entre los dos elementos son iniciadas por peticiones HTTP, estos pueden ser contenedorizado sy correr desde los puertos expuestos.

Prerequisitos

Docker

Para mantener las cosas simples, ambos componentes se ejecutarán usando Docker. Docker es una tecnología de contenedores que permite aislar diferentes componentes en sus respectivos entornos.

  • Para instalar Docker en Windows siga las instrucciones aquí
  • Para instalar Docker en Mac siga las instrucciones aquí
  • Para instalar Docker en Linux siga las instrucciones aquí

Docker Compose (Opcional)

Docker Compose es una herramienta para definir y ejecutar aplicaciones Docker multi-contenedor. A Se utiliza el archivo YAML para configurar los servicios requeridos para la aplicación. Esto significa que todos los servicios de los contenedores pueden ser lanzados en un solo comando. Docker Compose se instala de forma predeterminada como parte de Docker para Windows y Docker para Mac, sin embargo los usuarios de Linux tendrá que seguir las instrucciones que se encuentran aquí

Puede comprobar sus versiones actuales de Docker y Docker Compose usando los siguientes comandos:

docker-compose -v
docker version

Por favor, asegúrese de que está utilizando la versión 18.03 o superior de Docker y la versión 1.21 o superior de Docker Compose y actualícela si es necesario.

Iniciando los contenedores

Opcion 1) Usando los comandos de Docker directamente

Primero haga pull de las imágenes necesarias de Docker Hub y cree una red para que nuestros contenedores se conecten a ella:

docker pull mongo:3.6
docker pull fiware/orion
docker network create fiware_default

Para iniciar un contenedor Docker corriendo una base de datos MongoDB conectada a la red tenemos que ejecutar el siguiente comando:

docker run -d --name=mongo-db --network=fiware_default \
  --expose=27017 mongo:3.6 --bind_ip_all --smallfiles

El Orion Context Broker se puede iniciar y conectar a la red empleando el siguiente comando:

docker run -d --name fiware-orion -h orion --network=fiware_default \
  -p 1026:1026  fiware/orion -dbhost mongo-db

Nota: Si desea limpiar el entorno y empezar de nuevo puede hacerlo con los siguientes comandos:

docker stop fiware-orion docker rm fiware-orion docker stop mongo-db docker rm mongo-db docker network rm fiware_default

Opcion 2) Usando Docker Compose

Todos los servicios pueden ser inicializados desde la línea de comandos usando el comando "docker-compose". Por favor, clone el repositorio y cree las imágenes necesarias ejecutando los comandos como se muestra:

git clone https://github.com/FIWARE/tutorials.Getting-Started.git
cd tutorials.Getting-Started

docker-compose -p fiware up -d

Nota: Si desea limpiar el entorno y empezar de nuevo puede hacerlo con los siguientes comandos:

docker-compose -p fiware down

Creando tu primera Powered by FIWARE app

Comprobando la salud del servicio

Puede comprobar si el Orion Context Broker se está ejecutando haciendo una petición HTTP al puerto expuesto:

1 Peticion:

curl -X GET \
  'http://localhost:1026/version'

Respuesta:

La respuesta debe parecerse a la siguiente:

{
    "orion": {
        "version": "1.12.0-next",
        "uptime": "0 d, 0 h, 3 m, 21 s",
        "git_hash": "e2ff1a8d9515ade24cf8d4b90d27af7a616c7725",
        "compile_time": "Wed Apr 4 19:08:02 UTC 2018",
        "compiled_by": "root",
        "compiled_in": "2f4a69bdc191",
        "release_date": "Wed Apr 4 19:08:02 UTC 2018",
        "doc": "https://fiware-orion.readthedocs.org/en/master/"
    }
}

Que pasa si obtengo Failed to connect to localhost port 1026: Connection refused como respuesta?

Si recibes una respuesta Connection refused, el Orion Content Broker no se puede encontrar donde se espera para este tutorial - necesitas sustituir la URL y el puerto en cada comando cUrl con la dirección IP correcta. Todos los comandos cUrl de este tutorial suponen que Orion está disponible en localhost:1026 Prueba las siguientes soluciones:

  • Para comprobar si los contenedores de docker están corriendo pruebe lo siguiente

docker ps

Tendría que ver los dos contenedores corriendo. Si Orion no está corriendo, puede reiniciar los contenedores si es necesario. Este comando también mostrará la información de los puertos abiertos

  • Si tiene instalado docker-machine y Virtual Box, el contenedor de docker de orio quizás corra en otra direccion IP - Con el siguiente comando podrá obtener la IP del host:

curl -X GET \ 'http://$(docker-machine ip default):1026/version'

De forma alternativa, ejecute todos los comandos cUrl desde la red de los contenedores:

docker run --network fiware_default --rm appropriate/curl -s \ -X GET 'http://orion:1026/version'

Creando datos de contexto

En el fondo, FIWARE es un sistema de gestión de información contextual, por lo que permite añadir algunos datos contextuales al sistema mediante creando dos nuevas entidades (tiendas en Berlin). Cualquier entidad debe tener un id y atributos de tipo type, los atributos adicionales son opcionales y dependerán del sistema que se describa. Cada atributo adicional debe tener también un tipo definido y un atributo de valor.

2 Petición:

curl -iX POST \
  'http://localhost:1026/v2/entities' \
  -H 'Content-Type: application/json' \
  -d '
{
    "id": "urn:ngsi-ld:Store:001",
    "type": "Store",
    "address": {
        "type": "PostalAddress",
        "value": {
            "streetAddress": "Bornholmer Straße 65",
            "addressRegion": "Berlin",
            "addressLocality": "Prenzlauer Berg",
            "postalCode": "10439"
        },
        "metadata": {
            "verified": {
                "value": true,
                "type": "Boolean"
            }
        }
    },
    "location": {
        "type": "geo:json",
        "value": {
             "type": "Point",
             "coordinates": [13.3986, 52.5547]
        }
    },
    "name": {
        "type": "Text",
        "value": "Bösebrücke Einkauf"
    }
}'

3 Petición:

Cada entidad siguiente debe tener un "id" único para el "tipo" dado.

curl -iX POST \
  'http://localhost:1026/v2/entities' \
  -H 'Content-Type: application/json' \
  -d '
{
    "type": "Store",
    "id": "urn:ngsi-ld:Store:002",
    "address": {
        "type": "PostalAddress",
        "value": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "metadata": {
            "verified": {
                "value": true,
                "type": "Boolean"
            }
        }
    },
    "location": {
        "type": "geo:json",
        "value": {
             "type": "Point",
             "coordinates": [13.3903, 52.5075]
        }
    },
    "name": {
        "type": "Text",
        "value": "Checkpoint Markt"
    }
}'

Directrices de los modelos de datos

Aunque cada entidad de datos dentro de su contexto variará según su caso de uso, la estructura común dentro de cada entidad de datos debe ser estandarizada para promover la reutilización. Las directrices completas de los modelos de datos de FIWARE se pueden encontrar aquí. Este tutorial demuestra el uso de las siguientes recomendaciones:

Todos los terminos están definidos en inglés americano

Aunque los campos value de los datos de contexto pueden estar en cualquier idioma, todos los atributos y tipos se escriben usando el idioma inglés.

Los nombres de los tipos de entidad deben comenzar con una letra mayúscula

En este caso sólo tenemos un tipo de entidad - Store

Los ID de las entidades deben ser una URN siguiendo las directrices de NGSI-LD

NGSI-LD ha sido recientemente publicado como una especificación completa de la ETSI, la propuesta es que cada id es una URN que sigue un formato estándar: urn:ngsi-ld:<entity-type>:<entity-id>. Esto significará que cada id en el sistema será único.

Los nombres de los tipos de datos deben reutilizar los tipos de datos de schema.org siempre que sea posible

Schema.org es una iniciativa para crear esquemas de datos estructurados comunes. Para promover la reutilización hemos utilizado deliberadamente el los tipos de atributo Text y PostalAddress con nuestra entidad Store . Otros estándares existentes como Open311 (para el seguimiento de problemas de ciudad) o Datex II (para sistemas de tranposte) tambine pueden ser usado, pero la clave es comprobar la existencia de el mismo atributo en modelos de datos existentes y reusarlo.

Uso de la sintaxis camel case para el nombre de los atributos

Los atributos streetAddress, addressRegion, addressLocality ypostalCode son todos ejemplo del uso de camel case.

Location information should be defined using address and location attributes

  • Hemos usado un atributo address para las direcciones civiles definido por schema.org
  • Hemos usado el atributo location para las coordenadas geográficas.

Uso de GeoJSON para codificar propiedades geoespaciales

GeoJSON es un formato estándar abierto diseñado para representar elementos geográficos simples. El atributo location ha sido condificado como un elemento geoJSON de tipo punto Point.

Metadatos de atributos

Los metadatos son "datos acerca de los datos", son información adicional usada para describir propiedades de los valores de los atributos como precisión, proveedor del dato, o marca temporal. Existen diveros accuracy, provider, or a timestamp. Ya existen varios atributos de metadatos predefinidos y sus nombres están reservados:

  • dateCreated (tipo: DateTime): Fecha de creación del atributo como un string ISO 8601.
  • dateModified (tipo: DateTime): fecha de modificación del atributo como un string ISO 8601.
  • previousValue (tipo: cualquiera): sólo en las notificaciones. El valor anterior
  • actionType (tipo: Text): sólo en las notificaciones.

Un metadato que se puede encontrar en atributos de tipo address. es verified que indica cuando la dirección se ha confirmado

Consultando datos de contexto

Una aplicación puede solicitar datos de contexto haciendo peticiones HTTP al Orion Context Broker. La interfaz NGSI existente nos permite hacer consultas complejas y filtrar los resultados.

En este momento, para la demostración del buscador de tiendas, todos los datos de contexto se han añadido directamente a través de peticiones HTTP, sin embargo, en una solución inteligente más compleja, el Orion Context Broker también puede recuperar el contexto directamente de los sensores adjuntos asociados a cada entidad.

Aquí hay algunos ejemplos, en cada caso se ha utilizado el parámetro de consulta options=keyValues para acortar las respuestas quitando los elementos de tipo de cada atributo

Obteniendo datos de la entidad por ID

Este ejemplo devuelve los datos de urn:ngsi-ld:Store:001

4 Petición:

curl -G -X GET \
   'http://localhost:1026/v2/entities/urn:ngsi-ld:Store:001' \
   -d 'options=keyValues'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

{
    "id": "urn:ngsi-ld:Store:001",
    "type": "Store",
    "address": {
        "streetAddress": "Bornholmer Straße 65",
        "addressRegion": "Berlin",
        "addressLocality": "Prenzlauer Berg",
        "postalCode": "10439"
    },
    "location": {
        "type": "Point",
        "coordinates": [13.3986, 52.5547]
    },
    "name": "Bösebrücke Einkauf"
}

OObteniendo datos de la entidad por tipo

Este ejemplo devuelve el dato de todas las entidades Store con sus datos de contexto. El parámetro type limita la respuesta sólo a las entidades de tipo tienda

5 Petición:

curl -G -X GET \
    'http://localhost:1026/v2/entities' \
    -d 'type=Store' \
    -d 'options=keyValues'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

[
    {
        "id": "urn:ngsi-ld:Store:001",
        "type": "Store",
        "address": {
            "streetAddress": "Bornholmer Straße 65",
            "addressRegion": "Berlin",
            "addressLocality": "Prenzlauer Berg",
            "postalCode": "10439"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3986, 52.5547]
        },
        "name": "Bose Brucke Einkauf"
    },
    {
        "id": "urn:ngsi-ld:Store:002",
        "type": "Store",
        "address": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3903, 52.5075]
        },
        "name": "Checkpoint Markt"
    }
]

Filtrando datos de contexto comparando los valores de los atributos

Este ejemplo devuelve todos las tiendas con el atributo name con el valor Checkpoint Markt. Se puede filtrar usando el parámetro q - si una cadena tiene espacios en el, se puede condificar en URL y mantenerse entre comillas simples ' = %27

6 Petición:

curl -G -X GET \
    'http://localhost:1026/v2/entities' \
    -d 'type=Store' \
    -d 'q=name==%27Checkpoint%20Markt%27' \
    -d 'options=keyValues'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

[
    {
        "id": "urn:ngsi-ld:Store:002",
        "type": "Store",
        "address": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3903, 52.5075]
        },
        "name": "Checkpoint Markt"
    }
]

Filtrar datos de contexto comparando valores de un sub-atributo

Este ejemplo devuelve todas las tiendas encontradas en Kreuzberg District.

El filtrado se puede hacer usando el parámetro q - los sub-atributos Los sub-atributos se apuntan usando la sintaxis de puntos, por ejemplo, address.addressLocality

7 Petición:

curl -G -X GET \
    'http://localhost:1026/v2/entities' \
    -d 'type=Store' \
    -d 'q=address.addressLocality==Kreuzberg' \
    -d 'options=keyValues'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

[
    {
        "id": "urn:ngsi-ld:Store:002",
        "type": "Store",
        "address": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3903, 52.5075]
        },
        "name": "Checkpoint Markt"
    }
]

Filtrar datos de contexto buscando por metadato

Este ejemplo devuelve todos los datos de las entidades Store con la dirección verificada.

Las búsquedas por metadatos se pueden usar empleando el parámetro mq.

8 Petición:

curl -G -X GET \
    'http://localhost:1026/v2/entities' \
    -d 'type=Store' \
    -d 'mq=address.verified==true' \
    -d 'options=keyValues'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

[
    {
        "id": "urn:ngsi-ld:Store:001",
        "type": "Store",
        "address": {
            "streetAddress": "Bornholmer Straße 65",
            "addressRegion": "Berlin",
            "addressLocality": "Prenzlauer Berg",
            "postalCode": "10439"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3986, 52.5547]
        },
        "name": "Bösebrücke Einkauf"
    },
    {
        "id": "urn:ngsi-ld:Store:002",
        "type": "Store",
        "address": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3903, 52.5075]
        },
        "name": "Checkpoint Markt"
    }
]

Filtrando datos de contexto comparando los valores de un atributo geo:json

Este ejemplo devuelve todas las tiendas a 1.5Km de distancia de La puerta de Brandenburgo en Berlin (52.5162N 13.3777W)

9 etición:

curl -G -X GET \
  'http://localhost:1026/v2/entities' \
  -d 'type=Store' \
  -d 'georel=near;maxDistance:1500' \
  -d 'geometry=point' \
  -d 'coords=52.5162,13.3777'

Respuesta:

Debido al uso del modificador options=keyValues, la respuesta consta solo de un JSON sin los attributos type y sin elementos metadata.

[
    {
        "id": "urn:ngsi-ld:Store:002",
        "type": "Store",
        "address": {
            "streetAddress": "Friedrichstraße 44",
            "addressRegion": "Berlin",
            "addressLocality": "Kreuzberg",
            "postalCode": "10969"
        },
        "location": {
            "type": "Point",
            "coordinates": [13.3903, 52.5075]
        },
        "name": "Checkpoint Markt"
    }
]

Proximos pasos

Quieres aprender como añadir más complejidad a tu aplicación añadiendo funcionalidades avanzadas? Puedes encontrarlas leyendo otros tutoriales de esta misma serie

Desarrollo iterativo

El contexto del ejemplo buscador de tienda es muy simple, se puede ampliar fácilmente para que contenga la totalidad de una gestión stock.

se puede ampliar fácilmente para que contenga el conjunto de un sistema de gestión de existencias pasando el recuento de existencias actual de cada tienda como datos de contexto al sistema, pasando el recuento de existencias actual de cada tienda como datos de contexto al Orion Context Broker.

Hasta aquí, muy sencillo, pero considere los siguientes pasos de esta aplicación Smart:

  • Se pueden crear cuadros de mando en tiempo real para controlar el estado del stock en cada tienda mediante el componente de visualización [Wirecloud]
  • La disposición actual tanto del almacén como de la tienda podría pasarse al corredor de contexto para que la ubicación del stock pueda visualizarse en un mapa [Wirecloud]
  • Componentes de gestión de usuarios [Wilma, AuthZForce, Keyrock] pueden ser añadidos, así, sólo los directores de las tiendas pueden cambiar el precio de los artículos.
  • Se podría activar una alerta de umbral en el almacén a medida que se venden las mercancías para asegurar que las estanterías no se dejen vacías. [publish/subscribe function of Orion Context Broker]
  • Cada lista generada de artículos a ser colocados en el almacén podría ser calculada para maximizar la eficiencia del reabastecimiento [Complex Event Processing - CEP]
  • Se podría añadir un sensor de movimiento en la entrada para contar el número de clientes [IDAS]
  • El sensor de movimiento podría hacer sonar una campana cada vez que un cliente entra [IDAS]
  • Se podría añadir una serie de cámaras de vídeo para introducir una señal de vídeo en cada tienda. [Kurento]
  • Las imágenes de vídeo podrían ser procesadas para reconocer dónde están los clientes dentro de una tienda [Kurento]
  • Al mantener y procesar los datos históricos dentro del sistema, se puede calcular el tiempo de permanencia y por donde transitan - estableciendo qué áreas de la tienda son de mayor interés [conexión a través de Cygnus o Apache Nifi]
  • El reconocimiento de patrones de comportamientos inusuales pueden ser utilizados para disparar una alerta para evitar el robo [Kurento]
  • Los datos sobre el movimiento de las multitudes serían útiles para la investigación científica - los datos sobre el estado de la tienda podrían ser publicados externamente [extensions to CKAN]

Cada iteración añade valor a la solución a través de los componentes existentes con interfaces estándar y, por lo tanto, minimiza el tiempo de desarrollo.