{"info":{"_postman_id":"b240d096-0af8-44c3-9a5e-22fee62f49e7","name":"FIWARE Subscriptions","description":"<html><head></head><body><p>The tutorial builds on the entities and <a href=\"https://github.com/Fiware/tutorials.Subscriptions/tree/master/proxy\">Stock Management Frontend</a>\napplication created in the previous <a href=\"https://github.com/Fiware/tutorials.Accessing-Context/\">example</a> to enable users to understand\nthe <a href=\"https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json\">NGSI</a>\nSubscribe/Notify paradigm and how to use NGSI subscriptions within their own code.</p>\n<p>The <code>docker-compose</code> file for this tutorial can be found on GitHub: </p>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/icon/GitHub-Mark-32px.png\" alt=\"GitHub\"> <a href=\"https://github.com/Fiware/tutorials.Subscriptions\">FIWARE 106: Subscribing to Changes in Context</a></p>\n<h1 id=\"subscribing-to-changes-of-state\">Subscribing to Changes of State</h1>\n<blockquote>\n<p>\"Don't call us, we'll call you\"</p>\n<p>— Dorothy Kilgallen (The Voice Of Broadway)</p>\n</blockquote>\n<p>Within the FIWARE platform, an entity represents the state of a physical or conceptural object which exists in the real world. \nEvery smart solution needs to know the current state of these object at any given moment in time. </p>\n<p>The context of each of these entities is constantly changing. For example, within the stock management example, the context will\nchange as new stores open up, products are sold, prices change and so on. For a smart solution based on IoT sensor data, this issue\nis even more pressing as the system will constantly be reacting to changes in the real world.</p>\n<p>Until now all the operations we have used to change the state of the system have been <strong>synchronous</strong> - changes have been made by \ndirectly by a user or application and they have been informed of the result. The Orion Context Broker offers also an <strong>asynchronous</strong>\nnotification mechanism - applications can subscribe to changes of context information so that they can\nbe informed when something happens. This means the application does not need to continously poll or repeat query requests.</p>\n<p>Use of the subscription mechanism will therefore reduce both the volume of requests and amount of data being passed between components\nwithin the system. This reduction in network traffic will improve the overall responsiveness.</p>\n<h2 id=\"entities-within-a-stock-management-system\">Entities within a stock management system</h2>\n<p>The relationship between our entities is defined as shown:</p>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/entities.png\" alt=\"\"></p>\n<h2 id=\"stock-management-front-end\">Stock Management Front-End</h2>\n<p>In the previous <a href=\"https://github.com/Fiware/tutorials.Accessing-Context/\">tutorial</a>, a simple Node.js Express application was created.\nThis tutorial will use the monitor page to watch the status of recent requests, and a store page to buy products. Once the services\nare running these pages can be accessed from the following URLs:</p>\n<h4 id=\"event-montior\">Event Montior</h4>\n<p>The event monitor can be found at: <code>http://localhost:3000/app/monitor</code></p>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/monitor.png\" alt=\"FIWARE Monitor\"></p>\n<h4 id=\"store-002\">Store 002</h4>\n<p>Store002 can be found at: <code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></p>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/store2.png\" alt=\"Store\"></p>\n<h1 id=\"architecture\">Architecture</h1>\n<p>This application will make use of only one FIWARE component - the <a href=\"https://catalogue.fiware.org/enablers/publishsubscribe-context-broker-orion-context-broker\">Orion Context Broker</a>. Usage of the Orion Context Broker is sufficient for an application to qualify as <em>“Powered by FIWARE”</em>.</p>\n<p>Currently, the Orion Context Broker relies on open source <a href=\"https://www.mongodb.com/\">MongoDB</a> technology to keep\npersistence of the context data it holds. To request context data from external sources, a simple Context Provider NGSI \nproxy has also been added. To visualise and interact with the Context we will add a simple Express application </p>\n<p>Therefore, the architecture will consist of four elements:</p>\n<ul>\n<li>The Orion Context Broker server which will receive requests using <a href=\"https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json\">NGSI</a></li>\n<li>The underlying MongoDB database associated to the Orion Context Broker server</li>\n<li>The Context Provider NGSI proxy which will will:<ul>\n<li>receive requests using <a href=\"https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json\">NGSI</a></li>\n<li>makes requests to publicly available data sources using their own APIs in a proprietory format </li>\n<li>returns context data back to the Orion Context Broker in <a href=\"https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json\">NGSI</a> format.</li>\n</ul>\n</li>\n<li>The Stock Management Frontend which will will:<ul>\n<li>Display store information</li>\n<li>Show which products can be bought at each store</li>\n<li>Allow users to \"buy\" products and reduce the stock count.</li>\n</ul>\n</li>\n</ul>\n<p>Since all interactions between the elements are initiated by HTTP requests, the entities can be containerized and run\nfrom exposed ports. </p>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/architecture.png\" alt=\"\"></p>\n<p>The necessary configuration information can be seen in the services section of the associated <code>docker-compose.yml</code> file. It\nhas been described in a <a href=\"https://github.com/Fiware/tutorials.Context-Providers/\">previous tutorial</a></p>\n<h1 id=\"prerequisites\">Prerequisites</h1>\n<h2 id=\"docker\">Docker</h2>\n<p>To keep things simple both components will be run using <a href=\"https://www.docker.com\">Docker</a>. <strong>Docker</strong> is a container technology\nwhich allows to different components isolated into their respective environments. </p>\n<ul>\n<li>To install Docker on Windows follow the instructions <a href=\"https://docs.docker.com/docker-for-windows/\">here</a></li>\n<li>To install Docker on Mac follow the instructions <a href=\"https://docs.docker.com/docker-for-mac/\">here</a></li>\n<li>To install Docker on Linux follow the instructions <a href=\"https://docs.docker.com/install/\">here</a></li>\n</ul>\n<p><strong>Docker Compose</strong> is a tool for defining and running multi-container Docker applications. A \n<a href=\"https://raw.githubusercontent.com/Fiware/tutorials.Entity-Relationships/master/docker-compose.yml\">YAML file</a> is used\nconfigure the required services for the application. This means all container sevices can be brought up in a single \ncommmand. Docker Compose is installed by default  as part of Docker for Windows and  Docker for Mac, however Linux users \nwill need to follow the instructions found  <a href=\"https://docs.docker.com/compose/install/\">here</a></p>\n<h2 id=\"cygwin\">Cygwin</h2>\n<p>We will start up our services using a simple bash script. Windows users should download <a href=\"www.cygwin.com\">cygwin</a> to provide a\ncommand line functionality similar to a Linux distribution on Windows. </p>\n<h1 id=\"start-up\">Start Up</h1>\n<p>All services can be initialised from the command line by running the bash script provided within the repository:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">./services create; ./services start;\n</code></pre>\n<p>This command will also import seed data from the previous <a href=\"https://github.com/Fiware/tutorials.Context-Providers\">Stock Management example</a> on startup.</p>\n<blockquote>\n<p>:information_source: <strong>Note:</strong> If you want to clean up and start over again you can do so with the following command:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">./services stop\n</code></pre>\n</blockquote>\n<h1 id=\"using-subscriptions\">Using Subscriptions</h1>\n<p>To follow the tutorial correctly please ensure you have the follow pages available on tabs in your browser before you enter any cUrl commands.</p>\n<h4 id=\"event-monitor\">Event Monitor</h4>\n<p>The event monitor can be found at: <code>http://localhost:3000/app/monitor</code></p>\n<h4 id=\"stores\">Stores</h4>\n<p>The stores can be found at:</p>\n<ul>\n<li>Store 1 -  <code>http://localhost:3000/app/store/urn:ngsi-ld:Store:001</code></li>\n<li>Store 2 -  <code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></li>\n</ul>\n<h2 id=\"setting-up-a-simple-subscription\">Setting up a simple Subscription</h2>\n<p>Within the stock management example, imagine that the regional manager of the company wants to alter the price of a product. \nThe new price should immediately be reflected at the till in all stores within the system. It would be possible to set up the\nsystem so that it was constantly polling for new information, however prices are not changed very frequently so this would be\na waste of resources and create a lot of unnecessary data traffic.</p>\n<p>The alternative is to create a subscription which will POST a payload to a \"well-known\" URL whenever a price has changed. \nA new subscription can be added by making a POST request to the <code>/v2/subscriptions/</code> endpoint as shown below:</p>\n<h4 id=\"request\">Request:</h4>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">curl --request POST \\\n  --url 'http://localhost:1026/v2/subscriptions/' \\\n  --header 'content-type: application/json' \\\n  --data '{\n  \"description\": \"Notify me of all product price changes\",\n  \"subject\": {\n    \"entities\": [{\"idPattern\": \".*\", \"type\": \"Product\"}],\n    \"condition\": { \n      \"attrs\": [ \"price\" ]\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/price-change\"\n    }\n  }\n}'\n</code></pre>\n<p>The body of the POST request consists of two parts, the <code>subject</code> section of the request (consisting of <code>entities</code> and <code>conditions</code>)states that the subscription will be fired whenever the <code>price</code> attribute of any <strong>Product</strong> entity is altered. The notification section of the body states that once the conditions of the subscription have been met, a POST request containing all affected <strong>Product</strong> entities will be sent to the URL <code>http://context-provider:3000/subscription/price-change</code> which is handled by the stock management front-end application.</p>\n<p>For a first run, when the subscription is created, the Orion Context Broker runs the <code>condition</code> test, and since it has not been run before makes the assumption that all products have been changed. Therefore a request is sent to <code>subscription/price-change</code> immediately as shown:</p>\n<h4 id=\"httplocalhost3000appmonitor\"><code>http://localhost:3000/app/monitor</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/products-subscription.png\" alt=\"\"></p>\n<p>Code within the Stock Management Front-End application handles received the POST request as shown:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">router.post('/subscription/:type', (req, res) =&gt; {\n    _.forEach(req.body.data, item =&gt; {\n        broadcastEvents(req, item, ['refStore', 'refProduct', 'refShelf', 'type']);\n    });\n    res.status(204).send();\n});\n\nfunction broadcastEvents(req, item, types) {\n    const message = req.params.type + ' received';\n    _.forEach(types, type =&gt; {\n        if (item[type]) {\n            req.app.get('io').emit(item[type], message);\n        }\n    });\n}\n</code></pre>\n<p>This business logic emits socket io events to any registered parties (such as the cash till)</p>\n<p>The cash till has been set to reload if is receives an event - however in this case the prices have not changed yet, so the product prices\nremain the same - for example a bottle of beer remains at 0.99€</p>\n<h4 id=\"httplocalhost3000appstoreurnngsi-ldstore002\"><code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/beer-99.png\" alt=\"\"></p>\n<p>Let's reduce the price of a bottle of beer to 0.89€. This can't be done programmatically yet, so it has to be done with a curl command\nas shown:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">curl --request PUT \\\n  --url 'http://localhost:1026/v2/entities/urn:ngsi-ld:Product:001/attrs/price/value' \\\n  --header 'Content-Type: text/plain' \\\n  --data 89\n</code></pre>\n<p>Whenever an attribute of the <strong>Product</strong> entity is updated, the Orion Context Broker checks for any existing subscriptions \n(which exist for that entity) and  applies the <code>condition</code> test. This time only one <strong>Product</strong> entity has changed since the last run therefore a POST request is sent to <code>subscription/price-change</code> - which only contains one <strong>Product</strong> in the body:</p>\n<h4 id=\"httplocalhost3000appmonitor-1\"><code>http://localhost:3000/app/monitor</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/price-change.png\" alt=\"\"></p>\n<p>The business logic of the Stock Management Front End again emits socket io events to any registered parties (such as the cash till)\nand since the price has changed the till now displays a bottle of beer at 0.89€</p>\n<h4 id=\"httplocalhost3000appstoreurnngsi-ldstore002-1\"><code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/beer-89.png\" alt=\"\">   </p>\n<h2 id=\"reducing-payload-with--attrs-and-attrsformat\">Reducing Payload with  <code>attrs</code> and <code>attrsFormat</code></h2>\n<p>With the previous example the full verbose data from each affected <strong>Product</strong> entity was sent with the POST notification.\nThis is not very efficient. </p>\n<p>The amount of data to passed can be reduced by adding an <code>attrs</code> attribute which will specify a list of attributes to be \nincluded in notification messages - other attributes are ignored</p>\n<blockquote>\n<p><strong>Tip</strong> an <code>exceptAttrs</code> attribute also exists to return all attributes except for those on the exclude list.\n<code>attrs</code> and <code>exceptAttrs</code> cannot be used simualtaneously in the same subscription</p>\n</blockquote>\n<p>The <code>attrsFormat</code> attribute specifies how the entities are represented in notifications. A verbose response is returned by \ndefault <code>keyValues</code> and <code>values</code> work in the same manner as a <code>v2/entities</code> GET request.</p>\n<h2 id=\"reducing-scope-with--expression\">Reducing Scope with  <code>expression</code></h2>\n<p>Lets create two more subscriptions which will only fire under specific conditions - and will only return key-value pairs for\nthe entity affected. Imagine that the warehouse of each store now wants to be informed whenever the amount of product on the \nshelf falls below a threshold level. </p>\n<p>The subscription is tested whenever the <code>shelfCount</code> of an <strong>InventoryItem</strong> is updated, however the addition of an <code>expression</code> \nattribute will mean that the subscription will only fire if the expression returns valid data - for example\n<code>\"q\": \"shelfCount&lt;10;refStore==urn:ngsi-ld:Store:001</code> tests that the <code>shelfCount</code> is below ten and that the item is in store 001.\nThis means that we can set up out business logic so that other stores wont be bothered by notifications.</p>\n<h4 id=\"request-1\">Request:</h4>\n<p>The following command is a low stock notification for Store 001</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">curl --request POST \\\n  --url 'http://localhost:1026/v2/subscriptions' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"description\": \"Notify me of low stock in Store 001\",\n  \"subject\": {\n    \"entities\": [{\"idPattern\": \".*\",\"type\": \"InventoryItem\"}],\n    \"condition\": {\n      \"attrs\": [\"shelfCount\"],\n      \"expression\": {\"q\": \"shelfCount&lt;10;refStore==urn:ngsi-ld:Store:001\"}\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/low-stock-store001\"\n    },\n    \"attrsFormat\" : \"keyValues\"\n  }\n}'\n</code></pre>\n<h4 id=\"request-2\">Request:</h4>\n<p>The following command is a low stock notification for Store 002</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">curl --request POST \\\n  --url 'http://localhost:1026/v2/subscriptions' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\n  \"description\": \"Notify me of low stock in Store 002\",\n  \"subject\": {\n    \"entities\": [{\"idPattern\": \".*\", \"type\": \"InventoryItem\"}],\n    \"condition\": {\n      \"attrs\": [\"shelfCount\"],\n      \"expression\": {\"q\": \"shelfCount&lt;10;refStore==urn:ngsi-ld:Store:002\"}\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/low-stock-store002\"\n    },\n    \"attrsFormat\" : \"keyValues\"\n  }\n}'\n</code></pre>\n<p>The two requests are very similiar. It is merely the <code>url</code> and the <code>expresssion</code> attributes which differ. The first cUrl command\nwill only fire if the affected <strong>InventoryItem</strong> entity has a reference to Store 001 and the second one if the affected\n<strong>InventoryItem</strong> entity has a reference to Store 001. Obviously the URLs must be different so that the business logic of our\napplication is able to react diffferently to each request.</p>\n<blockquote>\n<p><strong>Tip</strong>: You can set stock levels directly by making a PUT request as shown:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-console\">curl --request PUT \\\n --url 'http://localhost:1026/v2/entities/urn:ngsi-ld:InventoryItem:005/attrs/shelfCount/value' \\\n --header 'Content-Type: text/plain' \\\n --data 5\n</code></pre>\n</blockquote>\n<p>If you now buy items from Store 002, once an <strong>InventoryItem</strong> dips below ten items the following occurs</p>\n<h4 id=\"httplocalhost3000appmonitor-2\"><code>http://localhost:3000/app/monitor</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/low-stock-monitor.png\" alt=\"\"></p>\n<p>As you can see the key value pairs of the affected  <strong>InventoryItem</strong>  have been passed to the Stock Managment Front End.</p>\n<p>If you look at the store itself:</p>\n<h4 id=\"httplocalhost3000appstoreurnngsi-ldstore002-2\"><code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></h4>\n<p><img src=\"https://fiware.github.io/tutorials.Subscriptions/img/low-stock-warehouse.png\" alt=\"\"></p>\n<p>An alert has been raised by the business logic within the application.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[{"content":"Subscribing to Changes of State","slug":"subscribing-to-changes-of-state"},{"content":"Architecture","slug":"architecture"},{"content":"Prerequisites","slug":"prerequisites"},{"content":"Start Up","slug":"start-up"},{"content":"Using Subscriptions","slug":"using-subscriptions"}],"owner":"513743","collectionId":"b240d096-0af8-44c3-9a5e-22fee62f49e7","publishedId":"RW1dHeTR","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"4C4C4C","highlight":"233C68"},"publishDate":"2018-05-31T10:56:35.000Z"},"item":[{"name":"Subscription Actions","item":[{"name":"Create a Subscription (Product)","id":"bc935401-10bf-45d6-89aa-4dfd69e7fbdb","request":{"method":"POST","header":[{"key":"content-type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"description\": \"Notify me of all product price changes\",\n  \"subject\": {\n    \"entities\": [\n      {\n        \"idPattern\": \".*\", \"type\": \"Product\"\n      }\n    ],\n     \"condition\": {\n      \"attrs\": [ \"price\" ]\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/price-change\"\n    }\n  }\n}"},"url":"http://localhost:1026/v2/subscriptions/","description":"<p>This example creates a new subscription. The subscription will fire an asynchronous notification to a URL\nwhenever the context is changed and the conditions of the subscription - <em>Any Changes to Product prices</em> - are met.</p>\n<p>New subscriptions can be added by making a POST request to the <code>/v2/subscriptions/</code> endpoint.</p>\n<p>The <code>subject</code> section of the request states that the subscription will be fired whenever the <code>price</code> attribute of\nany <strong>Product</strong> entity is altered.</p>\n<p>The <code>notification</code> section of the body states that a POST request containing all affected entities will\nbe sent to the <code>http://context-provider:3000/subscription/price-change</code> endpoint.</p>\n<p>Subscription ids are auto-generated when the subscription is created and returned in the header of the response.</p>\n<hr />\n<p>Subsequent requests will create duplicate subscriptions</p>\n","urlObject":{"protocol":"http","path":["v2","subscriptions",""],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"bc935401-10bf-45d6-89aa-4dfd69e7fbdb"},{"name":"Delete a Subscription","id":"e3292a9d-4405-4046-911c-fefbdb5fbd30","request":{"method":"DELETE","header":[],"body":{"mode":"raw","raw":""},"url":"http://localhost:1026:1026/v2/subscriptions/5c90c0c041df0cb69e62704c","description":"<p>This example deletes the Subscription with <code>id=5ae079b86e4f353c5163c939</code> from the context.</p>\n<p>Subscriptions can be deleted by making a DELETE request to the <code>/v2/subscriptions/&lt;subscription-id&gt;</code> endpoint.</p>\n<p>The Subscription id had been auto-generated when the subscription was created.</p>\n<hr />\n<p>Subsequent requests using the same <code>id</code> will result in an error response since the subscription no longer exists</p>\n","urlObject":{"protocol":"http","port":"1026","path":["v2","subscriptions","5c90c0c041df0cb69e62704c"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"e3292a9d-4405-4046-911c-fefbdb5fbd30"},{"name":"Amend an Existing Subscription","id":"d1b01fe3-e61f-4111-8440-e594e1651096","request":{"method":"PATCH","header":[{"key":"content-type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n    \"status\": \"active\",\n    \"notification\": {\n        \"http\": {\n            \"url\": \"http://context-provider:3000/notify/price-change\"\n        }\n    }\n}"},"url":"http://{{host}}:1026/v2/subscriptions/5ae07c7e6e4f353c5163c93e","description":"<p>This example amends an existing subscription with the id <code>5ae07c7e6e4f353c5163c93e</code> and updates the <code>notification</code> URL.</p>\n<p>Subscriptions can be updated making a PATCH request to the <code>/v2/subscriptions/&lt;subscription-id&gt;</code> endpoint.</p>\n<p>The Subscription id had been auto-generated when the subscription was created.</p>\n","urlObject":{"protocol":"http","port":"1026","path":["v2","subscriptions","5ae07c7e6e4f353c5163c93e"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"d1b01fe3-e61f-4111-8440-e594e1651096"},{"name":"List all Subscriptions","id":"9d2cda75-2cb7-4868-acf5-6ff8c7bb269e","request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"subject\": {\n        \"entities\": [{\n          \"id\": \"\"  \n        }],\n        \"condition\": {\n            \"attrs\": [\"capacity\"]\n        }\n    },\n    \"notification\": {\n        \"http\": {\n            \"url\": \"http://localhost:8000\"\n        }\n    }\n}"},"url":"http://localhost:1026/v2/subscriptions/","description":"<p>This example lists all subscriptions by making a GET request to the <code>/v2/subscriptions/</code> endpoint.</p>\n<p>The <code>notification</code> section of each subscription will also include the last time the conditios of the subscription\nwere met, and whether associated the POST action was successful.</p>\n","urlObject":{"protocol":"http","path":["v2","subscriptions",""],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"9d2cda75-2cb7-4868-acf5-6ff8c7bb269e"},{"name":"Read the detail of a Subscription","id":"7f872cf8-e6a7-409b-97b3-a5d5ef689eb6","request":{"method":"GET","header":[],"body":{"mode":"raw","raw":"{\n    \"subject\": {\n        \"entities\": [{\n          \"id\": \"\"  \n        }],\n        \"condition\": {\n            \"attrs\": [\"capacity\"]\n        }\n    },\n    \"notification\": {\n        \"http\": {\n            \"url\": \"http://localhost:8000\"\n        }\n    }\n}"},"url":"http://localhost:1026/v2/subscriptions/5aead3361587e1918de90aba","description":"<p>This example obtains the full details of a subscription with a given id.</p>\n<p>The response includes additional details in the <code>notification</code> section showing \nthe last time the conditions of the subscription were met, and whether associated the POST \naction was successful.</p>\n<p>Subscription details can be read by making a GET request to the <code>/v2/subscriptions/&lt;subscription-id&gt;</code> endpoint.</p>\n<p>The Subscription id had been auto-generated when the subscription was created.</p>\n","urlObject":{"protocol":"http","path":["v2","subscriptions","5aead3361587e1918de90aba"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"7f872cf8-e6a7-409b-97b3-a5d5ef689eb6"},{"name":"Create a Subscription ( Store 1) - Low Stock","id":"c4525080-603c-44ac-a1d7-b351e3101a36","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"description\": \"Notify me of low stock in Store 001\",\n  \"subject\": {\n    \"entities\": [\n      {\n        \"idPattern\": \".*\",\n        \"type\": \"InventoryItem\"\n      }\n    ],\n     \"condition\": {\n      \"attrs\": [\n        \"shelfCount\"\n      ],\n      \"expression\": {\n        \"q\": \"shelfCount<10;refStore==urn:ngsi-ld:Store:001\"\n      }\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/low-stock-store001\"\n    },\n    \"attrsFormat\" : \"keyValues\"\n  }\n}"},"url":"http://localhost:1026/v2/subscriptions","description":"<p>This example creates a new subscription which will only fire under specific conditions - \n<em>low stock for Store 001</em> - and will only return key-value pairs\nfor the entity affected. The subscription will fire an asynchronous notification to a URL\nwhenever the context is changed and only when all of the conditions of the subscription are met.</p>\n<p>New subscriptions can be added by making a POST request to the <code>/v2/subscriptions/</code> endpoint.</p>\n<ul>\n<li>The <code>subject</code> section of the request states that the subscription will be checked whenever the <code>shelfCount</code> attribute of\nany <strong>InventoryItem</strong> entity is altered.</li>\n<li>The <code>expression</code> section of the request states that the subscription will only fire if the <code>shelfCount</code> is below 10 items\nand the <strong>InventoryItem</strong> entity belongs to <code>Store:001</code></li>\n<li>The <code>notification</code> section of the body states that a POST request containing all affected entities will\nbe sent to the <code>http://context-provider:3000/subscription/low-stock-store001</code> endpoint. . The <code>attrsFormat</code> attribute informs\nthe context broker to only send key-value pairs</li>\n</ul>\n<hr />\n<p>Subsequent requests will create duplicate subscriptions</p>\n","urlObject":{"protocol":"http","path":["v2","subscriptions"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"c4525080-603c-44ac-a1d7-b351e3101a36"},{"name":"Create a Subscription ( Store 2) - Low Stock","id":"7a0f67d5-d975-4f9a-8c69-42eb850f4a1f","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"description\": \"Notify me of low stock in Store 002\",\n  \"subject\": {\n    \"entities\": [\n      {\n        \"idPattern\": \".*\",\n        \"type\": \"InventoryItem\"\n      }\n    ],\n     \"condition\": {\n      \"attrs\": [\n        \"shelfCount\"\n      ],\n      \"expression\": {\n        \"q\": \"shelfCount<10;refStore==urn:ngsi-ld:Store:002\"\n      }\n    }\n  },\n  \"notification\": {\n    \"http\": {\n      \"url\": \"http://context-provider:3000/subscription/low-stock-store002\"\n    },\n    \"attrsFormat\" : \"keyValues\"\n  }\n}"},"url":"http://localhost:1026/v2/subscriptions","description":"<p>This example creates a new subscription which will only fire under specific conditions - <em>low stock for Store 002</em> -  and will only return \nkey-value pairs for the entity affected. The subscription will fire an asynchronous notification to a URL\nwhenever the context is changed and only when all of the conditions of the subscription are met.</p>\n<p>New subscriptions can be added by making a POST request to the <code>/v2/subscriptions/</code> endpoint.</p>\n<ul>\n<li>The <code>subject</code> section of the request states that the subscription will be checked whenever the <code>shelfCount</code> attribute of\nany <strong>InventoryItem</strong> entity is altered.</li>\n<li>The <code>expression</code> section of the request states that the subscription will only fire if the <code>shelfCount</code> is below 10 items\nand the <strong>InventoryItem</strong> entity belongs to <code>Store:002</code></li>\n<li>The <code>notification</code> section of the body states that a POST request containing all affected entities will\nbe sent to the <code>http://context-provider:3000/subscription/low-stock-store002</code> endpoint. The <code>attrsFormat</code> attribute informs\nthe context broker to only send key-value pairs</li>\n</ul>\n<hr />\n<p>Subsequent requests will create duplicate subscriptions</p>\n","urlObject":{"protocol":"http","path":["v2","subscriptions"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"7a0f67d5-d975-4f9a-8c69-42eb850f4a1f"}],"id":"89da7ed6-4c05-4360-810b-a80e7ee213aa","description":"<p>A subscription notifies another service by making a POST request to a specified URL when the conditions of the subscription have been met.</p>\n<p>The <strong>CRUD</strong> operations for subscriptions map on to the expected HTTP verbs under the <code>/v2/subscriptions/</code> endpoint.</p>\n<ul>\n<li><strong>Create</strong> - HTTP POST</li>\n<li><strong>Read</strong> - HTTP GET</li>\n<li><strong>Update</strong> - HTTP PATCH</li>\n<li><strong>Delete</strong> - HTTP DELETE</li>\n</ul>\n<p>The <code>&lt;subscription-id&gt;</code> is auto generated when the subscription is created and returned in Header\nof the POST response to be used by the other operation thereafter.</p>\n","event":[{"listen":"prerequest","script":{"id":"d605e1da-1bc2-4e19-9f42-2a9efe1ec34f","type":"text/javascript","exec":[""]}},{"listen":"test","script":{"id":"3ed79691-91f2-49f5-8dd0-7af009166ae9","type":"text/javascript","exec":[""]}}],"_postman_id":"89da7ed6-4c05-4360-810b-a80e7ee213aa"},{"name":"Amending Context Data","item":[{"name":"Amend the price of a product","id":"32a891d8-3a62-4e07-a879-01aa924f2776","request":{"method":"PUT","header":[{"key":"Content-Type","value":"text/plain"}],"body":{"mode":"raw","raw":"89"},"url":"http://localhost:1026/v2/entities/urn:ngsi-ld:Product:001/attrs/price/value","description":"<p>This example reduces the price of a can of  Beer to 0.89 €.</p>\n<p>It updates the value of the <code>price</code> attribute of the Entity with <code>id=urn:ngsi-ld:Product:001</code></p>\n<p>Exisiting attribute values can be altered by making a PUT request to the <code>/v2/entities/&lt;entity&gt;/attrs/&lt;attribute&gt;/value</code> endpoint.</p>\n","urlObject":{"protocol":"http","path":["v2","entities","urn:ngsi-ld:Product:001","attrs","price","value"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"32a891d8-3a62-4e07-a879-01aa924f2776"},{"name":"Reduce the Shelf count","id":"d88c8106-93e1-41ec-96a0-9a3cd1afa2e5","request":{"method":"PUT","header":[{"key":"Content-Type","value":"text/plain"}],"body":{"mode":"raw","raw":"5"},"url":"http://localhost:1026/v2/entities/urn:ngsi-ld:InventoryItem:005/attrs/shelfCount/value","description":"<p>This example reduces the number of beer cans left on sale in <strong>Checkpoint Markt</strong>\n(<code>store:002</code>) down to 5. If a subscription has been set up, a warning will be sent to the warehouse. </p>\n<p>The value of the <code>shelfCount</code> attribute of the Entity with <code>id=urn:ngsi-ld:InventoryItem:005</code>can be \naltered by making a PUT request to the <code>/v2/entities/&lt;entity&gt;/attrs/&lt;attribute&gt;/value</code> endpoint.</p>\n","urlObject":{"protocol":"http","path":["v2","entities","urn:ngsi-ld:InventoryItem:005","attrs","shelfCount","value"],"host":["localhost:1026"],"query":[],"variable":[]}},"response":[],"_postman_id":"d88c8106-93e1-41ec-96a0-9a3cd1afa2e5"}],"id":"05a01e12-959a-45dd-a136-8d2ede80c655","description":"<p>The tutorial assumes that users will buy the products from the web app,\nhowever Postman commands are also provided for convenience.</p>\n<ul>\n<li><code>http://localhost:3000/app/monitor</code></li>\n<li><code>http://localhost:3000/app/store/urn:ngsi-ld:Store:002</code></li>\n</ul>\n","event":[{"listen":"prerequest","script":{"id":"c43b57f2-84cc-4d57-8c6d-5b4260399699","type":"text/javascript","exec":[""]}},{"listen":"test","script":{"id":"cc26f7d9-301c-48e2-891f-3c336c18fe96","type":"text/javascript","exec":[""]}}],"_postman_id":"05a01e12-959a-45dd-a136-8d2ede80c655"}],"event":[{"listen":"prerequest","script":{"id":"a25c858c-0646-4514-85e8-f6f9aeafc5be","type":"text/javascript","exec":[""]}},{"listen":"test","script":{"id":"f81ca278-51ac-41c1-a4e6-66baed8434f2","type":"text/javascript","exec":[""]}}],"variable":[{"key":"orion","value":"localhost:1026","type":"string"}]}