diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 93f1361..0000000 --- a/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -npm-debug.log diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index ddf132d..0000000 --- a/.gitpod.yml +++ /dev/null @@ -1,29 +0,0 @@ -tasks: - - name: Pull Images - init: ./services create - -ports: - - name: Orion - description: Context Broker - port: 1026 - onOpen: notify - - name: Tutorial App - description: Web app displaying context data - port: 3000 - onOpen: open-preview - - name: Tutorial Devices - description: Dummy IoT Sensors over HTTP - port: 3001 - onOpen: ignore - - name: IoT Agent (North Port) - description: NGSI data and device provisioning - port: 4041 - onOpen: ignore - - name: IoT Agent (South Port) - description: Ultralight HTTP measures - port: 7896 - onOpen: ignore - - name: MongoDB - description: Database for Orion + IoT Agent - port: 27017 - onOpen: ignore \ No newline at end of file diff --git a/FIWARE IoT Agent.postman_collection.json b/FIWARE IoT Agent.postman_collection.json deleted file mode 100644 index b9ecf43..0000000 --- a/FIWARE IoT Agent.postman_collection.json +++ /dev/null @@ -1,1434 +0,0 @@ -{ - "info": { - "_postman_id": "6b14053b-d153-4984-a955-6d4036dd3078", - "name": "FIWARE IoT Agent", - "description": "This tutorial introduces the concept of an **IoT Agent** and wires up the dummy [UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) IoT devices created in the\n[previous tutorial](https://github.com/Fiware/tutorials.IoT-Sensors) so that measurements can be read \nand commands can be sent using [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2) requests sent to the [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/).\n\nThe `docker-compose` files for this tutorial can be found on GitHub: \n\n![GitHub](https://fiware.github.io/tutorials.Historic-Context/icon/GitHub-Mark-32px.png) [FIWARE 202: Provisioning an IoT Agent](https://github.com/Fiware/tutorials.IoT-Agent)\n\n# What is an IoT Agent?\n\n> \"In every operation there is an above the line and a below the line.\n> Above the line is what you do by the book. Below the line is how you\n> do the job.\"\n>\n> — John le Carré (A Perfect Spy)\n\nAn IoT Agent is a component that lets a group of devices send their data to and be managed from a Context Broker\nusing their own native protocols. IoT Agents should also be able to deal with security aspects of the Fiware \nplatform (authentication and authorization of the channel) and provide other common services to the device programmer.\n\nThe Orion Context Broker exclusively uses [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2) requests for all\nof its interactions. Each IoT Agent provides a **North Port** [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2)\ninterface which is used for context broker interactions and all interactions beneath this port occur using the **native protocol**\nof the attached devices. \n\nIn effect, this brings a standard interface to all IoT interactions at the context information management level. \nEach group of IoT devices are able to use their own propriatory protocols and disparate transport mechanisms under\nthe hood whilst the associated IoT Agent offers a facade pattern to handle this complexity.\n\nIoT Agents already exist or are in development for many common transports and protocols. Examples include the following: \n\n* [IoTAgent-JSON](http://fiware-iotagent-json.readthedocs.io/en/latest/) (HTTP/MQTT transport) - a bridge between an HTTP/MQTT+JSON based protocol and NGSI\n* [IoTAgent-LWM2M](http://fiware-iotagent-lwm2m.readthedocs.io/en/latest) (CoaP transport) - a bridge between the Lightweight M2M protocol and NGSI\n* [IoTAgent-UL](http://fiware-iotagent-ul.readthedocs.io/en/latest) (HTTP/MQTT transport) - a bridge between the UltraLight2.0 protocol and NGSI \n* [IoTagent-LoraWAN](http://fiware-lorawan.readthedocs.io/en/latest) (CoaP transport) - a bridge between the LoraWAN protocol and NGSI\n\n## Southbound Traffic (Commands)\n\nHTTP requests generated by the from the Context Broker and passed downwards towards an IoT device (via\nan IoT agent) are known as southbound traffic. Southbound traffic consists of **commands** made to \nactuator devices which alter the state of the real world by their actions. \n\nFor example to switch on a real-life UltraLight 2.0 **Smart Lamp** the following interactions would occur:\n\n1. An request is sent to the **Context broker** to invoke the `on` command of the **Smart Lamp** via NGSI\n2. The **Context Broker** finds the entity within the context and notes that the context provision for this \n attribute has been delegated to the IoT Agent\n3. The **Context broker** sends an NGSI request to the North Port of the **IoT Agent** to invoke the command\n4. The **IoT Agent** receives this Southbound request and converts it to UltraLight 2.0 syntax and passes it on to the **Smart Lamp** \n5. The **Smart Lamp** switches on the lamp and returns the result of the command to the **IoT Agent** in UltraLight 2.0 syntax\n6. The **IoT Agent** receives this Northbound request, interprets it and passes the result of the interaction into\n the context by making an NGSI request to the **Context Broker**.\n6. The **Context Broker** receives this Northbound request and updates the context with the result of the command.\n\n\n![](https://fiware.github.io/tutorials.IoT-Agent/img/command-swimlane.png)\n\n* Requests between **User** and **Context Broker** use NGSI\n* Requests between **Context Broker** and **IoT Agent** use NGSI\n* Requests between **IoT Agent** and **IoT Device** use native protocols\n* Requests between **IoT Device** and **IoT Agent** use native protocols\n* Requests between **IoT Agent** and **Context Broker** use NGSI\n\n\n## Northbound Traffic (Measurements)\n\nRequests generated from an IoT device and passed back upwards towards the Context Broker (via an \nIoT agent) are known as northbound traffic. Northbound traffic consists of **measurements** made\nby sensor devices and relays the state of the real world into the context data of the system.\n\nFor example for a real-life **Motion Sensor** to send a count measurement the following interactions would occur:\n\n1. A **Motion Sensor** makes a measurement and passes the result to the **IoT Agent**\n2. The **IoT Agent** receives this Northbound request, converts the result from UltraLight syntax\n and passes the result of the interaction into the context by making an NGSI request to the **Context Broker**.\n3. The **Context Broker** receives this Northbound request and updates the context with the result of the measurement. \n\n\n![](https://fiware.github.io/tutorials.IoT-Agent/img/measurement-swimlane.png)\n\n* Requests between **Iot-Device** and **IoT-Agent** use native protocols\n* Requests between **Iot-Agent** and **Context-Broker** use NGSI\n\n> **Note** Other more complex interactions are also possible, but this overview is sufficient to understand the basic\n> principles of an IoT Agent.\n\n## Common Functionality\n\nAs can be seen from the previous sections, although each IoT Agent will be unique since they interpret different\nprotocols, there will a large degree of similarity between IoT agents. \n\n* Offering a standard location to listen to device updates\n* Offering a standard location to listen to context data updates\n* Holding a list of devices and mapping context data attributes to device syntax\n* Security Authorization\n\nThis base functionality has been abstracted out into a common [IoT Agent framework library](https://fiware-iotagent-node-lib.readthedocs.org)\n\n#### Device Monitor\n\nFor the purpose of this tutorial, a series of dummy IoT devices have been created, which will be attached to the context broker.\nThe state of each device can be seen on the UltraLight device monitor web-page found at: `http://localhost:3000/device/monitor`\n\n![FIWARE Monitor](https://fiware.github.io/tutorials.IoT-Agent/img/device-monitor.png)\n\n# Architecture\n\nThis application builds on the components created in [previous tutorials](https://github.com/Fiware/tutorials.Subscriptions/). It\nwill make use of two FIWARE components - the [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) and the [IoT Agent for UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/). Usage of the Orion Context Broker is sufficient for an application to qualify as *“Powered by FIWARE”*.\nBoth the Orion Context Broker and the IoT Agent rely on open source [MongoDB](https://www.mongodb.com/) technology to keep persistence of the information they hold. We will also be using the dummy IoT devices created in the [previous tutorial](https://github.com/Fiware/tutorials.IoT-Sensors/) \n\n\nTherefore the overall architecture will consist of the following elements:\n\n* The FIWARE [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) which will receive requests using [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2)\n* The FIWARE [IoT Agent for UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/) which will receive southbound requests using [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2) and convert them to [UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) commands for the devices\n* The underlying [MongoDB](https://www.mongodb.com/) database :\n + Used by the **Orion Context Broker** to hold context data information such as data entities, subscriptions and registrations\n + Used by the **IoT Agent** to hold device information such as device URLs and Keys\n* The **Context Provider NGSI** proxy is not used in this tutorial. It does the following:\n + receive requests using [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2)\n + makes requests to publicly available data sources using their own APIs in a proprietory format \n + returns context data back to the Orion Context Broker in [NGSI](https://fiware.github.io/specifications/OpenAPI/ngsiv2) format.\n* The **Stock Management Frontend** is not used in this tutorial will it does the following:\n + Display store information\n + Show which products can be bought at each store\n + Allow users to \"buy\" products and reduce the stock count.\n* A webserver acting as set of [dummy IoT devices]](https://github.com/Fiware/tutorials.IoT-Sensors) using the [UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) protocol running over HTTP.\n\nSince all interactions between the elements are initiated by HTTP requests, the entities can be containerized and run from exposed ports. \n\n![](https://fiware.github.io/tutorials.IoT-Agent/img/architecture.png)\n\nThe necessary configuration information for wiring up the IoT devices and the IoT Agent can be seen in the services section of the associated `docker-compose.yml` file:\n\n## Dummy IoT Devices Configuration\n\n```yaml\n context-provider:\n image: fiware/cp-web-app:latest\n hostname: context-provider\n container_name: context-provider\n networks:\n - default\n expose:\n - \"3000\"\n - \"3001\"\n ports:\n - \"3000:3000\"\n - \"3001:3001\"\n environment:\n - \"DEBUG=proxy:*\"\n - \"PORT=3000\"\n - \"IOTA_HTTP_HOST=iot-agent\"\n - \"IOTA_HTTP_PORT=7896\"\n - \"DUMMY_DEVICES_PORT=3001\"\n - \"DUMMY_DEVICES_API_KEY=4jggokgpepnvsb2uv4s40d59ov\"\n```\n\nThe `context-provider` container is listening on two ports: \n\n* Port `3000` is exposed so we can see the web-page displaying the Dummy IoT devices.\n* Port `3001` is exposed purely for tutorial access - so that cUrl or Postman can make UltraLight commands\n without being part of the same network.\n\n\nThe `context-provider` container is driven by environment variables as shown:\n\n| Key |Value|Description|\n|-----|-----|-----------|\n|DEBUG|`proxy:*`| Debug flag used for logging |\n|PORT|`3000`|Port used by web-app which displays the dummy device data |\n|IOTA_HTTP_HOST|`iot-agent`| The host name of the IoT Agent for UltraLight 2.0 - see below | \n|IOTA_HTTP_PORT|`7896` | The port that the IoT Agent for UltraLight 2.0 will be listening on. `7896` is a common default for UltraLight over HTTP |\n|DUMMY_DEVICES_PORT|`3001`|Port used by the dummy IoT devices to receive commands |\n|DUMMY_DEVICES_API_KEY|`4jggokgpepnvsb2uv4s40d59ov`| Random security key used for UltraLight interactions - used to ensure the integrity of interactions between the devices and the IoT Agent |\n\nThe other `context-provider` container configuration values described in the YAML file are not used in this tutorial.\n\n## IoT Agent for UltraLight 2.0 Configuration\n\nThe [IoT Agent for UltraLight 2.0](http://fiware-iotagent-ul.readthedocs.io/en/latest/) can be instantiated within a Docker container. An offical Docker image is available from [Docker Hub](https://hub.docker.com/r/fiware/iotagent-ul/) tagged `fiware/iotagent-ul`. The \nnecessary configuration can be seen below:\n\n```yaml\n iot-agent:\n image: fiware/iotagent-ul:latest\n hostname: iot-agent\n container_name: iot-agent\n depends_on:\n - context-db\n - orion\n networks:\n - default\n expose:\n - \"4041\"\n - \"7896\"\n ports:\n - \"4041:4041\"\n - \"7896:7896\"\n environment:\n - \"IOTA_CB_HOST=orion\"\n - \"IOTA_CB_PORT=1026\"\n - \"IOTA_NORTH_PORT=4041\"\n - \"IOTA_REGISTRY_TYPE=mongodb\"\n - \"IOTA_LOG_LEVEL=DEBUG\"\n - \"IOTA_TIMESTAMP=true\"\n - \"IOTA_MONGO_HOST=context-db\"\n - \"IOTA_MONGO_PORT=27017\"\n - \"IOTA_MONGO_DB=iotagentul\"\n - \"IOTA_HTTP_PORT=7896\"\n - \"IOTA_PROVIDER_URL=http://iot-agent:4041\"\n```\n\nThe `iot-agent` container relies on the precence of the Orion Context Broker and uses a MongoDB database to hold device information such as device URLs and Keys. The container is listening on two ports: \n\n* Port `7896` is exposed to receive Ultralight measurements over HTTP from the Dummy IoT devices\n* Port `4041` is exposed purely for tutorial access - so that cUrl or Postman can make provisioning commands\n without being part of the same network.\n\n\nThe `iot-agent` container is driven by environment variables as shown:\n\n| Key |Value|Description|\n|-----|-----|-----------|\n|IOTA_CB_HOST|`orion`| Hostname of the context broker to update context |\n|IOTA_CB_PORT|`1026`| Port that context broker listens on to update context |\n|IOTA_NORTH_PORT|`4041` | Port used for Configuring the IoT Agent and receiving context updates from the context broker |\n|IOTA_REGISTRY_TYPE|`mongodb`| Whether to hold IoT device info in memory or in a database |\n|IOTA_LOG_LEVEL|`DEBUG`|The log level of the IoT Agent |\n|IOTA_TIMESTAMP|`true`| Whether to supply timestamp information with each measurement received from attached devices |\n|IOTA_MONGO_HOST|`context-db`| The host name of mongoDB - used for holding device information |\n|IOTA_MONGO_PORT|`27017`| The port mongoDB is listening on |\n|IOTA_MONGO_DB|`iotagentul`| The name of the database used in mongoDB |\n|IOTA_HTTP_PORT|`7896`| The port where the IoT Agent listens for IoT device traffic over HTTP |\n|IOTA_PROVIDER_URL|`http://iot-agent:4041`| URL passed to the Context Broker when commands are registered, used as a forwarding URL location when the Context Broker issues a command to a device | ", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "513743", - "_collection_link": "https://fiware.postman.co/workspace/NGSI-v2-Tutorials~56ef8b2e-ab05-408c-bbe9-7714cfe08cf6/collection/513743-6b14053b-d153-4984-a955-6d4036dd3078?action=share&source=collection_link&creator=513743" - }, - "item": [ - { - "name": "Connecting IoT Devices", - "item": [ - { - "name": "IoT Agent - Obtain Version Information", - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/about", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "about" - ] - }, - "description": "Once the IoT Agent is running, You can check the status by making an HTTP request to the exposed port. \nIf the response is blank, this is usually because the MongoDB database holding the context information is not running or not connected.\n\n>**Troubleshooting:** What if the response is blank ?\n>\n> * To check that a docker container is running try\n>\n>```bash\n>docker ps\n>```\n>\n>You should see several containers running. If `iot-agent` is not running, you can restart the containers as necessary." - }, - "response": [] - }, - { - "name": "IoT Agent - Create a Service Group", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"services\": [\n {\n \"apikey\": \"4jggokgpepnvsb2uv4s40d59ov\",\n \"cbroker\": \"http://orion:1026\",\n \"entity_type\": \"Motion\",\n \"resource\": \"/iot/d\"\n }\n ]\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/services", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services" - ] - }, - "description": "Invoking group provision is always the the first step in connecting devices since it is always necessary to\nsupply an authentication key with each measurement and the IoT Agent will not initially know which URL \nthe context broker is responding on.\n\nIt is possible to set up default commands and attributes for all devices as well, but this\nis not done within this tutorial as we will be provisioning each device separately.\n\nThis example provisions an anonymous group of devices. It tells the IoT Agent that a series of devices\nwill be sending messages to the `IOTA_HTTP_PORT` (where the IoT Agent is listening for **Northbound** communications)\n\nIn the example the IoT Agent is informed that the `/iot/d` endpoint will be used and that devices will authenticate\nthemselves by including the token `4jggokgpepnvsb2uv4s40d59ov`. For an UltraLight IoT Agent this means devices will\nbe sending GET or POST requests to: \n\n```\nhttp://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov\n```\n\nWhich should be familiar UltraLight 2.0 syntax from the previous tutorial.\n\nWhen a measurement from an IoT device is received on the resource url it needs to be \ninterpreted and passed to the context broker. The `entity_type` attribute provides a\ndefault `type` for each device which has made a request (in this case anonymous devices\nwill be known as `Thing` entities. Furthermore the location of the\ncontext broker (`cbroker`) is needed, so that the IoT Agent can pass on any measurements \nreceived to the correct URL. `cbroker` is an optional attribute - if it is not provided, \nthe IoT Agent uses the context broker URL as defined in the configuration file, however\nit has been included here for completeness." - }, - "response": [] - }, - { - "name": "IoT Agent - Provision a Sensor", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"motion001\",\n \"entity_name\": \"urn:ngsi-ld:Motion:001\",\n \"entity_type\": \"Motion\",\n \"timezone\": \"Europe/Berlin\",\n \"attributes\": [\n { \"object_id\": \"c\", \"name\": \"count\", \"type\": \"Integer\" }\n ],\n \"static_attributes\": [\n { \"name\":\"refStore\", \"type\": \"Relationship\", \"value\": \"urn:ngsi-ld:Store:001\"}\n ]\n }\n ]\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "It is common good practice to use URNs following the NGSI-LD [draft recommendation](https://docbox.etsi.org/ISG/CIM/Open/ISG_CIM_NGSI-LD_API_Draft_for_public_review.pdf) when creating entities. Furthermore it is easier to understand\nmeaningful names when defining data attributes. These mappings can be defined by provisioning a device individually.\n\nThree types of meaasurement attributes can be provisioned:\n\n* `attributes` are active readings from the device\n* `lazy` attributes are only sent on request - The IoT Agent will inform the device to return the measurement\n* `static_attributes` are as the name suggests static data about the device (such as relationships) passed on \n to the context broker.\n\n>**Note**: in the case where individual `id`s are not required, or aggregated data is sufficient \n> the `attributes` can be defined within the provisioning service rather than individually.\n\nIn the request we are assiociating the device `motion001` with the URN `urn:ngsd-ld:Motion:001`\nand mapping the device reading `c` with the context attribute `count` (which is defined as an `Integer`)\nA `refStore` is defined as a `static_attribute`, placing the device within **Store** `urn:ngsi-ld:Store:001`" - }, - "response": [] - }, - { - "name": "Dummy Device - Measurement", - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "text/plain" - } - ], - "body": { - "mode": "raw", - "raw": "c|1" - }, - "url": { - "raw": "http://localhost:7896/iot/d?k=4jggokgpepnvsb2uv4s40d59ov&i=motion001", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "7896", - "path": [ - "iot", - "d" - ], - "query": [ - { - "key": "k", - "value": "4jggokgpepnvsb2uv4s40d59ov" - }, - { - "key": "i", - "value": "motion001" - } - ] - }, - "description": "This example simulates a request coming from the device `motion001`\n\nThe request to the previously provisioned resource `iot/d` is in UltraLight 2.0 format\nand identifies the device `motion001` and passes a known API key.\n\nA similar request was made in the previous tutorial (before the IoT Agent was connected)\nwhen the door was unlocked, you will have seen the state of each motion sensor changing\nand a Northbound request will be logged in the device monitor." - }, - "response": [] - }, - { - "name": "Context Broker - Read the Motion Sensor", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Motion:001", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Motion:001" - ] - }, - "description": "This example returns the data for the `Motion` entity with the `id=urn:ngsd-ld:Motion:001` within the context data.\n\nThe response shows that the device with `id=motion001` has been successfully identifed by the IoT Agent and mapped to the\nentity `id=urn:ngsd-ld:Motion:001`. This new entity has been created within the context data. The `c` \nattribute from the dummy device measurement request has been mapped to the more meaningful `count` attribute\nwithin the context. As you will notice, a `TimeInstant` attribute has been added to both the entity and the\nmeta data of the attribute - this represents the last time the entity and attribute have been updated, and is\nautomatically added to each new entity because the `IOTA_TIMESTAMP` environment variable was set when the\nIoT Agent was started up. The `refStore` attribute comes from the `static_attributes` set when the device was provisioned." - }, - "response": [] - }, - { - "name": "IoT Agent - Provision an Actuator", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"bell001\",\n \"entity_name\": \"urn:ngsi-ld:Bell:001\",\n \"entity_type\": \"Bell\",\n \"protocol\": \"PDI-IoTA-UltraLight\",\n \"transport\": \"HTTP\",\n \"endpoint\": \"http://context-provider:3001/iot/bell001\",\n \"commands\": [ \n {\n \"name\": \"ring\",\n \"type\": \"command\"\n }\n ],\n \"static_attributes\": [\n {\"name\":\"refStore\", \"type\": \"Relationship\",\"value\": \"urn:ngsi-ld:Store:001\"}\n \t]\n }\n ]\n}\n" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "Provisioning an actuator is similar to provisioning a sensor. This time an `endpoint` attribute holds\nthe location where the IoT Agent needs to send the UltraLight command and the `commands` array includes\na list of each command that can be invoked. The example below provisions a bell with the `deviceId=bell001`.\nThe endpoint is `http://context-provider:3001/iot/bell001` and it can accept the `ring` command." - }, - "response": [] - }, - { - "name": "IoT Agent - Provision a Bidrectional Attribute", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"bell002\",\n \"entity_name\": \"urn:ngsi-ld:Bell:002\",\n \"entity_type\": \"Bell\",\n \"protocol\": \"PDI-IoTA-UltraLight\",\n \"transport\": \"HTTP\",\n \"endpoint\": \"http://context-provider:3001/iot/bell002\",\n \"attributes\": [\n {\n \"name\": \"ring\",\n \"type\": \"Text\",\n \"expression\": \"ring\",\n \"reverse\": [\n {\n \"object_id\": \"ring\",\n \"type\": \"Text\",\n \"expression\": \"ring | toString()\"\n }\n ]\n }\n ],\n \"static_attributes\": [\n {\n \"name\": \"refStore\",\n \"type\": \"Relationship\",\n \"value\": \"urn:ngsi-ld:Store:002\"\n }\n ]\n }\n ]\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "An actuator can also be provisioned using a bidirectional attribute. Once again an `endpoint` attribute holds\nthe location where the IoT Agent needs to send the UltraLight command. The `ring` attribute is defined using an `expression` and mapped to itself in the `reverse` direction. When un update to the `ring` attribute is received, it is also send to the device itself." - }, - "response": [] - }, - { - "name": "IoT Agent - Invoke a Command", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"actionType\": \"update\",\n \"entities\": [\n {\n \"type\": \"Bell\",\n \"id\": \"urn:ngsi-ld:Bell:001\",\n \"ring\" : {\n \"type\": \"command\",\n \"value\": \"\"\n }\n }\n ]\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/v2/op/update", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "v2", - "op", - "update" - ] - }, - "description": "Before we wire-up the context broker, we can test that a command can be send to a device by making a REST request \ndirectly to the IoT Agent's North Port using the `/v1/updateContext` endpoint.\nIt is this endpoint that will eventually be invoked by the context broker once we have connected it up. \nTo test the configuration you can run the command directly as shown.\n\nIf you are viewing the device monitor page, you can also see the state of the bell change.\n\n![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif)" - }, - "response": [] - }, - { - "name": "Context Broker - Read the Command Result", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Bell:001?options=keyValues", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Bell:001" - ], - "query": [ - { - "key": "options", - "value": "keyValues" - } - ] - }, - "description": "The result of the command to ring the bell can be read by querying the entity within the Orion Context Broker. \n\nThe `TimeInstant` shows last the time any command associated with the entity has been invoked. the result of `ring` command can be see in the value of the `ring_info` attribute" - }, - "response": [] - }, - { - "name": "IoT Agent - Provision a Smart Door", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"door001\",\n \"entity_name\": \"urn:ngsi-ld:Door:001\",\n \"entity_type\": \"Door\",\n \"protocol\": \"PDI-IoTA-UltraLight\",\n \"transport\": \"HTTP\",\n \"endpoint\": \"http://context-provider:3001/iot/door001\",\n \"commands\": [ \n {\"name\": \"unlock\",\"type\": \"command\"},\n {\"name\": \"open\",\"type\": \"command\"},\n {\"name\": \"close\",\"type\": \"command\"},\n {\"name\": \"lock\",\"type\": \"command\"}\n ],\n \"attributes\": [\n \t{\"object_id\": \"s\", \"name\": \"state\", \"type\":\"Text\"}\n ],\n \"static_attributes\": [\n {\"name\":\"refStore\", \"type\": \"Relationship\",\"value\": \"urn:ngsi-ld:Store:001\"}\n ]\n }\n ]\n}\n" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "Provisioning a device which offers both commands and measurements is merely a matter of making an HTTP POST request\nwith both `attributes` and `command` attributes in the body of the request.\n\nThis example provisions a smart door with four commands `lock`, `unlock`, `open` and `close` and maps a single attribute." - }, - "response": [] - }, - { - "name": "IoT Agent - Provision a Smart Lamp", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"lamp001\",\n \"entity_name\": \"urn:ngsi-ld:Lamp:001\",\n \"entity_type\": \"Lamp\",\n \"protocol\": \"PDI-IoTA-UltraLight\",\n \"transport\": \"HTTP\",\n \"endpoint\": \"http://context-provider:3001/iot/lamp001\",\n \"commands\": [ \n {\"name\": \"on\",\"type\": \"command\"},\n {\"name\": \"off\",\"type\": \"command\"}\n ],\n \"attributes\": [\n \t{\"object_id\": \"s\", \"name\": \"state\", \"type\":\"Text\"},\n {\"object_id\": \"l\", \"name\": \"luminosity\", \"type\":\"Integer\"}\n ],\n \"static_attributes\": [\n {\"name\":\"refStore\", \"type\": \"Relationship\",\"value\": \"urn:ngsi-ld:Store:001\"}\n \t]\n }\n ]\n}\n" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "Provisioning a device which offers both commands and measurements is merely a matter of making an HTTP POST request\nwith both `attributes` and `command` attributes in the body of the request.\n\nThis example provisions a smart door with two commands `on` and `off` and maps two attributes." - }, - "response": [] - }, - { - "name": "IoT Agent - List all Provisioned Devices", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "This example lists all provisioned devices by making a GET request to the `/iot/devices` endpoint.\n\nThe response includes all the commands and attributes mappings associated with all provisioned IoT devices." - }, - "response": [] - } - ], - "description": "The IoT Agent acts as a middleware between the IoT devices and the context broker. It therefore\nneeds to be able to create context data entities with unique ids. Once a service has been provisioned\nand an unknown device makes a measurement the IoT Agent add this to the context using the supplied\n`` (unless the device is recognized and can be mapped to a known id.\n\nThere is no guarantee that every supplied IoT device `` will always be unique, therefore \nall provisioning requests to the IoT Agent require two mandatory headers:\n\n* `fiware-service` header is defined so that entities for a given service can be held in a separate mongoDB database.\n* `fiware-servicepath` can be used to differenciate between arrays of devices. \n\nFor example within a smart city application you would expect different `fiware-service` headers for different\ndepartments (e.g. parks, transport, refuse collection etc.) and each `fiware-servicepath` would refer to specific park \nand so on. This would mean that data and devices for each service can be identified and separated as needed, but the\ndata would not be siloed - for example data from a **Smart Bin** within a park can be combined with the **GPS Unit** \nof a refuse truck to alter the route of the truck in an efficient manner. \n\nThe **Smart Bin** and **GPS Unit** are likely to come from different manufacturers and it cannot be \nguaranteed that that there is no overlap within ``s used. The use of the `fiware-service` and\n`fiware-servicepath` headers can ensure that this is always the case, and allows the context broker to identify\nthe original source of the context data.\n", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Enabling Context Broker Commands", - "item": [ - { - "name": "Bell Commands", - "item": [ - { - "name": "Create Bell", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"id\": \"urn:ngsi-ld:Bell:001\",\n \"type\": \"Bell\"\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities" - ] - }, - "description": "To invoke the `open` command, the `open` attribute must be updated in the context." - }, - "response": [] - }, - { - "name": "Ring Bell", - "request": { - "method": "PATCH", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"ring\": {\n \"type\" : \"command\",\n \"value\" : \"\"\n }\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Bell:001/attrs?type=Bell", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Bell:001", - "attrs" - ], - "query": [ - { - "key": "type", - "value": "Bell" - } - ] - }, - "description": "To invoke the `ring` command, the `ring` attribute must be updated in the context.\n\nIf you are viewing the device monitor page, you can also see the state of the bell change.\n\n![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif)" - }, - "response": [] - }, - { - "name": "Bell Status", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\t\"ring\": {\n \t\"type\" : \"command\",\n \t\"value\" : \"\"\n\t}\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Bell:001?options=keyValues", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Bell:001" - ], - "query": [ - { - "key": "options", - "value": "keyValues" - } - ] - }, - "description": "The result of the command to ring the bell can be read by querying the entity within the Orion Context Broker. \n\nThe `TimeInstant` shows last the time any command associated with the entity has been invoked. the result of `ring` command can be see in the value of the `ring_info` attribute" - }, - "response": [] - } - ], - "description": "The **Bell** entity has been mapped to `id=\"urn:ngsi-ld:Bell:001\"` with an entity `type=\"Bell\"`", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Smart Door Commands", - "item": [ - { - "name": "Create Door", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"id\": \"urn:ngsi-ld:Door:001\",\n \"type\": \"Door\"\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities" - ] - }, - "description": "To invoke the `open` command, the `open` attribute must be updated in the context." - }, - "response": [] - }, - { - "name": "Open a Door", - "request": { - "method": "PATCH", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"open\": {\n \"type\" : \"command\",\n \"value\" : \"\"\n }\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Door:001/attrs?type=Door", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Door:001", - "attrs" - ], - "query": [ - { - "key": "type", - "value": "Door" - } - ] - }, - "description": "To invoke the `open` command, the `open` attribute must be updated in the context." - }, - "response": [] - }, - { - "name": "Door Status", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Door:001?options=keyValues", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Door:001" - ], - "query": [ - { - "key": "options", - "value": "keyValues" - } - ] - }, - "description": "The result of the invocation of **Smart Door** commands can be read by querying the entity within the Orion Context Broker. \n\nThe `TimeInstant` shows last the time any command associated with the entity has been invoked. \n\n* The result of `open` command can be see in the value of the `open_info` attribute\n* The result of `close` command can be see in the value of the `close_info` attribute\n* The result of `lock` command can be see in the value of the `lock_info` attribute\n* The result of `unlock` command can be see in the value of the `unlock_info` attribute" - }, - "response": [] - } - ], - "description": "The **Smart Door** entity has been mapped to `id=\"urn:ngsi-ld:Door:001\"` with an entity `type=\"Door\"`", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Smart Lamp", - "item": [ - { - "name": "Create Lamp", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"id\": \"urn:ngsi-ld:Lamp:001\",\n \"type\": \"Lamp\"\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities" - ] - }, - "description": "To invoke the `open` command, the `open` attribute must be updated in the context." - }, - "response": [] - }, - { - "name": "Switch On a Lamp", - "request": { - "method": "PATCH", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"on\": {\n \"type\" : \"command\",\n \"value\" : \"\"\n }\n}" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Lamp:001/attrs?type=Lamp", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Lamp:001", - "attrs" - ], - "query": [ - { - "key": "type", - "value": "Lamp" - } - ] - }, - "description": "To switch on the **Smart Lamp**, the `on` attribute must be updated in the context." - }, - "response": [] - }, - { - "name": "Lamp Status", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/urn:ngsi-ld:Lamp:001?options=keyValues", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "urn:ngsi-ld:Lamp:001" - ], - "query": [ - { - "key": "options", - "value": "keyValues" - } - ] - }, - "description": "The result of the invocation of **Smart Lamp** commands can be read by querying the entity within the Orion Context Broker. \n\nThe `TimeInstant` shows last the time any command associated with the entity has been invoked. \n\n* The result of `on` command can be see in the value of the `on_info` attribute\n* The result of `off` command can be see in the value of the `off_info` attribute" - }, - "response": [] - } - ], - "description": "The **Smart Lamp** entity has been mapped to `id=\"urn:ngsi-ld:Lamp:001\"` with an entity `type=\"Lamp\"`", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "List Provisioned Devices", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{orion}}/v2/entities/", - "protocol": "http", - "host": [ - "{{orion}}" - ], - "path": [ - "v2", - "entities", - "" - ] - }, - "description": "This example returns the data of all `Store` entities within the context data" - }, - "response": [] - } - ], - "description": "Having connected up the IoT Agent to the IoT devices, the Orion Context Broker was informed that the commands are\nnow available. In other words the IoT Agent registered itself as a\n[Context Provider](https://github.com/FIWARE/tutorials.Context-Providers/) for the command attributes.\n\nOnce the commands have been registered it will be possible to ring the **Bell**, open and close the **Smart Door** and\nswitch the **Smart Lamp** on and off by sending requests to the Orion Context Broker, rather than sending UltraLight 2.0\nrequests directly t the IoT devices as we did in the [previous tutorial](https://github.com/Fiware/tutorials.IoT-Sensors)", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Service Group CRUD Actions", - "item": [ - { - "name": "Create a Service Group", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"services\": [\n {\n \"apikey\": \"4jggokgpepnvsb2uv4s40d59ov\",\n \"cbroker\": \"http://orion:1026\",\n \"entity_type\": \"Thing\",\n \"resource\": \"/iot/d\"\n }\n ]\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/services", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services" - ] - }, - "description": "This example provisions an anonymous group of devices. It tells the IoT Agent that a series of devices\nwill be sending messages to the `IOTA_HTTP_PORT` (where the IoT Agent is listening for **Northbound** communications)\n\nIn the example the IoT Agent is informed that the `/iot/d` endpoint will be used and that devices will authenticate\nthemselves by including the token `4jggokgpepnvsb2uv4s40d59ov`." - }, - "response": [] - }, - { - "name": "Read Service Group details", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/x-www-form-urlencoded", - "type": "text" - } - ], - "url": { - "raw": "http://{{iot-agent}}/iot/services?resource=/iot/d", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services" - ], - "query": [ - { - "key": "resource", - "value": "/iot/d" - } - ] - }, - "description": "This example obtains the full details of a provisioned services with a given `resource` path.\n\nThe response includes all the defaults associated with the service group such as the `entity_type` and any default commands or attribute mappings.\n\nService group details can be read by making a GET request to the `/iot/services` endpoint and providing a `resource` parameter." - }, - "response": [] - }, - { - "name": "List all Service Groups", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/services", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services" - ] - }, - "description": "This example lists all provisioned services by making a GET request to the `/iot/services/` endpoint.\n\nThe response includes all the defaults associated with each service group such as the `entity_type` and any default commands or attribute mappings." - }, - "response": [] - }, - { - "name": "Update a Service Group", - "request": { - "method": "PUT", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"entity_type\": \"IoT-Device\"\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/services?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services" - ], - "query": [ - { - "key": "resource", - "value": "/iot/d" - }, - { - "key": "apikey", - "value": "4jggokgpepnvsb2uv4s40d59ov" - } - ] - }, - "description": "This example updates an existing service group with a given `resource` path and `apikey`\n\nService group details can be updated by making a PUT request to the `/iot/services` endpoint \nand providing a `resource` and `apikey` parameters." - }, - "response": [] - }, - { - "name": "Delete a Service Group", - "request": { - "method": "DELETE", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/services/?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "services", - "" - ], - "query": [ - { - "key": "resource", - "value": "/iot/d", - "description": "The path that the IoT Agent had been listening on" - }, - { - "key": "apikey", - "value": "4jggokgpepnvsb2uv4s40d59ov" - } - ] - }, - "description": "This example removes a provisioned service group by making a DELETE request to the `/iot/services/` endpoint.\n\nIt means that requests to `http://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov`\n(where the IoT Agent is listening for **Northbound** communications) should no longer be processed by the IoT Agent. \nThe `apiKey` and `resource` parameters must be supplied in order to identify the service group to be deleted." - }, - "response": [] - } - ], - "description": "The **CRUD** operations for a service group map on to the expected HTTP verbs under the `/iot/services` endpoint\n\n* **Create** - HTTP POST\n* **Read** - HTTP GET\n* **Update** - HTTP PUT\n* **Delete** - HTTP DELETE\n\nUse the `resource` and `apikey` parameters to uniquely identify a service group.", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Device CRUD Actions", - "item": [ - { - "name": "Create a Provisioned Device", - "request": { - "method": "POST", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"devices\": [\n {\n \"device_id\": \"bell002\",\n \"entity_name\": \"urn:ngsi-ld:Bell:002\",\n \"entity_type\": \"Bell\",\n \"protocol\": \"PDI-IoTA-UltraLight\",\n \"transport\": \"HTTP\",\n \"endpoint\": \"http://context-provider:3001/iot/bell002\",\n \"commands\": [ \n {\n \"name\": \"ring\",\n \"type\": \"command\"\n }\n ],\n \"static_attributes\": [\n {\"name\":\"refStore\", \"type\": \"Relationship\",\"value\": \"urn:ngsi-ld:Store:002\"}\n \t]\n }\n ]\n}\n" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "This example provisions an individual device. It maps the `device_id=bell002` to the entity URN `urn:ngsi-ld:Bell:002` and gives the\nentity a type `Bell`. The IoT Agent has been informed that the device offers a single `ring` `command` and is listening on \n`http://context-provider:3001/iot/bell002` using HTTP. `attributes`, `lazy` attributes and `static_attributes` can also be provisioned." - }, - "response": [] - }, - { - "name": "Read Provisioned Device Details", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices/bell002", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices", - "bell002" - ] - }, - "description": "This example obtains the full details of a provisioned device with a given `` path.\n\nThe response includes all the commands and attributes mappings associated with the device\n\nProvisioned Device details can be read by making a GET request to the `/iot/devices/` endpoint." - }, - "response": [] - }, - { - "name": "List all Provisioned Devices", - "request": { - "method": "GET", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices" - ] - }, - "description": "This example lists all provisioned devices by making a GET request to the `/iot/devices` endpoint.\n\nThe response includes all the commands and attributes mappings associated with all devices" - }, - "response": [] - }, - { - "name": "Update a Provisioned Device", - "request": { - "method": "PUT", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"entity_name\": \"urn:ngsi-ld:Thing:bell002\"\n}" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices/bell002", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices", - "bell002" - ] - }, - "description": "This example updates an existing provisioned device by making a PUT request to the `/iot/devices/` endpoint." - }, - "response": [] - }, - { - "name": "Delete a Provisioned Device", - "request": { - "method": "DELETE", - "header": [ - { - "key": "fiware-service", - "value": "openiot" - }, - { - "key": "fiware-servicepath", - "value": "/" - } - ], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://{{iot-agent}}/iot/devices/bell002", - "protocol": "http", - "host": [ - "{{iot-agent}}" - ], - "path": [ - "iot", - "devices", - "bell002" - ] - }, - "description": "This example removes a provisioned device by making a DELETE request to the `/iot/services/` endpoint.\n\nThe device attributes will no longer be mapped and commands can no longer be sent to the device.\nIf the device is making active measurements, they will still be handled with default values\nif the associated service has not been deleted." - }, - "response": [] - } - ], - "description": "The **CRUD** operations for an individual device map on to the expected HTTP verbs under the `/iot/devices` endpoint\n\n* **Create** - HTTP POST\n* **Read** - HTTP GET\n* **Update** - HTTP PUT\n* **Delete** - HTTP DELETE\n\nUse the `` to uniquely identify a device.", - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ], - "variable": [ - { - "key": "iot-agent", - "value": "localhost:4041" - }, - { - "key": "orion", - "value": "localhost:1026" - }, - { - "key": "ultralight", - "value": "localhost:3001" - } - ] -} \ No newline at end of file diff --git a/README.ja.md b/README.ja.md deleted file mode 100644 index 6fa23c8..0000000 --- a/README.ja.md +++ /dev/null @@ -1,1496 +0,0 @@ -[![FIWARE Banner](https://fiware.github.io/tutorials.IoT-Agent/img/fiware.png)](https://www.fiware.org/developers) -[![NGSI v2](https://img.shields.io/badge/NGSI-v2-5dc0cf.svg)](https://fiware-ges.github.io/orion/api/v2/stable/) - -[![FIWARE IoT Agents](https://nexus.lab.fiware.org/repository/raw/public/badges/chapters/iot-agents.svg)](https://github.com/FIWARE/catalogue/blob/master/iot-agents/README.md) -[![License: MIT](https://img.shields.io/github/license/fiware/tutorials.Iot-Agent.svg)](https://opensource.org/licenses/MIT) -[![Support badge](https://img.shields.io/badge/tag-fiware-orange.svg?logo=stackoverflow)](https://stackoverflow.com/questions/tagged/fiware) -[![UltraLight 2.0](https://img.shields.io/badge/Payload-Ultralight-27ae60.svg)](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) -
[![Documentation](https://img.shields.io/readthedocs/fiware-tutorials.svg)](https://fiware-tutorials.rtfd.io) - - - -このチュートリアルでは、**IoT Agent** の概念を紹介し -、[以前のチュートリアル](https://github.com/FIWARE/tutorials.Context-Providers/)で -作成したダミーの -[UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) -IoT デバイスを接続し -、[Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) に送信 -された [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) リクエスト -を使用して測定値を読み取り、コマンドを送信できるようにします。 - -このチュートリアルでは、全体で [cUrl](https://ec.haxx.se/) コマンドを使用してい -ますが、[Postman documentation](https://fiware.github.io/tutorials.IoT-Agent/) -も利用できます。 - -[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/2150531e68299d46f937) -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/FIWARE/tutorials.IoT-Agent/tree/NGSI-v2) - -## 内容 - -
-詳細 (クリックして拡大) - -- [IoT Agent とは何ですか?](#what-is-an-iot-agent) - - [サウス・バウンドのトラフィック (コマンド)](#southbound-traffic-commands) - - [ノース・バウンドのトラフィック (測定)](#northbound-traffic-measurements) - - [共通の機能](#common-functionality) -- [アーキテクチャ](#architecture) - - [ダミー IoT デバイスの設定](#dummy-iot-devices-configuration) - - [IoT Agent for UltraLight 2.0 の設定](#iot-agent-for-ultralight-20-configuration) -- [前提条件](#prerequisites) - - [Docker と Docker Compose](#docker-and-docker-compose) - - [Cygwin for Windows](#cygwin-for-windows) -- [起動](#start-up) -- [IoT Agent のプロビジョニング](#provisioning-an-iot-agent) - - [IoT Agent サービスの正常性の確認](#checking-the-iot-agent-service-health) - - [IoT デバイスの接続](#connecting-iot-devices) - - [サービス・グループのプロビジョニング](#provisioning-a-service-group) - - [センサのプロビジョニング](#provisioning-a-sensor) - - [コマンドを介したアクチュエータのプロビジョニング](#provisioning-an-actuator-via-a-command) - - [双方向属性を介したアクチュエータのプロビジョニング](#provisioning-an-actuator-via-a-bidirectional-attribute) - - [スマート・ドアのプロビジョニング](#provisioning-a-smart-door) - - [スマート・ランプのプロビジョニング](#provisioning-a-smart-lamp) - - [Context Broker コマンド の有効化](#enabling-context-broker-commands) - - [ベルを鳴らす](#ringing-the-bell) - - [スマート・ドアを開く](#opening-the-smart-door) - - [スマート・ランプをオンにする](#switching-on-the-smart-lamp) -- [サービス・グループの CRUD アクション](#service-group-crud-actions) - - [サービス・グループの作成](#creating-a-service-group) - - [サービス・グループの詳細を読み込む](#read-service-group-details) - - [すべてのサービス・グループを一覧表示](#list-all-service-groups) - - [サービス・グループを更新](#update-a-service-group) - - [サービス・グループを削除](#delete-a-service-group) -- [デバイスの CRUD アクション](#device-crud-actions) - - [プロビジョニングされたデバイスの作成](#creating-a-provisioned-device) - - [プロビジョニングされたデバイスの詳細を読み込む](#read-provisioned-device-details) - - [プロビジョニングされたすべてのデバイスを一覧表示](#list-all-provisioned-devices) - - [プロビジョニングされたデバイスを更新](#update-a-provisioned-device) - - [プロビジョニングされたデバイスを削除](#delete-a-provisioned-device) -- [次のステップ](#next-steps) - -
- - - -# IoT Agent とは何ですか? - -> "In every operation there is an above the line and a below the line. Above the -> line is what you do by the book. Below the line is how you do the job." -> -> — John le Carré (A Perfect Spy) - -IoT Agent は、デバイスのグループが独自のネイティブ・プロトコルを使用して Context -Broker にデータを送信し、Context Broker から管理できるようにするコンポーネントで -す。また、IoT Agent は、FIWARE プラットフォームのセキュリティ面(チャネルの認証と -認可)に対処し、他の共通サービスをデバイスのプログラマに提供できる必要があります -。 - -Orion Context Broker は、すべての相互作用に対して排他的に -[NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) リクエストを使用 -します。各 IoT Agent は、 Context Broker の対話に使用される**ノース・ポート** -[NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) インターフェイス -を提供し、このポートの下にあるすべての対話は、接続されたデバイスの**ネイティブ・ -プロトコル**を使用して行われます。 - -実際には、コンテキスト情報管理レベルでのすべての IoT インタラクションに対する標 -準インタフェースを提供します。IoT デバイスの各グループは、独自の専有プロトコルと -さまざまなトランスポート・メカニズムを内部で使用できますが、関連する IoT Agent -はこの複雑さを処理する Facade パターンを提供します。 - -IoT Agent はすでに存在しているか、多くの IoT コミュニケーション・プロトコルとデ -ータモデルのために開発中です。例には次のものがあります : - -- [IoTAgent-JSON](https://fiware-iotagent-json.readthedocs.io/en/latest/) - - JSON ペイロードを持つ HTTP/MQTT メッセージング と NGSI のブリッジ -- [IoTAgent-LWM2M](https://fiware-iotagent-lwm2m.readthedocs.io/en/latest) - - [Lightweight M2M](https://www.omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/) - プロトコル と NGSI のブリッジ -- [IoTAgent-UL](https://fiware-iotagent-ul.readthedocs.io/en/latest) - - UltraLight2.0 ペイロード を持つ HTTP/MQTT メッセージング と NGSI のブリッジ -- [IoTagent-LoRaWAN](https://fiware-lorawan.readthedocs.io/en/latest) - - [LoRaWAN](https://www.thethingsnetwork.org/docs/lorawan/) プロトコルと NGSI - のブリッジ - - - -## サウス・バウンドのトラフィック (コマンド) - -Context Broker から生成され、IoT Agent を介して、IoT デバイスに向けて下向きに渡 -された HTTP リクエストは、サウス・バウンド・トラフィックと呼ばれます。サウス・バ -ウンドのトラフィックは、実際の動作の状態を動作によって変更するアクチュエータ・デ -バイスに対する**コマンド**で構成されています。 - -たとえば、実際の Ultra Light 2.0 **スマート・ランプ**をオンに切り替えるには、次 -のようなやりとりが発生します : - -1. **Context Broker** に NGSI PATCH リクエストが送信され、**スマート・ラン - プ**の現在のコンテキストが更新されます - -- これは事実上、**スマート・ランプ**の `on` コマンドを呼び出す間接的な要求です - -2. **Context Broker** は、コンテキスト内でエンティティを見つけ、この属性のコン - テキスト・プロビジョニングは **IoT Agnet** に委任されていることに注意します -3. **Context Broker** は、**IoT Agnet** のノース・ポートに NGSI リクエストを送 - 信して、コマンドを呼び出します -4. **IoT Agnet** は、このサウス・バウンドのリクエストを受信し、UltraLight 2.0 - の構文に変換し、それを**スマート・ランプ** に渡します -5. **スマート・ランプ**はランプを点灯し、UltraLight 2.0 の構文で **IoT Agnet** - にコマンドの結果を返します -6. **IoT Agnet** はこのノース・バウンドのリクエストを受け取り、それを解釈し - 、**Context Broker** に NGSI リクエストを行うことによって、インタラクション - の結果をコンテキストに渡します -7. **Context Broker** は、このノース・バウンドのリクエストを受信して、コマンド - の結果でコンテキストを更新します - -![](https://fiware.github.io/tutorials.IoT-Agent/img/command-swimlane.png) - -- **ユーザ** と **Context Broker** との間のリクエストは NGSI を使用します -- **Context Broker** と **IoT Agent** の間のリクエストは NGSI を使用します -- **IoT Agent** と **IoT デバイス**間のリクエストは、ネイティブ・プロトコルを - 使用します -- **IoT デバイス** と **IoT Agent** の間のリクエストは、ネイティブ・プロトコル - を使用します -- **IoT Agent** と **Context Broker** 間のリクエストは NGSI を使用します - - - -## ノース・バウンドのトラフィック (測定) - -IoT デバイスから生成され、IoT Agent を介して、Context Broker に向けて上向きに戻 -されたリクエストは、ノース・バウンドのトラフィックと呼ばれます。ノース・バウンド -のトラフィックは、センサ・デバイスによって行われた**測定**からなり、現実世界の状 -態をシステムのコンテキスト・データに中継します。 - -たとえば、実際の**モーション・センサ**がカウント測定値を送信するために、次のよう -なやり取りが行われます : - -1. **モーション・センサ**は測定を行い、その結果を **IoT Agent** に渡します -2. **IoT Agent** は、このノース・バウンドのリクエストを受け取り、その結果を - Ultra Light2.0 の構文から変換し、**Context Broker** に対して NGSI リクエスト - を行うことで、インタラクションの結果をコンテキストに渡します -3. **Context Broker** は、このノース・バウンドのリクエストを受信し、測定結果で - コンテキストを更新します - -![](https://fiware.github.io/tutorials.IoT-Agent/img/measurement-swimlane.png) - -- **IoT デバイス** と **IoT Agent** 間のリクエストはネイティブ・プロトコルを使 - 用します -- **IoT Agent** と **Context Broker** 間のリクエストは NGSI を使用します - -> **注** さらに複雑なやり取りも可能ですが、この概要は IoT Agent の基本原則を理解 -> するのに十分です - - - -## 共通の機能 - -前のセクションから分かるように、各 IoT Agent はさまざまなプロトコルを解釈するの -でユニークになりますが、IoT Agent 間にはかなりの類似性があります。 - -- デバイスのアップデートをリッスンする標準的な場所を提供 -- コンテキスト・データの更新をリッスンするための標準的な場所を提供 -- デバイスのリストを保持し、コンテキスト・データ属性をデバイス構文にマッピング -- セキュリティ認証 - -この基本機能は、一般的な -[IoT Agent framework library](https://iotagent-node-lib.readthedocs.io/) に抽象 -化されています。 - -#### デバイス・モニタ - -このチュートリアルの目的のために、一連のダミーの IoT デバイスを作成し、Context -Broker に接続します。使用するアーキテクチャとプロトコルの詳細については -、[IoT Sensors tutorial](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2) を参照 -してください。各デバイスの状態は、次の UltraLight2.0 デバイスのモニタ Web ページ -で確認できます : `http://localhost:3000/device/monitor` - -![FIWARE Monitor](https://fiware.github.io/tutorials.IoT-Agent/img/device-monitor.png) - - - -# アーキテクチャ - -このアプリケーションは -、[Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) と -[IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/) -の 2 つの FIWARE コンポーネントを使用します。アプリケーションが _“Powered by -FIWARE”_ と認定されるには、Orion Context Broker を使用するだけで十分です。Orion -Context Broker と IoT Agent はオープンソースの MongoDB 技術を利用して、保持して -いる情報の永続性を保ちます -。[以前のチュートリアル](https://github.com/FIWARE/tutorials.Context-Providers/)で -作成したダミーの IoT デバイスも使用します。 - -したがって、全体的なアーキテクチャは次の要素で構成されます : - -- [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) を使用してリ - クエストを受信する、FIWARE - [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) -- [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) を使用してサ - ウス・バウンドのリクエストを受信し、デバイスの - [UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) - コマンドに変換する、FIWARE - [IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/) -- 基礎となる [MongoDB](https://www.mongodb.com/) データベース : - - **Orion Context Broker** が、データ・エンティティ、サブスクリプション、 - レジストレーションなどのコンテキスト・データの情報を保持するために使用し - ます - - **IoT Agent** が、デバイスの URL やキーなどのデバイス情報を保持するため - に使用します -- コンテキスト・プロバイダの NGSI proxy は次のようになります : - - [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) を使用し - てリクエストを受信します - - 独自の APIs を独自フォーマットで使用して、公開されているデータソースへの - リクエストを行います - - [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) 形式でコ - ンテキスト・データを Orion Context Broker に返します -- 在庫管理フロントエンドは以下を行います : - - 店舗情報を表示します - - 各店舗で購入できる商品を表示します - - ユーザが製品を購入して在庫数を減らすことを許可します -- HTTP 上で動作する - [UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) - プロトコルを使用して、ダミーの IoT デバイスのセットとして機能する Web サーバ - -要素間のすべての対話は HTTP リクエストによって開始されるため、エンティティはコン -テナ化され、公開されたポートから実行されます。 - -![](https://fiware.github.io/tutorials.IoT-Agent/img/architecture.png) - -IoT デバイス と IoT Agent を接続するために必要な構成情報は、関連する -`docker-compose.yml` ファイルの services セクションにあります : - - - -## ダミー IoT デバイスの設定 - -```yaml -tutorial: - image: quay.io/fiware/tutorials.context-provider - hostname: iot-sensors - container_name: fiware-tutorial - networks: - - default - expose: - - "3000" - - "3001" - ports: - - "3000:3000" - - "3001:3001" - environment: - - "DEBUG=tutorial:*" - - "PORT=3000" - - "IOTA_HTTP_HOST=iot-agent" - - "IOTA_HTTP_PORT=7896" - - "DUMMY_DEVICES_PORT=3001" - - "DUMMY_DEVICES_API_KEY=4jggokgpepnvsb2uv4s40d59ov" - - "DUMMY_DEVICES_TRANSPORT=HTTP" -``` - -`tutorial` コンテナは、2 つのポートでリッスンしています: - -- ポート`3000` が公開されているので、ダミー IoT デバイスを表示する Web ページ - が表示されます -- ポート`3001` は純粋にチュートリアルのアクセスのために公開されているため - 、cUrl または Postman は同じネットワーク以外からも、UltraLight コマンドを作 - 成できます - -`tutorial` コンテナは、次のように環境変数によって設定値を指定できます : - -| キー | 値 | 説明 | -| ----------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| DEBUG | `tutorial:*` | ロギングに使用するデバッグ・フラグ | -| WEB_APP_PORT | `3000` | ダミー・デバイスのデータを表示する web-app が使用するポート | -| IOTA_HTTP_HOST | `iot-agent` | Ultra Light 2.0 用 IoT Agent のホスト名 - 下記を参照 | -| IOTA_HTTP_PORT | `7896` | Ultra Light 2.0 の IoT Agent がリッスンするポート。`7896` は、Ultra Light over HTTP の一般的なデフォルトです | -| DUMMY_DEVICES_PORT | `3001` | コマンドを受信するためにダミー IoT デバイスが使用するポート | -| DUMMY_DEVICES_API_KEY | `4jggokgpepnvsb2uv4s40d59ov` | UltraLight インタラクションに使用されるランダムなセキュリティキー - デバイスと IoT Agent 間のインタラクションの完全性を保証するために使用します | -| DUMMY_DEVICES_TRANSPORT | `HTTP` | ダミー IoT デバイスによって使用されるトランスポート・プロトコル | - -このチュートリアルでは、YAML ファイルで説明されている他の `tutorial` コンテナの -設定値は使用しません。 - - - -## IoT Agent for UltraLight 2.0 の設定 - -[IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/) -は 、Docker コンテナ内でインスタンス化できます。公式の Docker イメージは -、[Docker Hub](https://hub.docker.com/r/fiware/iotagent-ul/) で -、`fiware/iotagent-ul` とタグ付けされています。必要な構成を以下に示します: - -```yaml -iot-agent: - image: quay.io/fiware/iotagent-ul:latest - hostname: iot-agent - container_name: fiware-iot-agent - depends_on: - - mongo-db - networks: - - default - expose: - - "4041" - - "7896" - ports: - - "4041:4041" - - "7896:7896" - environment: - - IOTA_CB_HOST=orion - - IOTA_CB_PORT=1026 - - IOTA_NORTH_PORT=4041 - - IOTA_REGISTRY_TYPE=mongodb - - IOTA_LOG_LEVEL=DEBUG - - IOTA_TIMESTAMP=true - - IOTA_CB_NGSI_VERSION=v2 - - IOTA_AUTOCAST=true - - IOTA_MONGO_HOST=mongo-db - - IOTA_MONGO_PORT=27017 - - IOTA_MONGO_DB=iotagentul - - IOTA_HTTP_PORT=7896 - - IOTA_PROVIDER_URL=http://iot-agent:4041 -``` - -`iot-agent` コンテナは、Orion Context Broker に依存し、MongoDB データベースを使 -用して、デバイスの URL やキーなどのデバイス情報を保持します。コンテナが 2 つのポ -ートをリッスンしています: - -- ポート `7896` は、ダミー IoT デバイスから HTTP 経由で Ultralight の測定値を - 受けるために公開されています -- ポート `4041` は、チュートリアルのアクセスのためだけに公開されているため - 、cUrl または Postman は同じネットワーク以外からも、UltraLight コマンドを作 - 成できます - -`iot-agent` コンテナは、次のように環境変数によって設定値を指定できます : - -| キー | 値 | 説明 | -| -------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| IOTA_CB_HOST | `orion` | コンテキストを更新する Context Broker のホスト名 | -| IOTA_CB_PORT | `1026` | Context Broker がコンテキストを更新するためにリッスンするポート | -| IOTA_NORTH_PORT | `4041` | IoT Agent の設定および Context Broker からのコンテキスト更新の受信に使用されるポート | -| IOTA_REGISTRY_TYPE | `mongodb` | メモリまたはデータベースに IoT デバイス情報を保持するかどうかを指定 | -| IOTA_LOG_LEVEL | `DEBUG` | IoT Agent のログレベル | -| IOTA_TIMESTAMP | `true` | 接続されたデバイスから受信した各測定値にタイムスタンプ情報を提供するかどうかを指定 | -| IOTA_CB_NGSI_VERSION | `v2` | アクティブな属性の更新を送信するときにNGSI v2 を使用するように指定するかどうか | -| IOTA_AUTOCAST | `true` | Ultralight の数値が文字列ではなく数値として読み取られるようにする | -| IOTA_MONGO_HOST | `context-db` | mongoDB のホスト名 - デバイス情報を保持するために使用 | -| IOTA_MONGO_PORT | `27017` | mongoDB はリッスンしているポート | -| IOTA_MONGO_DB | `iotagentul` | mongoDB で使用されるデータベースの名前 | -| IOTA_HTTP_PORT | `7896` | IoT Agent が HTTP 経由で IoT デバイスのトラフィックをリッスンするポート | -| IOTA_PROVIDER_URL | `http://iot-agent:4041` | コマンドが登録されたときに Context Broker に渡された URL。Context Broker がデバイスにコマンドを発行したときに転送 URL の場所として使用 | - - - -# 前提条件 - - - -## Docker - -物事を単純にするために、両方のコンポーネントが [Docker](https://www.docker.com) -を使用して実行されます。**Docker** は、さまざまコンポーネントをそれぞれの環境に -分離することを可能にするコンテナ・テクノロジです。 - -- Docker Windows にインストールするには - 、[こちら](https://docs.docker.com/docker-for-windows/)の手順に従ってくださ - い -- Docker Mac にインストールするには - 、[こちら](https://docs.docker.com/docker-for-mac/)の手順に従ってください -- Docker Linux にインストールするには - 、[こちら](https://docs.docker.com/install/)の手順に従ってください - -**Docker Compose** は、マルチコンテナ Docker アプリケーションを定義して実行する -ためのツールです -。[YAML file](https://raw.githubusercontent.com/Fiware/tutorials.IoT-Agent/master/docker-compose.yml) -ファイルは、アプリケーションのために必要なサービスを構成するために使用します。つ -まり、すべてのコンテナ・サービスは 1 つのコマンドで呼び出すことができます -。Docker Compose は、デフォルトで Docker for Windows と Docker for Mac の一部と -してインストールされますが、Linux ユーザ -は[ここ](https://docs.docker.com/compose/install/)に記載されている手順に従う必要 -があります。 - -次のコマンドを使用して、現在の **Docker** バージョンと **Docker Compose** バージ -ョンを確認できます : - -```console -docker-compose -v -docker version -``` - -Docker バージョン 20.10 以降と Docker Compose 1.29 以上を使用していることを確認 -し、必要に応じてアップグレードしてください。 - - - -## Cygwin for Windows - -シンプルな bash スクリプトを使用してサービスを開始します。Windows ユーザは -[cygwin](http://www.cygwin.com/) をダウンロードして、Windows 上の Linux ディスト -リビューションと同様のコマンドライン機能を提供する必要があります。 - - - -# Start Up - -開始する前に、必要な Docker イメージをローカルで取得または構築しておく必要があり -ます。リポジトリを複製し、以下のコマンドを実行して必要なイメージを作成してくださ -い : - -```console -git clone https://github.com/FIWARE/tutorials.IoT-Agent.git -cd tutorials.IoT-Agent -git checkout NGSI-v2 - -./services create -``` - -その後、リポジトリ内で提供される -、[services](https://github.com/FIWARE/tutorials.IoT-Agent/blob/NGSI-v2/services) -Bash スクリプトを実行することによって、コマンドラインからすべてのサービスを初期 -化することができます : - -```console -./services start -``` - -> :information_source: **注:** クリーンアップしてやり直す場合は、次のコマンドを -> 実行してください : -> -> ```console -> ./services stop -> ``` - - - -# IoT Agent のプロビジョニング - -チュートリアルを正しく実行するには、ブラウザのデバイス・モニタ・ページが表示され -ていることを確認し、ページをクリックして cUrl コマンドを入力する前にオーディオを -有効にしてください。デバイス・モニタには、Ultralight 2.0 構文を使用してダミー・ -デバイスのアレイの現在の状態が表示されます。 - -#### デバイス・モニタ - -デバイス・モニタは次の場所にあります: `http://localhost:3000/device/monitor` - - - -## IoT Agent サービスの正常性の確認 - -IoT Agent が動作しているかどうかは、公開されているポートに対して HTTP リクエスト -を行うことで確認できます: - -#### 1️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/about' -``` - -レスポンスは次のようになります: - -```json -{ - "libVersion": "2.6.0-next", - "port": "4041", - "baseRoot": "/", - "version": "1.6.0-next" -} -``` - -> **`Failed to connect to localhost port 4041: Connection refused` のレスポンス -> を受け取ったらどうしますか?** -> -> `Connection refused` のレスポンスを受け取った場合、IoT Agent がこのチュートリ -> アルで期待される場所に見つからないためです。各 cUrl コマンドの URL とポートを -> 訂正された IP アドレスで置き換える必要があります。すべての cUrl コマンドのチュ -> ートリアルでは、IoT Agent が `localhost:4041` で使用可能であると想定しています -> 。 -> -> 以下の対策を試してください: -> -> - Docker コンテナが動作していることを確認するには、次のようにしてください: -> -> ```console -> docker ps -> ``` -> -> 実行中の 4 つのコンテナが表示されます。IoT Agent が実行されていない場合は、必 -> 要に応じてコンテナを再起動できます。このコマンドは、開いているポート情報も表示 -> します。 -> -> - [`docker-machine`](https://docs.docker.com/machine/) と -> [Virtual Box](https://www.virtualbox.org/) をインストールした場合、Context -> Broker, IoT Agent, IoT Agnet とダミー・デバイスの Docker コンテナが別の IP -> アドレスから実行されている可能性があります: -> -> ```console -> curl -X GET \ -> 'http://$(docker-machine ip default):4041/version' -> ``` -> -> または、コンテナ・ネットワーク内からすべての curl コマンドを実行します: -> -> ```console -> docker run --network fiware_default --rm appropriate/curl -s \ -> -X GET 'http://iot-agent:4041/iot/about' -> ``` - - - -## IoT デバイスの接続 - -IoT Agent は、IoT デバイスと Context Broker との間のミドルウェアとして機能します -。したがって、ユニークな IDs を持つコンテキスト・データのエンティティを作成でき -る必要があります。サービスがプロビジョニングされ、未知のデバイスが測定を行うと -、IoT Agent は、デバイスが認識され、既知の ID にマッピングされない限り、提供され -た `` を使用して、これをコンテキストに追加します。 - -提供されたすべての IoT デバイス `` が常に一意であるという保証はないた -め、IoT Agent へのすべてのプロビジョニング・リクエストには、2 つの必須ヘッダが必 -要です: - -- `fiware-service` ヘッダは、特定のサービスのエンティティを別の mongoDB データ - ベースに保持できるように定義します -- `fiware-servicepath` デバイスの配列間を区別するために使用できます - -たとえば、スマートシティ・アプリケーションでは、さまざまな部門(パーク、交通機関 -、ごみ収集など)ごとに異なる `fiware-service` ヘッダが必要であり、各 -`fiware-servicepath` が特定の公園などを参照します。これは、各サービスのデータと -デバイスが必要に応じて識別され、分離されることを意味しますが、データはサイロ化さ -れません。たとえば、公園内の**スマート・ビン**のデータは、ごみ収集車 の **GPS ユ -ニット** と組み合わせて 、効率的な方法でトラックのルートを変更することができます -。 - -**スマート・ビン**と **GPS ユニット**は、さまざまなメーカーのものを使用する可能 -性があり、使用される `` に重複がないことを保証することはできません -。`fiware-service` ヘッダと `fiware-servicepath` ヘッダの使用は、これが常に当て -はまることを保証し、Context Broker がコンテキスト・データの元のソースを識別する -ことを可能にします。 - - - -### サービス・グループのプロビジョニング - -各測定で認証キーを供給することが常に必要であり、IoT Agent は Context Broker がど -の URL をレスポンスしているかを最初に知ることができないため、グループ接続の呼び -出しは常にデバイス接続の第一歩です。 - -また、すべての匿名デバイスのデフォルトのコマンドと属性を設定することもできますが -、このチュートリアルでは各デバイスを個別にプロビジョニングするため、これは行いま -せん。 - -この例では、匿名のデバイス・グループをプロビジョニングします。これは、IoT Agent -に、一連のデバイスが、IoT Agent が**ノース・バウンド**通信をリッスンしている -`IOTA_HTTP_PORT` クライアントにメッセージを送信することを通知します。 - -#### 2️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/services' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "services": [ - { - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "cbroker": "http://orion:1026", - "entity_type": "Thing", - "resource": "/iot/d" - } - ] -}' -``` - -この例では、`/iot/d` エンドポイントが使用され、デバイスがトークン -`4jggokgpepnvsb2uv4s40d59ov` を含めることによって自身を認証することが IoT Agent -に通知されます。UltraLight IoT Agent の場合、これはデバイスが GET リクエストまた -は POST リクエストを次の宛先に送信していることを意味します: - -``` -http://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov -``` - -これは -、[以前のチュートリアル](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2)で -Ultra Light 2.0 の構文に慣れているはずです。 - -IoT デバイスからの測定値がリソース url で受信されると、それを解釈して Context -Broker に渡す必要があります。この`entity_type` 属性は、リクエストを行った各装置 -のデフォルト `type` を提供します。この場合、匿名の装置は `Thing` エンティティと -呼ばれます。さらに、IoT Agent が受信した任意の測定値を正しい場所に渡すことができ -るように、Context Broker (`cbroker`) の位置が必要です。`cbroker` はオプションの -属性です。IoT Agent が提供されていない場合、IoT Agent は設定ファイルで定義されて -いる、Context Broker URL を使用しますが、完全性のためにここに含まれています。 - - - -### センサのプロビジョニング - -エンティティを作成するときは、NGSI-LD -[仕様](https://www.etsi.org/deliver/etsi_gs/CIM/001_099/009/01.08.01_60/gs_cim009v010801p.pdf)に -従って URNs を使用するのが一般的な良い方法です。さらに、データ属性を定義するとき -に意味のある名前にするとわかりやすくなります。これらのマッピングは、デバイスを個 -別にプロビジョニングすることによって定義できます。 - -3 つのタイプの測定値の属性をプロビジョニングできます: - -- `attributes` デバイスからのアクティブな読み取り値 -- `lazy` リクエストに応じて送信されます - IoT Agent は測定結果を返すようにデバ - イスに通知 -- `static_attributes` Context Broker に渡される、リレーションシップなどのデバ - イスに関する静的なデータを示す名前 - -> **注**: 個体 id が必要でないか、または集約されたデータが十分である場合は、個別 -> にではなくプロビジョニング・サービス内で `attributes` を定義できます - -#### 3️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "motion001", - "entity_name": "urn:ngsi-ld:Motion:001", - "entity_type": "Motion", - "timezone": "Europe/Berlin", - "attributes": [ - { "object_id": "c", "name": "count", "type": "Integer" } - ], - "static_attributes": [ - { "name":"refStore", "type": "Relationship", "value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -リクエストでは、デバイス `motion001` を URN `urn:ngsi-ld:Motion:001` と関連付け -て、デバイスの読み取り値 `c` を `Integer` として定義されているコンテキスト属性 -`count` とマッピングしています。`refStore` は static_attribute として定義され、 -デバイスを **Store** `urn:ngsi-ld:Store:001` 内に配置します。 - -> 静的属性は、`q` パラメータを使用したクエリを有効にするエンティティの追加データとして役立ちます。たとえば、Smart -> Data Models [Device](https://github.com/smart-data-models/dataModel.Device/blob/master/Device/doc/spec.md) モデルは、 -> クエリを次のように実行できるようにする `category` や `controledProperty` などの属性を定義します: -> -> - _現在どの **Actuators** の `batteryLevel` が低いですか?_ -> -> `/v2/entities?q=category=="actuator";batteryLevel<0.1` -> -> - _2020年1月より前にインストールされた `fillingLevel` を測定する **Devices** はどれですか?_ -> -> `/v2/entities?q=controlledProperty=="fillingLevel";dateInstalled<"2020-01-25T00:00:00.000Z"` -> -> 明らかに、静的データは必要に応じて拡張でき、エンティティ ID がクエリに対して柔軟性がない場合は、デバイスごとに一意の -> `name ` や `serialNumber` などの追加データを含めることもできます。 -> -> `/v2/entities?q=serialNumber=="XS403001-002"` -> -> さらに、固定の `location` 静的属性を持つデバイスは、ジオフェンス・パラメータを使用してクエリすることもできます。 -> -> `/v2/entities?georel=near;maxDistance:1500&geometry=point&coords=52.5162,13.3777` - -**モーション・センサ**のデバイス `motion001` からのダミー IoT デバイスの測定値を -シミュレーションするには、次のリクエストを行います - -#### 4️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:7896/iot/d?k=4jggokgpepnvsb2uv4s40d59ov&i=motion001' \ - -H 'Content-Type: text/plain' \ - -d 'c|1' -``` - -IoT Agent が接続される前、以前のチュートリアルで同様のリクエストが行われ、ドアが -ロック解除されると、各**モーション・センサ**の状態が変化し、デバイス・モニタにノ -ース・バウンドのリクエストが記録されます。 - -今度は、IoT Agent が接続され、サービス・グループは IoT Agent が (`iot/d`) をリッ -スンしているリソースと、リクエスト(4jggokgpepnvsb2uv4s40d59ov)を認証するために使 -用された API キーを定義しました。これらの両方が認識されるので測定は有効です。 - -IoT Agent はデバイス(`motion001`)を特別にプロビジョニングしたため、Orion Context -Broker でリクエストを発行する前に属性をマップできます。 - -Context Broker からエンティティのデータを取得することによって、測定値が記録され -ていることがわかります。`fiware-service` と `fiware-service-path` ヘッダを追加す -ることを忘れないでください。 - -#### 5️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Motion:001?type=Motion' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -```json -{ - "id": "urn:ngsi-ld:Motion:001", - "type": "Motion", - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.00Z", - "metadata": {} - }, - "count": { - "type": "Integer", - "value": "1", - "metadata": { - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.646Z" - } - } - }, - "refStore": { - "type": "Relationship", - "value": "urn:ngsi-ld:Store:001", - "metadata": { - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.646Z" - } - } - } -} -``` - -レスポンスは、`id = motion001`の**モーション・センサ**のデバイスが IoT Agnet に -よって正常に識別され、エンティティ `id=urn:ngsi-ld:Motion:001` にマッピングされ -ていることを示します。この新しいエンティティは、コンテキスト・データ内で作成され -ました。ダミー・デバイスの測定リクエストからの `c` 属性はコンテキスト内のより意 -味のある `count` 属性にマップされています。お気づきのように、`TimeInstant` 属性 -がエンティティと属性のメタデータの両方に追加されました。これはエンティティと属性 -が最後に更新された時刻を表し、`IOTA_TIMESTAMP` 環境変数が IoT Agent の起動時に設 -定されます。`refStore` 属性は、デバイスがプロビジョニングされたときにセットされ -た `static_attributes` から来ます。 - - - -### コマンドを介したアクチュエータのプロビジョニング - -アクチュエータのプロビジョニングは、センサのプロビジョニングと同様です。今回 -、`endpoint` 属性には、IoT Agent が UltraLight コマンドを送信する必要がある場所 -が格納され、`commands` 配列には呼び出すことができる各コマンドのリストが含まれて -います。以下の例では、`deviceId=bell001` のベルがプロビジョニングされています。 -エンドポイントは `http://iot-sensors:3001/iot/bell001` であり、`ring` コマンドを -受け入れることができます。 - -#### 6️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "bell001", - "entity_name": "urn:ngsi-ld:Bell:001", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell001", - "commands": [ - { "name": "ring", "type": "command" } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - - - -### 双方向属性 (bidirectional attribute) を介したアクチュエータのプロビジョニング - -アクチュエータは、双方向属性を使用してプロビジョニングすることもできます。 ここでも、`endpoint` 属性は、IoT Agent が -UltraLight コマンドを送信する必要がある場所を保持します。`ring` 属性は `expression` を使用して定義され、`reverse` -方向にそれ自体にマップされます。 `ring` 属性の更新を受信すると、それはデバイス自体にも送信されます。内部的な違いは、 -この方法がレジストレーションではなくサブスクリプションに依存していることです。 - -#### 7️⃣ リクエスト : - -```console -curl -L -X POST 'http://localhost:4041/iot/devices' \ --H 'fiware-service: openiot' \ --H 'fiware-servicepath: /' \ --H 'Content-Type: application/json' \ --H 'Cookie: _csrf=MAPTGFPcoPnewsGCWklHi4Mq' \ ---data-raw '{ - "devices": [ - { - "device_id": "bell002", - "entity_name": "urn:ngsi-ld:Bell:002", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "attributes": [ - { - "name": "ring", - "type": "Text", - "expression": "ring", - "reverse": [ - { - "object_id": "ring", - "type": "Text", - "expression": "ring | toString()" - } - ] - } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:002"} - ] - } - ] -} -' -``` - -Context Broker を接続する前に、`/v2/op/update` エンドポイントを使用して IoT -Agent のノース・ポートに REST リクエストを直接送信することで、コマンドをデバイス -に送信できることをテストできます。Context Broker が接続すると、最終的に Context -Broker によって呼び出されるのはこのエンドポイントです。設定をテストするには、次 -のようにコマンドを直接実行します : - -#### 8️⃣ リクエスト : - -```console -curl -iX POST \ - http://localhost:4041/v2/op/update \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "actionType": "update", - "entities": [ - { - "type": "Bell", - "id": "urn:ngsi-ld:Bell:001", - "ring" : { - "type": "command", - "value": "" - } - } - ] -}' -``` - -デバイス・モニタ・ページを表示している場合は、ベル変更の状態も表示できます。 - -![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif) - -ベルを鳴らすコマンドの結果は、Orion Context Broker 内のエンティティにクエリする -ことによって読み取ることができます。 - -#### 9️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001?type=Bell&options=keyValues' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -```json -{ - "id": "urn:ngsi-ld:Bell:001", - "type": "Bell", - "TimeInstant": "2018-05-25T20:06:28.00Z", - "refStore": "urn:ngsi-ld:Store:001", - "ring_info": " ring OK", - "ring_status": "OK", - "ring": "" -} -``` - -`TimeInstant` は、エンティティに関連付けられたコマンドが呼び出された時刻を最後に -表示します。 リング・コマンドの結果は、`ring_info` 属性の値で見ることができます -。 - - - -### スマート・ドアのプロビジョニング - -コマンドと測定の両方を提供するデバイスのプロビジョニングは、リクエストの本文に -`attributes` と `command` 属性の両方を含む、HTTP POST リクエストを作成するだけで -す。 - -#### 1️⃣0️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "door001", - "entity_name": "urn:ngsi-ld:Door:001", - "entity_type": "Door", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/door001", - "commands": [ - {"name": "unlock","type": "command"}, - {"name": "open","type": "command"}, - {"name": "close","type": "command"}, - {"name": "lock","type": "command"} - ], - "attributes": [ - {"object_id": "s", "name": "state", "type":"Text"} - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - - - -### スマート・ランプのプロビジョニング - -同様に、2 つのコマンド(`on` および `off`)と 2 つの属性を持つ**スマート・ラン -プ**は、次のようにプロビジョニングできます: - -#### 1️⃣1️⃣リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "lamp001", - "entity_name": "urn:ngsi-ld:Lamp:001", - "entity_type": "Lamp", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/lamp001", - "commands": [ - {"name": "on","type": "command"}, - {"name": "off","type": "command"} - ], - "attributes": [ - {"object_id": "s", "name": "state", "type":"Text"}, - {"object_id": "l", "name": "luminosity", "type":"Integer"} - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -プロビジョニングされたデバイスの完全なリストは、`/iot/devices` エンドポイントに -GET リクエストを行うことで取得できます。 - -#### 1️⃣2️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - - - -## Context Broker コマンド の有効化 - -IoT Agent を IoT デバイスに接続すると、Orion Context Broker にコマンドが利用可能に -なったことが通知されました。つまり、IoT Agent は、コマンド属性の -[コンテキスト・プロバイダ](https://github.com/FIWARE/tutorials.Context-Providers/) -として自身を登録しました。 - -コマンドが登録されていたら -、[以前のチュートリアル](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2)で行っ -たように、IoT デバイスから直接 Ultra Light 2.0 リクエストを送信するのではなく -、**ベル**に呼び出し音を出したり、**スマート・ドア**を開閉したり、**スイッチスマ -ート・ランプ**をオン/オフに切り替えることができます。 - - - -### ベルを鳴らす - -`ring` コマンドを呼び出すには、コンテキスト内で `ring` 属性を更新する必要があり -ます。 - -#### 1️⃣3️⃣ リクエスト : - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001/attrs?type=Bell' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "ring": { - "type" : "command", - "value" : "" - } -}' -``` - -デバイス・モニタ・ページを表示している場合は、ベル変更の状態も表示できます。 - -![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif) - - - -### スマート・ドアを開く - -`open` コマンドを呼び出すには、コンテキスト内で `open` 属性を更新する必要があり -ます。 - -#### 1️⃣4️⃣ リクエスト : - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Door:001/attrs?type=Door' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "open": { - "type" : "command", - "value" : "" - } -}' -``` - - - -### スマート・ランプをオンにする - -**スマート・ランプ**をオンにするには、その `on` 属性をコンテキストで更新する必要 -があります。 - -#### 1️⃣5️⃣ リクエスト : - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Lamp:001/attrs?type=Lamp' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "on": { - "type" : "command", - "value" : "" - } -}' -``` - - - -# サービス・グループの CRUD アクション - -サービス・グループをプロビジョニングするための **CRUD** 操作は、`/iot/services` -エンドポイントの下にある期待される HTTP 動詞にマップされます。 - -- **Create** - HTTP POST -- **Read** - HTTP GET -- **Update** - HTTP PUT -- **Delete** - HTTP DELETE - -`resource` と `apikey` パラメータを使用して、サービス・グループを一意に識別しま -す。 - - - -### サービス・グループの作成 - -この例では、匿名のデバイス・グループをプロビジョニングします。IoT Agent は、一連 -のデバイスが、 IoT Agent が**ノース・バウンド**通信をリッスンしている -`IOTA_HTTP_PORT` にメッセージを送信することを通知します。 - -#### 1️⃣6️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/services' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "services": [ - { - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "cbroker": "http://orion:1026", - "entity_type": "Thing", - "resource": "/iot/d" - } - ] -}' -``` - - - -### サービス・グループの詳細を読み込む - -この例では、指定された `resource` パスを持つプロビジョニングされたサービスの完全 -な詳細を取得します。 - -サービス・グループの詳細は、`/iot/services` エンドポイントへの GET リクエストと -`resource` パラメータの提供によって読み取ることができます。 - -#### 1️⃣7️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/services?resource=/iot/d' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -```json -{ - "_id": "5b07b2c3d7eec57836ecfed4", - "subservice": "/", - "service": "openiot", - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "resource": "/iot/d", - "attributes": [], - "lazy": [], - "commands": [], - "entity_type": "Thing", - "internal_attributes": [], - "static_attributes": [] -} -``` - -レスポンスには、`entity_type` などの各サービス・グループに関連付けられているすべ -てのデフォルトや、デフォルトのコマンド、または属性のマッピングなどが含まれます。 - - - -### すべてのサービス・グループを一覧表示 - -この例では、`/iot/services` エンドポイントに GET リクエストを行うことによって、 -プロビジョニングされたすべてのサービスを一覧表示します。 - -#### 1️⃣8️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/services' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -```json -{ - "_id": "5b07b2c3d7eec57836ecfed4", - "subservice": "/", - "service": "openiot", - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "resource": "/iot/d", - "attributes": [], - "lazy": [], - "commands": [], - "entity_type": "Thing", - "internal_attributes": [], - "static_attributes": [] -} -``` - -レスポンスには、`entity_type` などの各サービス・グループに関連付けられているすべ -てのデフォルトや、デフォルトのコマンド、または属性のマッピングなどが含まれます。 - - - -### サービス・グループを更新 - -この例では、既存のサービス・グループを特定の `resource` パスおよび `apikey` で更 -新します。 - -サービス・グループの詳細は、`/iot/services` エンドポイントへの PUT リクエストを -行い、`resource` および `apikey` パラメータを提供することによって更新できます。 - -#### 1️⃣9️⃣ リクエスト : - -```console -curl -iX PUT \ - 'http://localhost:4041/iot/services?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "entity_type": "IoT-Device" -}' -``` - - - -### サービス・グループを削除 - -この例では、`/iot/services/` エンドポイントに DELETE リクエストを行うことによっ -て、プロビジョニングされたサービス・グループを削除します。 - -つまり、IoT Agent が**ノース・バウンド**通信をリスンしている -`http://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov` へのリ -クエストは、IoT Agent によって処理されなくなります。削除するサービス・グループを -識別するには、`apiKey` パラメータと `resource` パラメータを指定する必要がありま -す。 - -#### 2️⃣0️⃣ リクエスト : - -```console -curl -iX DELETE \ - 'http://localhost:4041/iot/services/?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -# デバイスの CRUD アクション - -個々のデバイスをプロビジョニングするための **CRUD** 操作は、`/iot/devices` エン -ドポイントの下にある期待される HTTP 動詞にマッピングされます - -- **Create** - HTTP POST -- **Read** - HTTP GET -- **Update** - HTTP PUT -- **Delete** - HTTP DELETE - -`` を使用して、デバイスを一意に識別します。 - - - -### プロビジョニングされたデバイスの作成 - -この例では個々のデバイスをプロビジョニングします。`device_id=bell002` をエンティ -ティ `urn:ngsi-ld:Bell:002` にマップし、エンティティに `Bell` 型を与えます。IoT -Agent は、デバイスが単一の `ring` `command` を提供し、HTTP を使用して -`http://iot-sensors:3001/iot/bell002` でリッスンしていることを通知されました -。`attributes`, `lazy` 属性と、`static_attributes` もプロビジョニングできます。 - -#### 2️⃣1️⃣ リクエスト : - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "bell002", - "entity_name": "urn:ngsi-ld:Bell:002", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "commands": [ - { - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:002"} - ] - } - ] -}' -``` - - - -### プロビジョニングされたデバイスの詳細を読み込む - -この例では、指定された `` パスを持つプロビジョニングされたデバイスの -完全な詳細を取得します。 - -プロビジョニングされたデバイスの詳細は、`/iot/devices/` エンドポイン -トに GET リクエストを行うことで読み取ることができます。 - -#### 2️⃣2️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -レスポンスには、デバイスに関連付けられているすべてのコマンドと属性のマッピングが -含まれています。 - -```json -{ - "device_id": "bell002", - "service": "openiot", - "service_path": "/", - "entity_name": "urn:ngsi", - "entity_type": "Bell", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "transport": "HTTP", - "attributes": [], - "lazy": [], - "commands": [ - { - "object_id": "ring", - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - { - "name": "refStore", - "type": "Relationship", - "value": "urn:ngsi-ld:Store:002" - } - ], - "protocol": "PDI-IoTA-UltraLight" -} -``` - - - -### プロビジョニングされたすべてのデバイスを一覧表示 - -この例では、`/iot/devices` エンドポイントに GET リクエストを行うことによって、プ -ロビジョニングされたすべてのデバイスを一覧表示します。 - -#### 2️⃣3️⃣ リクエスト : - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### レスポンス : - -レスポンスには、すべてのデバイスに関連付けられているすべてのコマンドと属性のマッ -ピングが含まれます。 - -```json -{ - "count": 5, - "devices": [ - { - "device_id": "bell002", - "service": "openiot", - "service_path": "/", - "entity_name": "urn:ngsi", - "entity_type": "Bell", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "transport": "HTTP", - "attributes": [], - "lazy": [], - "commands": [ - { - "object_id": "ring", - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - { - "name": "refStore", - "type": "Relationship", - "value": "urn:ngsi-ld:Store:002" - } - ], - "protocol": "PDI-IoTA-UltraLight" - }, - etc... - ] -} -``` - - - -### プロビジョニングされたデバイスを更新 - -この例では、`/iot/devices/` エンドポイントに PUT リクエストを行うこと -によって、既存のプロビジョニングされたデバイスを更新します。 - -#### 2️⃣4️⃣ リクエスト : - -```console -curl -iX PUT \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "entity_type": "IoT-Device" -}' -``` - - - -### プロビジョニングされたデバイスを削除 - -この例では、`/iot/devices/` エンドポイントに DELETE リクエストを行う -ことによって、プロビジョニングされたデバイスを削除します。 - -デバイスの属性はマップされなくなり、コマンドはデバイスに送信できなくなります。デ -バイスがアクティブな測定を行っていると、関連付けられたサービスが削除されていない -場合でも、デフォルト値で処理されます。 - -#### 2️⃣5️⃣ リクエスト : - -```console -curl -iX DELETE \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - - - -# 次のステップ - -高度な機能を追加することで、アプリケーションに複雑さを加える方法を知りたいですか -?このシリーズ -の[他のチュートリアル](https://www.letsfiware.jp/fiware-tutorials)を読むことで見 -つけることができます - ---- - -## License - -[MIT](LICENSE) © 2018-2024 FIWARE Foundation e.V. diff --git a/README.md b/README.md index 5c98675..b752c05 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ [![FIWARE Banner](https://fiware.github.io/tutorials.IoT-Agent/img/fiware.png)](https://www.fiware.org/developers) -[![NGSI v2](https://img.shields.io/badge/NGSI-v2-5dc0cf.svg)](https://fiware-ges.github.io/orion/api/v2/stable/) [![FIWARE IoT Agents](https://nexus.lab.fiware.org/repository/raw/public/badges/chapters/iot-agents.svg)](https://github.com/FIWARE/catalogue/blob/master/iot-agents/README.md) [![License: MIT](https://img.shields.io/github/license/fiware/tutorials.Iot-Agent.svg)](https://opensource.org/licenses/MIT) [![Support badge](https://img.shields.io/badge/tag-fiware-orange.svg?logo=stackoverflow)](https://stackoverflow.com/questions/tagged/fiware) [![UltraLight 2.0](https://img.shields.io/badge/Payload-Ultralight-27ae60.svg)](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) -
[![Documentation](https://img.shields.io/readthedocs/fiware-tutorials.svg)](https://fiware-tutorials.rtfd.io) This tutorial introduces the concept of an **IoT Agent** and wires up the dummy [UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) IoT @@ -15,1311 +13,43 @@ measurements can be read and commands can be sent using [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/). The tutorial uses [cUrl](https://ec.haxx.se/) commands throughout, but is also available as -[Postman documentation](https://fiware.github.io/tutorials.IoT-Agent/) +[Postman documentation](https://www.postman.com/downloads/). -[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/2150531e68299d46f937) -[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/FIWARE/tutorials.IoT-Agent/tree/NGSI-v2) +# Start-Up -- このチュートリアルは[日本語](README.ja.md)でもご覧いただけます。 +## NGSI-v2 Smart Supermarket -## Contents - -
-Details - -- [What is an IoT Agent?](#what-is-an-iot-agent) - - [Southbound Traffic (Commands)](#southbound-traffic-commands) - - [Northbound Traffic (Measurements)](#northbound-traffic-measurements) - - [Common Functionality](#common-functionality) -- [Architecture](#architecture) - - [Dummy IoT Devices Configuration](#dummy-iot-devices-configuration) - - [IoT Agent for UltraLight 2.0 Configuration](#iot-agent-for-ultralight-20-configuration) -- [Prerequisites](#prerequisites) - - [Docker and Docker Compose](#docker-and-docker-compose) - - [Cygwin for Windows](#cygwin-for-windows) -- [Start Up](#start-up) -- [Provisioning an IoT Agent](#provisioning-an-iot-agent) - - [Checking the IoT Agent Service Health](#checking-the-iot-agent-service-health) - - [Connecting IoT Devices](#connecting-iot-devices) - - [Provisioning a Service Group](#provisioning-a-service-group) - - [Provisioning a Sensor](#provisioning-a-sensor) - - [Provisioning an Actuator via a Command](#provisioning-an-actuator-via-a-command) - - [Provisioning an Actuator via a Bidirectional Attribute](#provisioning-an-actuator-via-a-bidirectional-attribute) - - [Provisioning a Smart Door](#provisioning-a-smart-door) - - [Provisioning a Smart Lamp](#provisioning-a-smart-lamp) - - [Enabling Context Broker Commands](#enabling-context-broker-commands) - - [Ringing the Bell](#ringing-the-bell) - - [Opening the Smart Door](#opening-the-smart-door) - - [Switching on the Smart Lamp](#switching-on-the-smart-lamp) -- [Service Group CRUD Actions](#service-group-crud-actions) - - [Creating a Service Group](#creating-a-service-group) - - [Read Service Group Details](#read-service-group-details) - - [List all Service Groups](#list-all-service-groups) - - [Update a Service Group](#update-a-service-group) - - [Delete a Service Group](#delete-a-service-group) -- [Device CRUD Actions](#device-crud-actions) - - [Creating a Provisioned Device](#creating-a-provisioned-device) - - [Read Provisioned Device Details](#read-provisioned-device-details) - - [List all Provisioned Devices](#list-all-provisioned-devices) - - [Update a Provisioned Device](#update-a-provisioned-device) - - [Delete a Provisioned Device](#delete-a-provisioned-device) -- [Next Steps](#next-steps) - -
- -# What is an IoT Agent? - -> "In every operation there is an above the line and a below the line. Above the line is what you do by the book. Below -> the line is how you do the job." -> -> — John le Carré (A Perfect Spy) - -An IoT Agent is a component that lets a group of devices send their data to and be managed from a Context Broker using -their own native protocols. IoT Agents should also be able to deal with security aspects of the FIWARE platform -(authentication and authorization of the channel) and provide other common services to the device programmer. - -The Orion Context Broker exclusively uses [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) requests for -all of its interactions. Each IoT Agent provides a **North Port** -[NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) interface which is used for context broker -interactions and all interactions beneath this port occur using the **native protocol** of the attached devices. - -In effect, this brings a standard interface to all IoT interactions at the context information management level. Each -group of IoT devices are able to use their own proprietary protocols and disparate transport mechanisms under the hood -whilst the associated IoT Agent offers a facade pattern to handle this complexity. - -IoT Agents already exist or are in development for many IoT communication protocols and data models. Examples include -the following: - -- [IoTAgent-JSON](https://fiware-iotagent-json.readthedocs.io/en/latest/) - a bridge between HTTP/MQTT messaging (with - a JSON payload) and NGSI -- [IoTAgent-LWM2M](https://fiware-iotagent-lwm2m.readthedocs.io/en/latest) - a bridge between the - [Lightweight M2M](https://www.omaspecworks.org/what-is-oma-specworks/iot/lightweight-m2m-lwm2m/) protocol and NGSI -- [IoTAgent-UL](https://fiware-iotagent-ul.readthedocs.io/en/latest) - a bridge between HTTP/MQTT messaging (with an - UltraLight2.0 payload) and NGSI -- [IoTagent-LoRaWAN](https://fiware-lorawan.readthedocs.io/en/latest) - a bridge between the - [LoRaWAN](https://www.thethingsnetwork.org/docs/lorawan/) protocol and NGSI -- [IoTagent-OPCUA](https://iotagent-opcua.readthedocs.io/en/latest/) - a bridge between the - [OPC-UA](https://opcfoundation.org/about/opc-technologies/opc-ua/) protocol and NGSI - -## Southbound Traffic (Commands) - -HTTP requests generated by the Orion Context Broker and passed downwards towards an IoT device (via an IoT agent) are -known as southbound traffic. Southbound traffic consists of **commands** made to actuator devices which alter the state -of the real world by their actions. - -For example to switch on a real-life UltraLight 2.0 **Smart Lamp** the following interactions would occur: - -1. An NGSI PATCH request is sent to the **Context broker** to update the current context of **Smart Lamp** - -- this is effectively an indirect request invoke the `on` command of the **Smart Lamp** - -2. The **Context Broker** finds the entity within the context and notes that the context provision for this attribute - has been delegated to the IoT Agent -3. The **Context broker** sends an NGSI request to the North Port of the **IoT Agent** to invoke the command -4. The **IoT Agent** receives this Southbound request and converts it to UltraLight 2.0 syntax and passes it on to the - **Smart Lamp** -5. The **Smart Lamp** switches on the lamp and returns the result of the command to the **IoT Agent** in UltraLight 2.0 - syntax -6. The **IoT Agent** receives this Northbound request, interprets it and passes the result of the interaction into the - context by making an NGSI request to the **Context Broker**. -7. The **Context Broker** receives this Northbound request and updates the context with the result of the command. - -![](https://fiware.github.io/tutorials.IoT-Agent/img/command-swimlane.png) - -- Requests between **User** and **Context Broker** use NGSI -- Requests between **Context Broker** and **IoT Agent** use NGSI -- Requests between **IoT Agent** and **IoT Device** use native protocols -- Requests between **IoT Device** and **IoT Agent** use native protocols -- Requests between **IoT Agent** and **Context Broker** use NGSI - -## Northbound Traffic (Measurements) - -Requests generated from an IoT device and passed back upwards towards the Context Broker (via an IoT agent) are known as -northbound traffic. Northbound traffic consists of **measurements** made by sensor devices and relays the state of the -real world into the context data of the system. - -For example for a real-life **Motion Sensor** to send a count measurement the following interactions would occur: - -1. A **Motion Sensor** makes a measurement and passes the result to the **IoT Agent** -2. The **IoT Agent** receives this Northbound request, converts the result from UltraLight syntax and passes the result - of the interaction into the context by making an NGSI request to the **Context Broker**. -3. The **Context Broker** receives this Northbound request and updates the context with the result of the measurement. - -![](https://fiware.github.io/tutorials.IoT-Agent/img/measurement-swimlane.png) - -- Requests between **IoT-Device** and **IoT-Agent** use native protocols -- Requests between **IoT-Agent** and **Context-Broker** use NGSI - -> [!NOTE] -> Other more complex interactions are also possible, but this overview is sufficient to understand the basic -> principles of an IoT Agent. - -## Common Functionality - -As can be seen from the previous sections, although each IoT Agent will be unique since they interpret different -protocols, there will a large degree of similarity between IoT agents. - -- Offering a standard location to listen to device updates -- Offering a standard location to listen to context data updates -- Holding a list of devices and mapping context data attributes to device syntax -- Security Authorization - -This base functionality has been abstracted out into a common -[IoT Agent framework library](https://iotagent-node-lib.readthedocs.io/) - -#### Device Monitor - -For the purpose of this tutorial, a series of dummy IoT devices have been created, which will be attached to the context -broker. Details of the architecture and protocol used can be found in the -[IoT Sensors tutorial](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2) The state of each device can be -seen on the UltraLight device monitor web page found at: `http://localhost:3000/device/monitor` - -![FIWARE Monitor](https://fiware.github.io/tutorials.IoT-Agent/img/device-monitor.png) - -# Architecture - -This application builds on the components created in -[previous tutorials](https://github.com/FIWARE/tutorials.Subscriptions/). It will make use of two FIWARE components - -the [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) and the -[IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/). Usage of the Orion Context Broker -is sufficient for an application to qualify as _“Powered by FIWARE”_. Both the Orion Context Broker and the IoT Agent -rely on open source [MongoDB](https://www.mongodb.com/) technology to keep persistence of the information they hold. We -will also be using the dummy IoT devices created in the -[previous tutorial](https://github.com/FIWARE/tutorials.IoT-Sensors/) - -Therefore the overall architecture will consist of the following elements: - -- The FIWARE [Orion Context Broker](https://fiware-orion.readthedocs.io/en/latest/) which will receive requests using - [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) -- The FIWARE [IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/) which will receive - southbound requests using [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) and convert them to - [UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) - commands for the devices -- The underlying [MongoDB](https://www.mongodb.com/) database : - - Used by the **Orion Context Broker** to hold context data information such as data entities, subscriptions and - registrations - - Used by the **IoT Agent** to hold device information such as device URLs and Keys -- The **Context Provider NGSI** proxy is not used in this tutorial. It does the following: - - receive requests using [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) - - makes requests to publicly available data sources using their own APIs in a proprietary format - - returns context data back to the Orion Context Broker in - [NGSI-v2](https://fiware.github.io/specifications/OpenAPI/ngsiv2) format. -- The **Stock Management Frontend** is not used in this tutorial will it does the following: - - Display store information - - Show which products can be bought at each store - - Allow users to "buy" products and reduce the stock count. -- A webserver acting as set of [dummy IoT devices](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2) using - the - [UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/usermanual/index.html#user-programmers-manual) - protocol running over HTTP. - -Since all interactions between the elements are initiated by HTTP requests, the entities can be containerized and run -from exposed ports. - -![](https://fiware.github.io/tutorials.IoT-Agent/img/architecture.png) - -The necessary configuration information for wiring up the IoT devices and the IoT Agent can be seen in the services -section of the associated `docker-compose.yml` file: - -## Dummy IoT Devices Configuration - -```yaml -tutorial: - image: quay.io/fiware/tutorials.context-provider - hostname: iot-sensors - container_name: fiware-tutorial - networks: - - default - expose: - - '3000' - - '3001' - ports: - - '3000:3000' - - '3001:3001' - environment: - - 'DEBUG=tutorial:*' - - 'PORT=3000' - - 'IOTA_HTTP_HOST=iot-agent' - - 'IOTA_HTTP_PORT=7896' - - 'DUMMY_DEVICES_PORT=3001' - - 'DUMMY_DEVICES_API_KEY=4jggokgpepnvsb2uv4s40d59ov' - - 'DUMMY_DEVICES_TRANSPORT=HTTP' -``` - -The `tutorial` container is listening on two ports: - -- Port `3000` is exposed so we can see the web page displaying the Dummy IoT devices. -- Port `3001` is exposed purely for tutorial access - so that cUrl or Postman can make UltraLight commands without - being part of the same network. - -The `tutorial` container is driven by environment variables as shown: - -| Key | Value | Description | -| ----------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -| DEBUG | `tutorial:*` | Debug flag used for logging | -| WEB_APP_PORT | `3000` | Port used by web-app which displays the dummy device data | -| IOTA_HTTP_HOST | `iot-agent` | The hostname of the IoT Agent for UltraLight 2.0 - see below | -| IOTA_HTTP_PORT | `7896` | The port that the IoT Agent for UltraLight 2.0 will be listening on. `7896` is a common default for UltraLight over HTTP | -| DUMMY_DEVICES_PORT | `3001` | Port used by the dummy IoT devices to receive commands | -| DUMMY_DEVICES_API_KEY | `4jggokgpepnvsb2uv4s40d59ov` | Random security key used for UltraLight interactions - used to ensure the integrity of interactions between the devices and the IoT Agent | -| DUMMY_DEVICES_TRANSPORT | `HTTP` | The transport protocol used by the dummy IoT devices | - -The other `tutorial` container configuration values described in the YAML file are not used in this tutorial. - -## IoT Agent for UltraLight 2.0 Configuration - -The [IoT Agent for UltraLight 2.0](https://fiware-iotagent-ul.readthedocs.io/en/latest/) can be instantiated within a -Docker container. An official Docker image is available from [Docker Hub](https://hub.docker.com/r/fiware/iotagent-ul/) -tagged `fiware/iotagent-ul`. The necessary configuration can be seen below: - -```yaml -iot-agent: - image: quay.io/fiware/iotagent-ul:latest - hostname: iot-agent - container_name: fiware-iot-agent - depends_on: - - mongo-db - networks: - - default - expose: - - '4041' - - '7896' - ports: - - '4041:4041' - - '7896:7896' - environment: - - IOTA_CB_HOST=orion - - IOTA_CB_PORT=1026 - - IOTA_NORTH_PORT=4041 - - IOTA_REGISTRY_TYPE=mongodb - - IOTA_LOG_LEVEL=DEBUG - - IOTA_TIMESTAMP=true - - IOTA_CB_NGSI_VERSION=v2 - - IOTA_AUTOCAST=true - - IOTA_MONGO_HOST=mongo-db - - IOTA_MONGO_PORT=27017 - - IOTA_MONGO_DB=iotagentul - - IOTA_HTTP_PORT=7896 - - IOTA_PROVIDER_URL=http://iot-agent:4041 -``` - -The `iot-agent` container relies on the precence of the Orion Context Broker and uses a MongoDB database to hold device -information such as device URLs and Keys. The container is listening on two ports: - -- Port `7896` is exposed to receive Ultralight measurements over HTTP from the Dummy IoT devices -- Port `4041` is exposed purely for tutorial access - so that cUrl or Postman can make provisioning commands without - being part of the same network. - -The `iot-agent` container is driven by environment variables as shown: - -| Key | Value | Description | -| -------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| IOTA_CB_HOST | `orion` | Hostname of the context broker to update context | -| IOTA_CB_PORT | `1026` | Port that context broker listens on to update context | -| IOTA_NORTH_PORT | `4041` | Port used for Configuring the IoT Agent and receiving context updates from the context broker | -| IOTA_REGISTRY_TYPE | `mongodb` | Whether to hold IoT device info in memory or in a database | -| IOTA_LOG_LEVEL | `DEBUG` | The log level of the IoT Agent | -| IOTA_TIMESTAMP | `true` | Whether to supply timestamp information with each measurement received from attached devices | -| IOTA_CB_NGSI_VERSION | `v2` | Whether to supply use NGSI v2 when sending updates for active attributes | -| IOTA_AUTOCAST | `true` | Ensure Ultralight number values are read as numbers not strings | -| IOTA_MONGO_HOST | `context-db` | The hostname of mongoDB - used for holding device information | -| IOTA_MONGO_PORT | `27017` | The port mongoDB is listening on | -| IOTA_MONGO_DB | `iotagentul` | The name of the database used in mongoDB | -| IOTA_HTTP_PORT | `7896` | The port where the IoT Agent listens for IoT device traffic over HTTP | -| IOTA_PROVIDER_URL | `http://iot-agent:4041` | URL passed to the Context Broker when commands are registered, used as a forwarding URL location when the Context Broker issues a command to a device | - -# Prerequisites - -## Docker - -To keep things simple all components will be run using [Docker](https://www.docker.com). **Docker** is a container -technology which allows to different components isolated into their respective environments. - -- To install Docker on Windows follow the instructions [here](https://docs.docker.com/docker-for-windows/) -- To install Docker on Mac follow the instructions [here](https://docs.docker.com/docker-for-mac/) -- To install Docker on Linux follow the instructions [here](https://docs.docker.com/install/) - -**Docker Compose** is a tool for defining and running multi-container Docker applications. A -[YAML file](https://raw.githubusercontent.com/Fiware/tutorials.Entity-Relationships/master/docker-compose.yml) is used -configure the required services for the application. This means all container services can be brought up in a single -command. Docker Compose is installed by default as part of Docker for Windows and Docker for Mac, however Linux users -will need to follow the instructions found [here](https://docs.docker.com/compose/install/) - -You can check your current **Docker** and **Docker Compose** versions using the following commands: - -```console -docker-compose -v -docker version -``` - -Please ensure that you are using Docker version 20.10 or higher and Docker Compose 1.29 or higher and upgrade if -necessary. - -## Cygwin - -We will start up our services using a simple bash script. Windows users should download [cygwin](http://www.cygwin.com/) -to provide a command-line functionality similar to a Linux distribution on Windows. - -# Start Up - -Before you start you should ensure that you have obtained or built the necessary Docker images locally. Please clone the -repository and create the necessary images by running the commands as shown: +**NGSI-v2** offers JSON based interoperability used in individual Smart Systems. To run this tutorial with **NGSI-v2**, use the `NGSI-v2` branch. ```console -git clone https://github.com/FIWARE/tutorials.IoT-Agent.git -cd tutorials.IoT-Agent +git clone https://github.com/FIWARE/tutorials.Identity-Management.git +cd tutorials.Identity-Management git checkout NGSI-v2 ./services create -``` - -Thereafter, all services can be initialized from the command-line by running the -[services](https://github.com/FIWARE/tutorials.IoT-Agent/blob/NGSI-v2/services) Bash script provided within the -repository: - -```console ./services start ``` -> [!NOTE] -> If you want to clean up and start over again you can do so with the following command: -> -> ```console -> ./services stop -> ``` - -# Provisioning an IoT Agent - -To follow the tutorial correctly please ensure you have the device monitor page available in your browser and click on -the page to enable audio before you enter any cUrl commands. The device monitor displays the current state of an array -of dummy devices using Ultralight 2.0 syntax - -#### Device Monitor - -The device monitor can be found at: `http://localhost:3000/device/monitor` - -## Checking the IoT Agent Service Health - -You can check if the IoT Agent is running by making an HTTP request to the exposed port: - -#### 1️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/about' -``` - -The response will look similar to the following: - -```json -{ - "libVersion": "3.4.0", - "port": "4041", - "baseRoot": "/", - "version": "2.4.0" -} -``` - -> **What if I get a `Failed to connect to localhost port 4041: Connection refused` Response?** -> -> If you get a `Connection refused` response, the IoT Agent cannot be found where expected for this tutorial - you will -> need to substitute the URL and port in each cUrl command with the corrected IP address. All the cUrl commands tutorial -> assume that the IoT Agent is available on `localhost:4041`. -> -> Try the following remedies: -> -> - To check that the docker containers are running try the following: -> -> ```console -> docker ps -> ``` -> -> You should see four containers running. If the IoT Agent is not running, you can restart the containers as necessary. -> This command will also display open port information. -> -> - If you have installed [`docker-machine`](https://docs.docker.com/machine/) and -> [Virtual Box](https://www.virtualbox.org/), the context broker, IoT Agent and Dummy Device docker containers may -> be running from another IP address - you will need to retrieve the virtual host IP as shown: -> -> ```console -> curl -X GET \ -> 'http://$(docker-machine ip default):4041/version' -> ``` -> -> Alternatively run all your curl commands from within the container network: -> -> ```console -> docker run --network fiware_default --rm appropriate/curl -s \ -> -X GET 'http://iot-agent:4041/iot/about' -> ``` - -## Connecting IoT Devices - -The IoT Agent acts as a middleware between the IoT devices and the context broker. It therefore needs to be able to -create context data entities with unique IDs. Once a service has been provisioned and an unknown device makes a -measurement the IoT Agent add this to the context using the supplied `` (unless the device is recognized and -can be mapped to a known ID. - -There is no guarantee that every supplied IoT device `` will always be unique, therefore all provisioning -requests to the IoT Agent require two mandatory headers: - -- `fiware-service` header is defined so that entities for a given service can be held in a separate mongoDB database. -- `fiware-servicepath` can be used to differentiate between arrays of devices. - -For example within a smart city application you would expect different `fiware-service` headers for different -departments (e.g. parks, transport, refuse collection etc.) and each `fiware-servicepath` would refer to specific park -and so on. This would mean that data and devices for each service can be identified and separated as needed, but the -data would not be siloed - for example data from a **Smart Bin** within a park can be combined with the **GPS Unit** of -a refuse truck to alter the route of the truck in an efficient manner. - -The **Smart Bin** and **GPS Unit** are likely to come from different manufacturers and it cannot be guaranteed that -there is no overlap within ``s used. The use of the `fiware-service` and `fiware-servicepath` headers can -ensure that this is always the case, and allows the context broker to identify the original source of the context data. - -### Provisioning a Service Group - -Invoking group provision is always the first step in connecting devices since it is always necessary to supply an -authentication key with each measurement and the IoT Agent will not initially know which URL the context broker is -responding on. - -It is also possible to set up default commands and attributes for all anonymous devices as well, but this is not done -within this tutorial as we will be provisioning each device separately. - -This example provisions an anonymous group of devices. It tells the IoT Agent that a series of devices will be sending -messages to the `IOTA_HTTP_PORT` (where the IoT Agent is listening for **Northbound** communications) - -#### 2️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/services' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "services": [ - { - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "cbroker": "http://orion:1026", - "entity_type": "Thing", - "resource": "/iot/d" - } - ] -}' -``` - -In the example the IoT Agent is informed that the `/iot/d` endpoint will be used and that devices will authenticate -themselves by including the token `4jggokgpepnvsb2uv4s40d59ov`. For an UltraLight IoT Agent this means devices will be -sending GET or POST requests to: - -``` -http://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov -``` - -Which should be familiar UltraLight 2.0 syntax from the -[previous tutorial](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2). - -When a measurement from an IoT device is received on the resource URL it needs to be interpreted and passed to the -context broker. The `entity_type` attribute provides a default `type` for each device which has made a request (in this -case anonymous devices will be known as `Thing` entities. Furthermore the location of the context broker (`cbroker`) is -needed, so that the IoT Agent can pass on any measurements received to the correct location. `cbroker` is an optional -attribute - if it is not provided, the IoT Agent uses the context broker URL as defined in the configuration file, -however it has been included here for completeness. - -### Provisioning a Sensor - -It is common good practice to use URNs following the NGSI-LD -[specification](https://www.etsi.org/deliver/etsi_gs/CIM/001_099/009/01.08.01_60/gs_cim009v010801p.pdf) when creating -entities. Furthermore it is easier to understand meaningful names when defining data attributes. These mappings can be -defined by provisioning a device individually. - -Three types of measurement attributes can be provisioned: - -- `attributes` are active readings from the device -- `lazy` attributes are only sent on request - The IoT Agent will inform the device to return the measurement -- `static_attributes` are as the name suggests static data about the device (such as relationships) passed on to the - context broker. - -> [!NOTE] -> In the case where individual `id`s are not required, or aggregated data is sufficient the `attributes` can -> be defined within the provisioning service rather than individually. - -#### 3️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "motion001", - "entity_name": "urn:ngsi-ld:Motion:001", - "entity_type": "Motion", - "timezone": "Europe/Berlin", - "attributes": [ - { "object_id": "c", "name": "count", "type": "Integer" } - ], - "static_attributes": [ - { "name":"refStore", "type": "Relationship", "value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -In the request we are associating the device `motion001` with the URN `urn:ngsi-ld:Motion:001` and mapping the device -reading `c` with the context attribute `count` (which is defined as an `Integer`) A `refStore` is defined as a -`static_attribute`, placing the device within **Store** `urn:ngsi-ld:Store:001`. - -> Static attributes are useful as additional data on an entity to enable querying using the `q` parameter. For example -> the Smart Data Models [Device](https://github.com/smart-data-models/dataModel.Device/blob/master/Device/doc/spec.md) -> model defines attributes such as `category` or `controlledProperty` which enable queries to be made like: -> -> - _Which **Actuators** currently have a low `batteryLevel`?_ -> -> `/v2/entities?q=category=="actuator";batteryLevel<0.1` -> -> - _Which **Devices** measuring `fillingLevel` were installed before January 2020?_ -> -> `/v2/entities?q=controlledProperty=="fillingLevel";dateInstalled<"2020-01-25T00:00:00.000Z"` -> -> Obviously static data can be extended as necessary and can also include additional data such as a unique `name` or -> `serialNumber` for each device should the entity ID be too inflexible for queries. -> -> `/v2/entities?q=serialNumber=="XS403001-002"` -> -> Additionally devices with a fixed `location` static attribute can also be queried using the Geofencing parameters. -> -> `/v2/entities?georel=near;maxDistance:1500&geometry=point&coords=52.5162,13.3777` - -You can simulate a dummy IoT device measurement coming from the **Motion Sensor** device `motion001`, by making the -following request - -#### 4️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:7896/iot/d?k=4jggokgpepnvsb2uv4s40d59ov&i=motion001' \ - -H 'Content-Type: text/plain' \ - -d 'c|1' -``` - -A similar request was made in the previous tutorial (before the IoT Agent was connected) when the door was unlocked, you -will have seen the state of each motion sensor changing and a Northbound request will be logged in the device monitor. - -Now the IoT Agent is connected, the service group has defined the resource upon which the IoT Agent is listening -(`iot/d`) and the API key used to authenticate the request (`4jggokgpepnvsb2uv4s40d59ov`). Since both of these are -recognized, the measurement is valid. - -Because we have specifically provisioned the device (`motion001`) - the IoT Agent is able to map attributes before -raising a request with the Orion Context Broker. - -You can see that a measurement has been recorded, by retrieving the entity data from the context broker. Don't forget to -add the `fiware-service` and `fiware-service-path` headers. - -#### 5️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Motion:001?type=Motion' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### Response: - -```json -{ - "id": "urn:ngsi-ld:Motion:001", - "type": "Motion", - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.00Z", - "metadata": {} - }, - "count": { - "type": "Integer", - "value": "1", - "metadata": { - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.646Z" - } - } - }, - "refStore": { - "type": "Relationship", - "value": "urn:ngsi-ld:Store:001", - "metadata": { - "TimeInstant": { - "type": "ISO8601", - "value": "2018-05-25T10:51:32.646Z" - } - } - } -} -``` - -The response shows that the **Motion Sensor** device with `id=motion001` has been successfully identified by the IoT -Agent and mapped to the entity `id=urn:ngsi-ld:Motion:001`. This new entity has been created within the context data. -The `c` attribute from the dummy device measurement request has been mapped to the more meaningful `count` attribute -within the context. As you will notice, a `TimeInstant` attribute has been added to both the entity and the metadata of -the attribute - this represents the last time the entity and attribute have been updated, and is automatically added to -each new entity because the `IOTA_TIMESTAMP` environment variable was set when the IoT Agent was started up. The -`refStore` attribute comes from the `static_attributes` set when the device was provisioned. - -### Provisioning an Actuator via a Command - -Provisioning an actuator is similar to provisioning a sensor. This time an `endpoint` attribute holds the location where -the IoT Agent needs to send the UltraLight command and the `commands` array includes a list of each command that can be -invoked. The example below provisions a bell with the `deviceId=bell001`. The endpoint is -`http://iot-sensors:3001/iot/bell001` and it can accept the `ring` command. The `transport=HTTP` attribute defines the -communications protocol to be used. - -#### 6️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "bell001", - "entity_name": "urn:ngsi-ld:Bell:001", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell001", - "commands": [ - { "name": "ring", "type": "command" } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -### Provisioning an Actuator via a Bidirectional attribute - -An actuator can also be provisioned using a bidirectional attribute. Once again an `endpoint` attribute holds the -location where the IoT Agent needs to send the UltraLight command. The `ring` attribute is defined using an `expression` -and mapped to itself in the `reverse` direction. When an update to the `ring` attribute is received, it is also sent to -the device itself. Internally the difference is that this method relies on a subscription rather than a registration. - -> Note: This functionality has been removed in version 2.4.0 and higher. - -#### 7️⃣ Request: - -```console -curl -L -X POST 'http://localhost:4041/iot/devices' \ --H 'fiware-service: openiot' \ --H 'fiware-servicepath: /' \ --H 'Content-Type: application/json' \ ---data-raw '{ - "devices": [ - { - "device_id": "bell002", - "entity_name": "urn:ngsi-ld:Bell:002", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "attributes": [ - { - "name": "ring", - "type": "Text", - "expression": "ring", - "reverse": [ - { - "object_id": "ring", - "type": "Text", - "expression": "ring | toString()" - } - ] - } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:002"} - ] - } - ] -} -' -``` - -Before we wire-up the context broker, we can test that a command can be send to a device by making a REST request -directly to the IoT Agent's North Port using the `/v2/op/update` endpoint. It is this endpoint that will eventually be -invoked by the context broker once we have connected it up. - -To test the configuration you can run the command directly as shown: - -#### 8️⃣ Request: - -```console -curl -iX POST \ - http://localhost:4041/v2/op/update \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "actionType": "update", - "entities": [ - { - "type": "Bell", - "id": "urn:ngsi-ld:Bell:001", - "ring" : { - "type": "command", - "value": "" - } - } - ] -}' -``` - -If you are viewing the device monitor page, you can also see the state of the bell change. +| [![NGSI v2](https://img.shields.io/badge/NGSI-v2-5dc0cf.svg)](https://fiware-ges.github.io/orion/api/v2/stable/) | :books: [Documentation](https://github.com/FIWARE/tutorials.Identity-Management/tree/NGSI-LD) | [Postman Collection](https://fiware.github.io/tutorials.Identity-Management/) | +| --- | --- | --- | -![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif) -The result of the command to ring the bell can be read by querying the entity within the Orion Context Broker. +## NGSI-LD Smart Farm -#### 9️⃣ Request: +**NGSI-LD** offers JSON-LD based interoperability used for Federations and Data Spaces. To run this tutorial with **NGSI-LD**, use the `NGSI-LD` branch. ```console -curl -X GET \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001?type=Bell&options=keyValues' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### Response: - -```json -{ - "id": "urn:ngsi-ld:Bell:001", - "type": "Bell", - "TimeInstant": "2018-05-25T20:06:28.00Z", - "refStore": "urn:ngsi-ld:Store:001", - "ring_info": " ring OK", - "ring_status": "OK", - "ring": "" -} -``` - -The `TimeInstant` shows last the time any command associated with the entity has been invoked. The result of `ring` -command can be seen in the value of the `ring_info` attribute. - -### Provisioning a Smart Door - -Provisioning a device which offers both commands and measurements is merely a matter of making an HTTP POST request with -both `attributes` and `command` attributes in the body of the request. - -#### 1️⃣0️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "door001", - "entity_name": "urn:ngsi-ld:Door:001", - "entity_type": "Door", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/door001", - "commands": [ - {"name": "unlock","type": "command"}, - {"name": "open","type": "command"}, - {"name": "close","type": "command"}, - {"name": "lock","type": "command"} - ], - "attributes": [ - {"object_id": "s", "name": "state", "type":"Text"} - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -### Provisioning a Smart Lamp - -Similarly, a **Smart Lamp** with two commands (`on` and `off`) and two attributes can be provisioned as follows: - -#### 1️⃣1️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "lamp001", - "entity_name": "urn:ngsi-ld:Lamp:001", - "entity_type": "Lamp", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/lamp001", - "commands": [ - {"name": "on","type": "command"}, - {"name": "off","type": "command"} - ], - "attributes": [ - {"object_id": "s", "name": "state", "type":"Text"}, - {"object_id": "l", "name": "luminosity", "type":"Integer"} - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"} - ] - } - ] -} -' -``` - -The full list of provisioned devices can be obtained by making a GET request to the `/iot/devices` endpoint. - -#### 1️⃣2️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -## Enabling Context Broker Commands - -Having connected up the IoT Agent to the IoT devices, the Orion Context Broker was informed that the commands now are -available. In other words the IoT Agent registered itself as a -[Context Provider](https://github.com/FIWARE/tutorials.Context-Providers/) for the command attributes. - -Once the commands have been registered it will be possible to ring the **Bell**, open and close the **Smart Door** and -switch the **Smart Lamp** on and off by sending requests to the Orion Context Broker, rather than sending UltraLight 2.0 -requests directly the IoT devices as we did in the -[previous tutorial](https://github.com/FIWARE/tutorials.IoT-Sensors/tree/NGSI-v2) - -> [!NOTE] -> If the device is provisioned, but no data concerning the Entity is present in the context yet, the invocation must -> include the `type` of the Entity to succeed. However if the Entity `type` is already known -> to the broker, this hint -> is not necessary. This is because the registration is matched on both `id` and `type`. - -### Ringing the Bell - -To invoke the `ring` command, the `ring` attribute must be updated in the context. - -#### 1️⃣3️⃣ Request: - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Bell:001/attrs?type=Bell' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "ring": { - "type" : "command", - "value" : "" - } -}' -``` - -If you are viewing the device monitor page, you can also see the state of the bell change. - -![](https://fiware.github.io/tutorials.IoT-Agent/img/bell-ring.gif) - -### Opening the Smart Door - -To invoke the `open` command, the `open` attribute must be updated in the context. - -#### 1️⃣4️⃣ Request: - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Door:001/attrs?type=Door' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "open": { - "type" : "command", - "value" : "" - } -}' -``` - -### Switching on the Smart Lamp - -To switch on the **Smart Lamp**, the `on` attribute must be updated in the context. - -#### 1️⃣5️⃣ Request: - -```console -curl -iX PATCH \ - 'http://localhost:1026/v2/entities/urn:ngsi-ld:Lamp:001/attrs?type=Lamp' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "on": { - "type" : "command", - "value" : "" - } -}' -``` - -# Service Group CRUD Actions - -The **CRUD** operations for provisioning a service group map on to the expected HTTP verbs under the `/iot/services` -endpoint - -- **Create** - HTTP POST -- **Read** - HTTP GET -- **Update** - HTTP PUT -- **Delete** - HTTP DELETE - -Use the `resource` and `apikey` parameters to uniquely identify a service group. - -### Creating a Service Group - -This example provisions an anonymous group of devices. It tells the IoT Agent that a series of devices will be sending -messages to the `IOTA_HTTP_PORT` (where the IoT Agent is listening for **Northbound** communications) - -#### 1️⃣6️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/services' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "services": [ - { - "apikey": "12345", - "cbroker": "http://orion:1026", - "entity_type": "Thing", - "resource": "/iot/d" - } - ] -}' -``` - -### Read Service Group Details - -This example obtains the full details of a provisioned service with a given `resource` path. - -Service group details can be read by making a GET request to the `/iot/services` endpoint and providing a `resource` -parameter. - -#### 1️⃣7️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/services?resource=/iot/d' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` +git clone https://github.com/FIWARE/tutorials.Identity-Management.git +cd tutorials.Identity-Management +git checkout NGSI-LD -#### Response: - -```json -{ - "_id": "5b07b2c3d7eec57836ecfed4", - "subservice": "/", - "service": "openiot", - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "resource": "/iot/d", - "attributes": [], - "lazy": [], - "commands": [], - "entity_type": "Thing", - "internal_attributes": [], - "static_attributes": [] -} -``` - -The response includes all the defaults associated with each service group such as the `entity_type` and any default -commands or attribute mappings. - -### List all Service Groups - -This example lists all provisioned services by making a GET request to the `/iot/services` endpoint. - -#### 1️⃣8️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/services' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### Response: - -```json -{ - "_id": "5b07b2c3d7eec57836ecfed4", - "subservice": "/", - "service": "openiot", - "apikey": "4jggokgpepnvsb2uv4s40d59ov", - "resource": "/iot/d", - "attributes": [], - "lazy": [], - "commands": [], - "entity_type": "Thing", - "internal_attributes": [], - "static_attributes": [] -} -``` - -The response includes all the defaults associated with each service group such as the `entity_type` and any default -commands or attribute mappings. - -### Update a Service Group - -This example updates an existing service group with a given `resource` path and `apikey` - -Service group details can be updated by making a PUT request to the `/iot/services` endpoint and providing a `resource` -and `apikey` parameters. - -#### 1️⃣9️⃣ Request: - -```console -curl -iX PUT \ - 'http://localhost:4041/iot/services?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "entity_type": "IoT-Device" -}' -``` - -### Delete a Service Group - -This example removes a provisioned service group by making a DELETE request to the `/iot/services/` endpoint. - -It means that requests to `http://iot-agent:7896/iot/d?i=&k=4jggokgpepnvsb2uv4s40d59ov` (where the IoT Agent -is listening for **Northbound** communications) should no longer be processed by the IoT Agent. The `apiKey` and -`resource` parameters must be supplied in order to identify the service group to be deleted. - -#### 2️⃣0️⃣ Request: - -```console -curl -iX DELETE \ - 'http://localhost:4041/iot/services/?resource=/iot/d&apikey=4jggokgpepnvsb2uv4s40d59ov' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -# Device CRUD Actions - -The **CRUD** operations for provisioning individual devices map on to the expected HTTP verbs under the `/iot/devices` -endpoint - -- **Create** - HTTP POST -- **Read** - HTTP GET -- **Update** - HTTP PUT -- **Delete** - HTTP DELETE - -Use the `` to uniquely identify a device. - -### Creating a Provisioned Device - -This example provisions an individual device. It maps the `device_id=bell002` to the entity URN `urn:ngsi-ld:Bell:002` -and gives the entity a type `Bell`. The IoT Agent has been informed that the device offers a single `ring` `command` and -is listening on `http://iot-sensors:3001/iot/bell002` using HTTP. `attributes`, `lazy` attributes and -`static_attributes` can also be provisioned. - -#### 2️⃣1️⃣ Request: - -```console -curl -iX POST \ - 'http://localhost:4041/iot/devices' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "devices": [ - { - "device_id": "bell002", - "entity_name": "urn:ngsi-ld:Bell:002", - "entity_type": "Bell", - "protocol": "PDI-IoTA-UltraLight", - "transport": "HTTP", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "commands": [ - { - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - {"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:002"} - ] - } - ] -}' -``` - -### Read Provisioned Device Details - -This example obtains the full details of a provisioned device with a given `` path. - -Provisioned Device details can be read by making a GET request to the `/iot/devices/` endpoint. - -#### 2️⃣2️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### Response: - -The response includes all the commands and attributes mappings associated with the device. - -```json -{ - "device_id": "bell002", - "service": "openiot", - "service_path": "/", - "entity_name": "urn:ngsi", - "entity_type": "Bell", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "transport": "HTTP", - "attributes": [], - "lazy": [], - "commands": [ - { - "object_id": "ring", - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - { - "name": "refStore", - "type": "Relationship", - "value": "urn:ngsi-ld:Store:002" - } - ], - "protocol": "PDI-IoTA-UltraLight" -} -``` - -### List all Provisioned Devices - -This example lists all provisioned devices by making a GET request to the `/iot/devices` endpoint. - -#### 2️⃣3️⃣ Request: - -```console -curl -X GET \ - 'http://localhost:4041/iot/devices' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' -``` - -#### Response: - -The response includes all the commands and attributes mappings associated with all devices. - -```json -{ - "count": 5, - "devices": [ - { - "device_id": "bell002", - "service": "openiot", - "service_path": "/", - "entity_name": "urn:ngsi", - "entity_type": "Bell", - "endpoint": "http://iot-sensors:3001/iot/bell002", - "transport": "HTTP", - "attributes": [], - "lazy": [], - "commands": [ - { - "object_id": "ring", - "name": "ring", - "type": "command" - } - ], - "static_attributes": [ - { - "name": "refStore", - "type": "Relationship", - "value": "urn:ngsi-ld:Store:002" - } - ], - "protocol": "PDI-IoTA-UltraLight" - }, - etc... - ] -} -``` - -### Update a Provisioned Device - -This example updates an existing provisioned device by making a PUT request to the `/iot/devices/` endpoint. - -#### 2️⃣4️⃣ Request: - -```console -curl -iX PUT \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'Content-Type: application/json' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' \ - -d '{ - "entity_type": "IoT-Device" -}' -``` - -### Delete a Provisioned Device - -This example removes a provisioned device by making a DELETE request to the `/iot/devices/` endpoint. - -The device attributes will no longer be mapped and commands can no longer be sent to the device. If the device is making -active measurements, they will still be handled with default values if the associated service has not been deleted. - -#### 2️⃣5️⃣ Request: - -```console -curl -iX DELETE \ - 'http://localhost:4041/iot/devices/bell002' \ - -H 'fiware-service: openiot' \ - -H 'fiware-servicepath: /' +./services create +./services start ``` -# Next Steps +| [![NGSI LD](https://img.shields.io/badge/NGSI-LD-d6604d.svg)](https://www.etsi.org/deliver/etsi_gs/CIM/001_099/009/01.08.01_60/gs_cim009v010801p.pdf) | :books: [Documentation](https://github.com/FIWARE/tutorials.Identity-Management/tree/NGSI-LD) | [Postman Collection](https://fiware.github.io/tutorials.Identity-Management/ngsi-ld.html) | +| --- | --- | --- | -Want to learn how to add more complexity to your application by adding advanced features? You can find out by reading -the other [tutorials in this series](https://fiware-tutorials.rtfd.io) --- diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 2ef1612..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,143 +0,0 @@ -# WARNING: Do not deploy this tutorial configuration directly to a production environment -# -# The tutorial docker-compose files have not been written for production deployment and will not -# scale. A proper architecture has been sacrificed to keep the narrative focused on the learning -# goals, they are just used to deploy everything onto a single Docker machine. All FIWARE components -# are running at full debug and extra ports have been exposed to allow for direct calls to services. -# They also contain various obvious security flaws - passwords in plain text, no load balancing, -# no use of HTTPS and so on. -# -# This is all to avoid the need of multiple machines, generating certificates, encrypting secrets -# and so on, purely so that a single docker-compose file can be read as an example to build on, -# not use directly. -# -# When deploying to a production environment, please refer to the Helm Repository -# for FIWARE Components in order to scale up to a proper architecture: -# -# see: https://github.com/FIWARE/helm-charts/ -# -version: "3.8" -services: - # Orion is an NGSI-v2 context broker - orion-v2: - labels: - org.fiware: 'tutorial' - image: quay.io/fiware/orion:${ORION_VERSION} - hostname: orion - container_name: fiware-orion - depends_on: - - mongo-db - networks: - - default - expose: - - "${ORION_PORT}" - ports: - - "${ORION_PORT}:${ORION_PORT}" # localhost:1026 - command: -dbhost mongo-db -logLevel DEBUG - healthcheck: - test: curl --fail -s http://orion:${ORION_PORT}/version || exit 1 - interval: 5s - - # IoT-Agent is configured for the UltraLight Protocol - iot-agent: - labels: - org.fiware: 'tutorial' - image: quay.io/fiware/iotagent-ul:${ULTRALIGHT_VERSION} - hostname: iot-agent - container_name: fiware-iot-agent - depends_on: - - mongo-db - networks: - - default - expose: - - "${IOTA_NORTH_PORT}" - - "${IOTA_SOUTH_PORT}" - ports: - - "${IOTA_NORTH_PORT}:${IOTA_NORTH_PORT}" # localhost:4041 - - "${IOTA_SOUTH_PORT}:${IOTA_SOUTH_PORT}" # localhost:7896 - environment: - - IOTA_CB_HOST=orion # name of the context broker to update context - - IOTA_CB_PORT=${ORION_PORT} # port the context broker listens on to update context - - IOTA_NORTH_PORT=${IOTA_NORTH_PORT} - - IOTA_REGISTRY_TYPE=mongodb #Whether to hold IoT device info in memory or in a database - - IOTA_LOG_LEVEL=DEBUG # The log level of the IoT Agent - - IOTA_TIMESTAMP=true # Supply timestamp information with each measurement - - IOTA_CB_NGSI_VERSION=v2 # use NGSIv2 when sending updates for active attributes - - IOTA_AUTOCAST=true # Ensure Ultralight number values are read as numbers not strings - - IOTA_MONGO_HOST=mongo-db # The host name of MongoDB - - IOTA_MONGO_PORT=${MONGO_DB_PORT} # The port mongoDB is listening on - - IOTA_MONGO_DB=iotagentul # The name of the database used in mongoDB - - IOTA_HTTP_PORT=${IOTA_SOUTH_PORT} # The port used for device traffic over HTTP - - IOTA_PROVIDER_URL=http://iot-agent:${IOTA_NORTH_PORT} - - IOTA_DEFAULT_RESOURCE=/iot/d - healthcheck: - interval: 5s - - - # Tutorial acts as a series of dummy IoT Sensors over HTTP - tutorial: - labels: - org.fiware: 'tutorial' - image: quay.io/fiware/tutorials.context-provider - hostname: iot-sensors - container_name: fiware-tutorial - depends_on: - - orion-v2 - - iot-agent - networks: - default: - aliases: - - tutorial - - context-provider - expose: - - "${TUTORIAL_APP_PORT}" - - "${TUTORIAL_DUMMY_DEVICE_PORT}" - ports: - - "${TUTORIAL_APP_PORT}:${TUTORIAL_APP_PORT}" # localhost:3000 - - "${TUTORIAL_DUMMY_DEVICE_PORT}:${TUTORIAL_DUMMY_DEVICE_PORT}" # localhost:3001 - environment: - - "MONGO_URL=mongodb://mongo-db:27017" - - "DEBUG=tutorial:*" - - "WEB_APP_PORT=${TUTORIAL_APP_PORT}" # Port used by the content provider proxy and web-app for viewing data - - "IOTA_HTTP_HOST=iot-agent" - - "IOTA_HTTP_PORT=${IOTA_SOUTH_PORT}" - - "DUMMY_DEVICES_PORT=${TUTORIAL_DUMMY_DEVICE_PORT}" # Port used by the dummy IOT devices to receive commands - - "DUMMY_DEVICES_TRANSPORT=HTTP" # Default transport used by dummy Io devices - - "DUMMY_DEVICES_API_KEY=4jggokgpepnvsb2uv4s40d59ov" - - "CONTEXT_BROKER=http://orion:${ORION_PORT}/v2" # URL of the context broker to update context - - "OPENWEATHERMAP_KEY_ID=" - - "TWITTER_CONSUMER_KEY=" - - "TWITTER_CONSUMER_SECRET=" - # Database - mongo-db: - labels: - org.fiware: 'tutorial' - image: mongo:${MONGO_DB_VERSION} - hostname: mongo-db - container_name: db-mongo - expose: - - "${MONGO_DB_PORT}" - ports: - - "${MONGO_DB_PORT}:${MONGO_DB_PORT}" # localhost:27017 - networks: - - default - volumes: - - mongo-db:/data - healthcheck: - test: ["CMD","mongosh", "--eval", "db.adminCommand('ping')"] - interval: 5s - timeout: 5s - retries: 3 - start_period: 5s - - -networks: - default: - labels: - org.fiware: 'tutorial' - ipam: - config: - - subnet: 172.18.1.0/24 - -volumes: - mongo-db: ~ diff --git a/import-data b/import-data deleted file mode 100755 index 55fb35e..0000000 --- a/import-data +++ /dev/null @@ -1,427 +0,0 @@ -#!/bin/bash -# -# curl commands to reload the data from the previous tutorial -# -# - -set -e - -printf "⏳ Loading context data " - -# -# Create four Store Entities in various locations across Berlin -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -g -d '{ - "actionType": "append", - "entities": [ - { - "id":"urn:ngsi-ld:Store:001","type":"Store", - "address":{"type":"PostalAddress","value":{"streetAddress":"Bornholmer Straße 65","addressRegion":"Berlin","addressLocality":"Prenzlauer Berg","postalCode":"10439"}}, - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.3986,52.5547]}}, - "name":{"type":"Text","value":"Bösebrücke Einkauf"} - }, - { - "id":"urn:ngsi-ld:Store:002","type":"Store", - "address":{"type":"PostalAddress","value":{"streetAddress":"Friedrichstraße 44","addressRegion":"Berlin","addressLocality":"Kreuzberg","postalCode":"10969"}}, - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.3903,52.5075]}}, - "name":{"type":"Text","value":"Checkpoint Markt"}}, - { - "id":"urn:ngsi-ld:Store:003","type":"Store", - "address":{"type":"PostalAddress","value":{"streetAddress":"Mühlenstrasse 10","addressRegion":"Berlin","addressLocality":"Friedrichshain","postalCode":"10243"}}, - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4447,52.5031]}}, - "name":{"type":"Text","value":"East Side Galleria"} - }, - { - "id":"urn:ngsi-ld:Store:004","type":"Store", - "address":{"type":"PostalAddress","value":{"streetAddress":"Panoramastraße 1A","addressRegion":"Berlin","addressLocality":"Mitte","postalCode":"10178"}}, - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4094,52.5208]}}, - "name":{"type":"Text","value":"Tower Trödelmarkt"} - } - ] -}' - -# -# Add Weather and Twitter Responses for Store 1 using random values -# -curl -s -o /dev/null -X POST \ - http://orion:1026/v2/registrations \ - -H 'Content-Type: application/json' \ - -d '{ - "description": "Weather Conditions", - "dataProvided": { - "entities": [ - { - "id" : "urn:ngsi-ld:Store:001", - "type": "Store" - } - ], - "attrs": [ - "temperature", "relativeHumidity" - ] - }, - "provider": { - "http": { - "url": "http://context-provider:3000/proxy/v1/random/weatherConditions" - }, - "legacyForwarding": true - }, - "status": "active" -}' - -curl -s -o /dev/null -X POST \ - http://orion:1026/v2/registrations \ - -H 'Content-Type: application/json' \ - -d '{ - "description": "Tweeting Cat Facts", - "dataProvided": { - "entities": [ - { - "id" : "urn:ngsi-ld:Store:001", - "type": "Store" - } - ], - "attrs": [ - "tweets" - ] - }, - "provider": { - "http": { - "url": "http://context-provider:3000/proxy/v1/catfacts/tweets" - }, - "legacyForwarding": true - }, - "status": "active" -}' - - -# Add Weather and Twitter Responses for Store 2 using real sources -# -# curl -s -o /dev/null -X POST \ -# 'http://orion:1026/v2/registrations' \ -# -H 'Content-Type: application/json' \ -# -d '{ -# "description": "Store:002 - Real Temperature and Humidity", -# "dataProvided": { -# "entities": [ -# { -# "id": "urn:ngsi-ld:Store:002", -# "type": "Store" -# } -# ], -# "attrs": [ -# "temperature", -# "relativeHumidity" -# ] -# }, -# "provider": { -# "http": { -# "url": "http://context-provider:3000/proxy/weather/number/temperature:temp,relativeHumidity:humidity/berlin%2cde" -# }, -# "legacyForwarding": true -# } -# }' - -# curl -s -o /dev/null -X POST \ -# 'http://orion:1026/v2/registrations' \ -# -H 'Content-Type: application/json' \ -# -d '{ -# "description": "Store:002 Real Tweets", -# "dataProvided": { -# "entities": [ -# { -# "id": "urn:ngsi-ld:Store:002", -# "type": "Store" -# } -# ], -# "attrs": [ -# "tweets" -# ] -# }, -# "provider": { -# "http": { -# "url": "http://context-provider:3000/proxy/twitter/list/tweets:text/FIWARE" -# }, -# "legacyForwarding": true -# } -# }' - -# -# Create a series of Shelf Entities and place the in each Store. -# Each shelf is designed to hold one product. -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -g -d '{ - "actionType": "append", - "entities": [ - { - "id":"urn:ngsi-ld:Shelf:unit001","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.3986112,52.554699]}}, - "maxCapacity":{"type":"Integer","value":50}, - "name":{"type":"Text","value":"Corner Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit002","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.3987221,52.554664]}}, - "maxCapacity":{"type":"Integer","value":100}, - "name":{"type":"Text","value":"Wall Unit 1"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit003","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.3987221,52.554664]}}, - "maxCapacity":{"type":"Integer","value":100}, - "name":{"type":"Text","value":"Wall Unit 2"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit004","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.390311,52.507522]}}, - "maxCapacity":{"type":"Integer","value":50}, - "name":{"type":"Text","value":"Corner Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:002"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit005","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.390309,52.50751]}}, - "maxCapacity":{"type":"Integer","value":200}, - "name":{"type":"Text","value":"Long Wall Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:002"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit006","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4447112,52.503199]}}, - "maxCapacity":{"type":"Integer","value":50}, - "name":{"type":"Text","value":"Corner Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit007","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4447221,52.503164]}}, - "maxCapacity":{"type":"Integer","value":100}, - "name":{"type":"Text","value":"Wall Unit 1"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit008","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4447221,52.503164]}}, - "maxCapacity":{"type":"Integer","value":100}, - "name":{"type":"Text","value":"Wall Unit 2"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit009","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.444711,52.503122]}}, - "maxCapacity":{"type":"Integer","value":50}, - "name":{"type":"Text","value":"Corner Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"} - }, - { - "id":"urn:ngsi-ld:Shelf:unit010","type":"Shelf", - "location":{"type":"geo:json","value":{"type":"Point","coordinates":[13.4094111,52.5208028]}}, - "maxCapacity":{"type":"Integer","value":200}, - "name":{"type":"Text","value":"Long Wall Unit"}, - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:004"} - } - ] -}' - -# -# Create a series of Product Entities. -# These are a series of alcoholc and non-alcoholic drinks which are available to sell. -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -d '{ - "actionType":"APPEND", - "entities":[ - { - "id":"urn:ngsi-ld:Product:001", "type":"Product", - "name":{"type":"Text", "value":"Apples"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - }, - { - "id":"urn:ngsi-ld:Product:002", "type":"Product", - "name":{"type":"Text", "value":"Bananas"}, - "size":{"type":"Text", "value": "M"}, - "price":{"type":"Integer", "value": 1099} - }, - { - "id":"urn:ngsi-ld:Product:003", "type":"Product", - "name":{"type":"Text", "value":"Coconuts"}, - "size":{"type":"Text", "value": "M"}, - "price":{"type":"Integer", "value": 1499} - }, - { - "id":"urn:ngsi-ld:Product:004", "type":"Product", - "name":{"type":"Text", "value":"Melons"}, - "size":{"type":"Text", "value": "XL"}, - "price":{"type":"Integer", "value": 5000} - }, - { - "id":"urn:ngsi-ld:Product:005", "type":"Product", - "name":{"type":"Text", "value":"Kiwi Fruits"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - }, - { - "id":"urn:ngsi-ld:Product:006", "type":"Product", - "name":{"type":"Text", "value":"Strawberries"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - }, - { - "id":"urn:ngsi-ld:Product:007", "type":"Product", - "name":{"type":"Text", "value":"Raspberries"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - }, - { - "id":"urn:ngsi-ld:Product:008", "type":"Product", - "name":{"type":"Text", "value":"Pineapples"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - }, - { - "id":"urn:ngsi-ld:Product:009", "type":"Product", - "name":{"type":"Text", "value":"Oranges"}, - "size":{"type":"Text", "value": "S"}, - "price":{"type":"Integer", "value": 99} - } - ] -}' - - -# -# Create a series of InventoryItems Entities. -# These the drinks on order in Store:001 -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -d '{ - "actionType":"APPEND", - "entities":[ - { - "id":"urn:ngsi-ld:InventoryItem:001","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit001"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:001"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":15} - }, - { - "id":"urn:ngsi-ld:InventoryItem:002","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit002"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:003"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - }, - { - "id":"urn:ngsi-ld:InventoryItem:003","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:001"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit003"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:004"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - } - - ] -}' -# -# Create a series of InventoryItems Entities. -# These the drinks on order in Store:002 -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -d '{ - "actionType":"APPEND", - "entities":[ - { - "id":"urn:ngsi-ld:InventoryItem:004","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:002"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit004"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:001"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":15} - }, - { - "id":"urn:ngsi-ld:InventoryItem:005","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:002"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit005"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:002"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":15} - } - ] -}' -# -# Create a series of InventoryItems Entities. -# These the drinks on order in Store:003 -# Note that Shelf Unit009 is currently unused -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -d '{ - "actionType":"APPEND", - "entities":[ - { - "id":"urn:ngsi-ld:InventoryItem:006","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit006"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:001"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - }, - { - "id":"urn:ngsi-ld:InventoryItem:007","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit007"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:008"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - }, - { - "id":"urn:ngsi-ld:InventoryItem:008","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:003"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit008"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:009"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - } - - ] -}' -# -# Create a series of InventoryItems Entities. -# These the drinks on order in Store:004 -# -curl -s -o /dev/null -X POST \ - 'http://orion:1026/v2/op/update' \ - -H 'Content-Type: application/json' \ - -d '{ - "actionType":"APPEND", - "entities":[ - { - "id":"urn:ngsi-ld:InventoryItem:401","type":"InventoryItem", - "refStore":{"type":"Relationship","value":"urn:ngsi-ld:Store:004"}, - "refShelf":{"type":"Relationship","value":"urn:ngsi-ld:Shelf:unit010"}, - "refProduct":{"type":"Relationship","value":"urn:ngsi-ld:Product:001"}, - "stockCount":{"type":"Integer","value":10000}, - "shelfCount":{"type":"Integer","value":50} - } - - ] -}' - -echo -e " \033[1;32mdone\033[0m" diff --git a/services b/services index 12e202e..c744bc4 100755 --- a/services +++ b/services @@ -2,151 +2,8 @@ # # Command Line Interface to start all services associated with the Tutorial # -# For this tutorial the commands are merely a convenience script to run docker or docker-compose -# -# Each services script can be run using either docker-compose (the external tool with the hyphen -) -# or docker compose (the newer version directly bundled with Docker with a space ) -# -# if you start up with the following command: -# -# ./services start legacy -# -# This will force the script to use docker-compose which may be more reliable in -# some cases (or if an older version of Docker is being used) set -e -dockerCmd="docker compose" -if (( $# == 2 )); then - dockerCmd="docker-compose" -fi - -if (( $# < 1 )); then - echo "Illegal number of parameters" - echo "usage: services [create|start|stop]" - exit 1 -fi - -loadData () { - docker run --rm -v $(pwd)/import-data:/import-data \ - --network fiware_default \ - --entrypoint /bin/ash quay.io/curl/curl /import-data - waitForIoTAgent - echo "" -} - -stoppingContainers () { - CONTAINERS=$(docker ps --filter "label=org.fiware=tutorial" -aq) - if [[ -n $CONTAINERS ]]; then - echo "Stopping containers" - docker rm -f $CONTAINERS || true - fi - VOLUMES=$(docker volume ls -qf dangling=true) - if [[ -n $VOLUMES ]]; then - echo "Removing old volumes" - docker volume rm $VOLUMES || true - fi - NETWORKS=$(docker network ls --filter "label=org.fiware=tutorial" -q) - if [[ -n $NETWORKS ]]; then - echo "Removing tutorial networks" - docker network rm $NETWORKS || true - fi -} - -addDatabaseIndex () { - printf "Adding appropriate \033[1mMongoDB\033[0m indexes for \033[1;34mOrion\033[0m ..." - docker exec db-mongo mongosh --eval ' - conn = new Mongo();db.createCollection("orion"); - db = conn.getDB("orion"); - db.createCollection("entities"); - db.entities.createIndex({"_id.servicePath": 1, "_id.id": 1, "_id.type": 1}, {unique: true}); - db.entities.createIndex({"_id.type": 1}); - db.entities.createIndex({"_id.id": 1});' > /dev/null - - docker exec db-mongo mongosh --eval ' - conn = new Mongo();db.createCollection("orion-openiot"); - db = conn.getDB("orion-openiot"); - db.createCollection("entities"); - db.entities.createIndex({"_id.servicePath": 1, "_id.id": 1, "_id.type": 1}, {unique: true}); - db.entities.createIndex({"_id.type": 1}); - db.entities.createIndex({"_id.id": 1});' > /dev/null - echo -e " \033[1;32mdone\033[0m" - -} - -waitForMongo () { - echo -e "\n⏳ Waiting for \033[1mMongoDB\033[0m to be available\n" - while ! [ `docker inspect --format='{{.State.Health.Status}}' db-mongo` == "healthy" ] - do - sleep 1 - done -} - -waitForOrion () { - echo -e "\n⏳ Waiting for \033[1;34mOrion\033[0m to be available\n" - - while ! [ `docker inspect --format='{{.State.Health.Status}}' fiware-orion` == "healthy" ] - do - echo -e "Context Broker HTTP state: " `curl -s -o /dev/null -w %{http_code} 'http://localhost:1026/version'` " (waiting for 200)" - sleep 1 - done -} - - -waitForIoTAgent () { - echo -e "\n⏳ Waiting for \033[1;36mIoT-Agent\033[0m to be available\n" - while ! [ `docker inspect --format='{{.State.Health.Status}}' fiware-iot-agent` == "healthy" ] - - do - echo -e "IoT Agent HTTP state: " `curl -s -o /dev/null -w %{http_code} 'http://localhost:4041/version'` " (waiting for 200)" - sleep 1 - done -} - -displayServices () { - echo "" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" --filter name=fiware-* - (gp ports list 2> /dev/null) || true - echo "" -} - -command="$1" -case "${command}" in - "help") - echo "usage: services [create|start|stop]" - ;; - "start") - export $(cat .env | grep "#" -v) - stoppingContainers - echo -e "Starting containers: \033[1;34mOrion\033[0m, \033[1;36mIoT-Agent\033[0m, \033[1mTutorial\033[0m and a \033[1mMongoDB\033[0m database." - echo -e "- \033[1;34mOrion\033[0m is the context broker" - echo -e "- \033[1;36mIoT-Agent\033[0m is configured for the UltraLight Protocol" - echo -e "- \033[1mTutorial\033[0m acts as a series of dummy IoT Sensors over HTTP" - echo "" - ${dockerCmd} up -d --remove-orphans - waitForMongo - addDatabaseIndex - waitForOrion - loadData - displayServices - echo -e "Now open \033[4mhttp://localhost:3000/device/monitor\033[0m" - ;; - "stop") - export $(cat .env | grep "#" -v) - stoppingContainers - ;; - "create") - export $(cat .env | grep "#" -v) - echo "Pulling Docker images" - docker pull -q quay.io/curl/curl - ${dockerCmd} pull --ignore-pull-failures - ;; - *) - echo "Command not Found." - echo "usage: services [create|start|stop]" - exit 127; - ;; -esac - - - +echo -e "Checkout the \033[1;36mNGSI-v2\033[0m branch of this repository to run the Smart Supermarket tutorial.\n" +echo -e "Checkout the \033[1;31mNGSI-LD\033[0m branch of this repository to run the Smart Farm tutorial.\n"