diff --git a/.textlintrc b/.textlintrc new file mode 100644 index 00000000..92d6c0cc --- /dev/null +++ b/.textlintrc @@ -0,0 +1,198 @@ +{ + "rules": { + "terminology": { + "defaultTerms": false, + "terms": [ + // Brands + "Airbnb", + "Android", + "AppleScript", + "AppVeyor", + "AVA", + "BrowserStack", + "Browsersync", + "Codecov", + "CodePen", + "CodeSandbox", + "DefinitelyTyped", + "EditorConfig", + "ESLint", + "FIWARE", + "GitHub", + "GraphQL", + "iOS", + "JavaScript", + "JetBrains", + "jQuery", + "LinkedIn", + "Lodash", + "MacBook", + "Markdown", + "OpenType", + "PayPal", + "PhpStorm", + "RubyMine", + "Sass", + "SemVer", + "TypeScript", + "UglifyJS", + "WebStorm", + "WordPress", + "YouTube", + ["JSDocs?", "JSDoc"], +// ["Node(?:js)?", "Node.js"], + ["React[ .]js", "React"], + ["SauceLabs", "Sauce Labs"], + ["StackOverflow", "Stack Overflow"], + ["styled ?components", "styled-components"], + ["HTTP[ /]2(?:\\.0)?", "HTTP/2"], + ["OS X", "macOS"], + ["Mac ?OS", "macOS"], + ["a npm", "an npm"], + + // ECMAScript + "ECMAScript", + ["ES2015", "ES6"], + ["ES7", "ES2016"], + + // Abbreviations + "3D", + ["3-D", "3D"], + "Ajax", + "API", + ["API['’]?s", "APIs"], + "CSS", + "GIF", + "HTML", + "HTTPS", + "IoT", + "I/O", + ["I-O", "I/O"], + "JPEG", + "MIME", + ["NGSIv2", "NGSI v2"], + "OK", + "PaaS", + "PDF", + "PNG", + "SaaS", + "URL", + ["URL['’]?s", "URLs"], + ["an URL", "a URL"], + ["wi[- ]?fi", "Wi-Fi"], + + // Names + "McKenzie", + "McConnell", + + // Words and phrases + "ID", // http://stackoverflow.com/questions/1151338/id-or-id-on-user-interface + ["id['’]?s", "IDs"], + ["backwards compatible", "backward compatible"], + ["build system(s?)", "build tool$1"], + ["CLI tool(s?)", "command-line tool$1"], + ["he or she", "they"], + ["he/she", "they"], + ["\\(s\\)he", "they"], + ["repo\\b", "repository"], + ["smartphone(s?)", "mobile phone$1"], + ["web[- ]?site(s?)", "site$1"], + + // Single word + ["auto[- ]complete", "autocomplete"], + ["auto[- ]format", "autoformat"], + ["auto[- ]fix", "autofix"], + ["auto[- ]fixing", "autofixing"], + ["back[- ]end(\\w*)", "backend$1"], + ["bug[- ]fix(es?)", "bugfix$1"], + ["check[- ]box(es?)", "checkbox$1"], + ["code[- ]base(es?)", "codebase$1"], + ["co[- ]locate(d?)", "colocate$1"], + ["end[- ]point(s?)", "endpoint$1"], + ["e[- ]mail(s?)", "email$1"], + ["file[- ]name(s?)", "filename$1"], + ["front[- ]end(\\w*)", "frontend$1"], + ["hack[- ]a[- ]thon(s?)", "hackathon$1"], + ["host[- ]name(s?)", "hostname$1"], + ["hot[- ]key(s?)", "hotkey$1"], + ["life[- ]cycle", "lifecycle"], + ["life[- ]stream(s?)", "lifestream$1"], + ["lock[- ]file(s?)", "lockfile$1"], + ["mark-up", "markup"], // “mark up” as a verb is OK + ["meta[- ]data", "metadata"], + ["name[- ]space(s?)", "namespace$1"], + ["pre[- ]condition(s?)", "precondition$1"], + ["pre[- ]defined", "predefined"], + ["pre[- ]release(s?)", "prerelease$1"], + ["run[- ]time", "runtime"], + ["screen[- ]shot(s?)", "screenshot$1"], + ["screen[- ]?snap(s?)", "screenshot$1"], + ["sub[- ]class((?:es|ing)?)", "subclass$1"], + ["sub[- ]tree(s?)", "subtree$1"], + ["time[- ]stamp(s?)", "timestamp$1"], + ["touch[- ]screen(s?)", "touchscreen$1"], + ["user[- ]name(s?)", "username$1"], + ["walk[- ]through", "walkthrough"], + ["white[- ]space", "whitespace"], + ["wild[- ]card(s?)", "wildcard$1"], + + // Multiple words + ["change-?log(s?)", "change log$1"], + ["css-?in-?js", "CSS in JS"], + ["code-?review(s?)", "code review$1"], + ["code-?splitting", "code splitting"], + ["end-?user(s?)", "end user$1"], + ["file-?type(s?)", "file type$1"], + ["open-?source(ed?)", "open source$1"], + ["regexp?(s?)", "regular expression$1"], + ["style-?guide(s?)", "style guide$1"], + ["tree-?shaking", "tree shaking"], + ["source-?map(s?)", "source map$1"], + ["style-?sheet(s?)", "style sheet$1"], + ["user-?base", "user base"], + ["web-?page(s?)", "web page$1"], + + // Hyphenated + ["built ?in", "built-in"], + ["client ?side", "client-side"], + ["command ?line", "command-line"], + ["end ?to ?end", "end-to-end"], + ["error ?prone", "error-prone"], + ["higher ?order", "higher-order"], + ["key[/ ]?value", "key-value"], + ["server ?side", "server-side"], + ["two ?steps?", "two-step"], + ["2 ?steps?", "two-step"], + + // Starts from a lower case letter in the middle of a sentence + ["(\\w+[^.?!]\\)? )base64", "$1base64"], + ["(\\w+[^.?!]\\)? )stylelint", "$1stylelint"], + ["(\\w+[^.?!]\\)? )webpack", "$1webpack"], + ["(\\w+[^.?!]\\)? )npm", "$1npm"], + + // Typos + ["environemnt(s?)", "environment$1"], + ["pacakge(s?)", "package$1"], + ["tilda", "tilde"], + ["falsey", "falsy"] + ] + }, + "common-misspellings": true, + "write-good": { + "adverb": false, + "passive": false, + "tooWordy": false, + "weasel": false, + "so": false, + "thereIs" :false + }, + "no-dead-link": { + "ignoreRedirects": true, + "ignore": [ + "mailto:*", + "https://github.com/telefonicaid/sigfox-iotagent/blob/master/doc/roadmap.md", + "https://coveralls.io/**" + ] + } + } +} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 04a277c0..60271bc8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,66 @@ language: node_js - sudo: required -node_js: - - "6" - - "8" - - "10" - branches: only: - master services: - - rabbitmq - - docker - - mongodb + - rabbitmq + - docker + - mongodb install: - - npm install + - npm install + +jobs: + include: + - stage: test + name: "Unit Tests: Node 6" + node_js: 6 + + before_install: + - docker pull ansi/mosquitto + - docker run -d -p 1883:1883 -l mosquitto ansi/mosquitto + + before_script: + - npm run lint + + after_script: + - npm run test:coveralls + + - stage: test + name: "Unit Tests: Node 8" + node_js: 8 + + before_install: + - docker pull ansi/mosquitto + - docker run -d -p 1883:1883 -l mosquitto ansi/mosquitto + + before_script: + - npm run lint + + after_script: + - npm run test:coveralls + + - stage: test + name: "Unit Tests: Node 10" + node_js: 10 + + before_install: + - docker pull ansi/mosquitto + - docker run -d -p 1883:1883 -l mosquitto ansi/mosquitto -before_install: - - docker pull ansi/mosquitto - - docker run -d -p 1883:1883 -l mosquitto ansi/mosquitto + before_script: + - npm run lint -before_script: - - npm run lint + after_script: + - npm run test:coveralls -after_script: - - npm run test:coveralls + - stage: test + name: "Documentation Tests" + node_js: 10 + script: + - npm run lint:md + - npm run lint:text diff --git a/README.md b/README.md index b13f50b4..ba305e41 100644 --- a/README.md +++ b/README.md @@ -10,25 +10,22 @@ [![Coverage Status](https://coveralls.io/repos/github/telefonicaid/iotagent-json/badge.svg?branch=master)](https://coveralls.io/github/telefonicaid/iotagent-json?branch=master) ![Status](https://nexus.lab.fiware.org/static/badges/statuses/iot-json.svg) -An Internet of Things Agent for a JSON based protocol (with -[AMQP](https://www.amqp.org/), [HTTP](https://www.w3.org/Protocols/) and -[MQTT](https://mqtt.org/) transports). This IoT Agent is designed to be a bridge -between [JSON](https://json.org/) and the +An Internet of Things Agent for a JSON based protocol (with [AMQP](https://www.amqp.org/), +[HTTP](https://www.w3.org/Protocols/) and [MQTT](https://mqtt.org/) transports). This IoT Agent is designed to be a +bridge between [JSON](https://json.org/) and the [NGSI](https://swagger.lab.fiware.org/?url=https://raw.githubusercontent.com/Fiware/specifications/master/OpenAPI/ngsiv2/ngsiv2-openapi.json) interface of a context broker. -It is based on the -[IoT Agent Node.js Library](https://github.com/telefonicaid/iotagent-node-lib). -Further general information about the FIWARE IoT Agents framework, its -architecture and the common interaction model can be found in the library's -GitHub repository. +It is based on the [IoT Agent Node.js Library](https://github.com/telefonicaid/iotagent-node-lib). Further general +information about the FIWARE IoT Agents framework, its architecture and the common interaction model can be found in the +library's GitHub repository. -This project is part of [FIWARE](https://www.fiware.org/). For more information -check the FIWARE Catalogue entry for the +This project is part of [FIWARE](https://www.fiware.org/). For more information check the FIWARE Catalogue entry for the [IoT Agents](https://github.com/Fiware/catalogue/tree/master/iot-agents). | :books: [Documentation](https://fiware-iotagent-json.rtfd.io) | :mortar_board: [Academy](https://fiware-academy.readthedocs.io/en/latest/iot-agents/idas) | :whale: [Docker Hub](https://hub.docker.com/r/fiware/iotagent-json/) | :dart: [Roadmap](https://github.com/telefonicaid/iotagent-json/blob/master/docs/roadmap.md) | -|---|---|---|---| +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | + ## Contents @@ -36,31 +33,24 @@ check the FIWARE Catalogue entry for the - [Install](#build--install) - [Usage](#usage) - [API](#api) -- [Command Line Client](#command-line-client) +- [Command-line Client](#command-line-client) - [Testing](#testing) - [License](#license) ## Background -This IoT Agent is designed to be a bridge between an MQTT/HTTP+JSON based -protocol and the FIWARE NGSI standard used in FIWARE. This project is based in -the Node.js IoT Agent library. More information about the IoT Agents can be -found within the library's -[GitHub repository](https://github.com/telefonicaid/iotagent-node-lib). - -A quick way to get started is to read the -[Step by step Manual](./docs/stepbystep.md). - -As is the case in any IoT Agent, this one follows the interaction model defined -in the -[Node.js IoT Agent Library](https://github.com/telefonicaid/iotagent-node-lib), -that is used for the implementation of the Northbound APIs. Information about -the IoTAgent's architecture can be found on that global repository. This -documentation will only address those features and characteristics that are -particular to the JSON IoTAgent. - -If you want to contribute to the project, check out the -[Development section](#development) and the +This IoT Agent is designed to be a bridge between an MQTT/HTTP+JSON based protocol and the FIWARE NGSI standard used in +FIWARE. This project is based in the Node.js IoT Agent library. More information about the IoT Agents can be found +within the library's [GitHub repository](https://github.com/telefonicaid/iotagent-node-lib). + +A quick way to get started is to read the [Step by step Manual](./docs/stepbystep.md). + +As is the case in any IoT Agent, this one follows the interaction model defined in the +[Node.js IoT Agent Library](https://github.com/telefonicaid/iotagent-node-lib), that is used for the implementation of +the Northbound APIs. Information about the IoTAgent's architecture can be found on that global repository. This +documentation will only address those features and characteristics that are particular to the JSON IoTAgent. + +If you want to contribute to the project, check out the [Development section](#development) and the [Contribution guidelines](./docs/contribution.md). Additional information about operating the component can be found in the @@ -68,60 +58,54 @@ Additional information about operating the component can be found in the ## Install -Information about how to install the JSON IoTAgent can be found at the -corresponding section of the +Information about how to install the JSON IoTAgent can be found at the corresponding section of the [Installation & Administration Guide](docs/installationguide.md). A `Dockerfile` is also available for your use - further information can be found [here](docker/README.md) ## Usage -Information about how to use the IoT Agent can be found in the -[User & Programmers Manual](docs/usermanual.md). +Information about how to use the IoT Agent can be found in the [User & Programmers Manual](docs/usermanual.md). The following features are listed as [deprecated](docs/deprecated.md). ## API Apiary reference for the Configuration API can be found -[here](http://docs.telefonicaiotiotagents.apiary.io/#reference/configuration-api) -More information about IoT Agents and their APIs can be found in the IoT Agent -Library [documentation](https://iotagent-node-lib.rtfd.io/). +[here](http://docs.telefonicaiotiotagents.apiary.io/#reference/configuration-api) More information about IoT Agents and +their APIs can be found in the IoT Agent Library [documentation](https://iotagent-node-lib.rtfd.io/). -The latest IoT Agent for JSON documentation is also available on [ReadtheDocs](https://fiware-iotagent-json.readthedocs.io/en/latest/) +The latest IoT Agent for JSON documentation is also available on +[ReadtheDocs](https://fiware-iotagent-json.readthedocs.io/en/latest/) -## Command Line Client +## Command-line Client -The JSON IoT Agent comes with a client that can be used to test its features, -simulating a device. The client can be executed with the following command: +The JSON IoT Agent comes with a client that can be used to test its features, simulating a device. The client can be +executed with the following command: ```console bin/iotaJsonTester.js ``` -This will show a prompt where commands can be issued to the MQTT broker. For a -list of the currently available commands type `help`. +This will show a prompt where commands can be issued to the MQTT broker. For a list of the currently available commands +type `help`. -The client loads a global configuration used for all the commands, containing -the host and port of the MQTT broker and the API Key and Device ID of the device -to simulate. This information can be changed with the `config` command. +The client loads a global configuration used for all the commands, containing the host and port of the MQTT broker and +the API Key and Device ID of the device to simulate. This information can be changed with the `config` command. -In order to use any of the MQTT commands, you have to connect to the MQTT broker -first. If no connection is available, MQTT commands will show an error message -reminding you to connect. +In order to use any of the MQTT commands, you have to connect to the MQTT broker first. If no connection is available, +MQTT commands will show an error message reminding you to connect. -The Command Line Client gets its default values from a config file in the root -of the project: `client-config.js`. This config file can be used to permanently -tune the MQTT broker parameters, or the default device ID and APIKey. +The command-line Client gets its default values from a config file in the root of the project: `client-config.js`. This +config file can be used to permanently tune the MQTT broker parameters, or the default device ID and APIKey. ## Testing -[Mocha](http://visionmedia.github.io/mocha/) Test Runner + [Should.js](https://shouldjs.github.io/) Assertion Library. +[Mocha](https://mochajs.org/) Test Runner + [Should.js](https://shouldjs.github.io/) Assertion Library. The test environment is preconfigured to run BDD testing style. -Module mocking during testing can be done with -[proxyquire](https://github.com/thlorenz/proxyquire) +Module mocking during testing can be done with [proxyquire](https://github.com/thlorenz/proxyquire) To run tests, type @@ -131,8 +115,7 @@ npm test #### Requirements -All the tests are designed to test end to end scenarios, and there are some -requirements for its current execution: +All the tests are designed to test end-to-end scenarios, and there are some requirements for its current execution: - Mosquitto v1.3.5 server running - MongoDB v3.x server running @@ -141,25 +124,21 @@ requirements for its current execution: ## License -The IoT Agent for JSON is licensed under [Affero General Public License (GPL) -version 3](./LICENSE). +The IoT Agent for JSON is licensed under [Affero General Public License (GPL) version 3](./LICENSE). © 2019 Telefonica Investigación y Desarrollo, S.A.U ### Are there any legal issues with AGPL 3.0? Is it safe for me to use? -There is absolutely no problem in using a product licensed under AGPL 3.0. Issues with GPL -(or AGPL) licenses are mostly related with the fact that different people assign different -interpretations on the meaning of the term “derivate work” used in these licenses. Due to this, -some people believe that there is a risk in just _using_ software under GPL or AGPL licenses -(even without _modifying_ it). - -For the avoidance of doubt, the owners of this software licensed under an AGPL-3.0 license -wish to make a clarifying public statement as follows: +There is absolutely no problem in using a product licensed under AGPL 3.0. Issues with GPL (or AGPL) licenses are mostly +related with the fact that different people assign different interpretations on the meaning of the term “derivate work” +used in these licenses. Due to this, some people believe that there is a risk in just _using_ software under GPL or AGPL +licenses (even without _modifying_ it). -> Please note that software derived as a result of modifying the source code of this -> software in order to fix a bug or incorporate enhancements is considered a derivative -> work of the product. Software that merely uses or aggregates (i.e. links to) an otherwise -> unmodified version of existing software is not considered a derivative work, and therefore -> it does not need to be released as under the same license, or even released as open source. +For the avoidance of doubt, the owners of this software licensed under an AGPL-3.0 license wish to make a clarifying +public statement as follows: +> Please note that software derived as a result of modifying the source code of this software in order to fix a bug or +> incorporate enhancements is considered a derivative work of the product. Software that merely uses or aggregates (i.e. +> links to) an otherwise unmodified version of existing software is not considered a derivative work, and therefore it +> does not need to be released as under the same license, or even released as open source. diff --git a/docs/contribution.md b/docs/contribution.md index 2bacd0cb..c5e5eaa6 100644 --- a/docs/contribution.md +++ b/docs/contribution.md @@ -1,22 +1,28 @@ # Contribution Guidelines + ================== + ## Overview + Being an Open Source project, everyone can contribute, provided that it respect the following points: -* Before contributing any code, the author must make sure all the tests work (see below how to launch the tests). -* Developed code must adhere to the syntax guidelines enforced by the linters. -* Code must be developed following the branching model and changelog policies defined below. -* For any new feature added, unit tests must be provided, following the example of the ones already created. + +- Before contributing any code, the author must make sure all the tests work (see below how to launch the tests). +- Developed code must adhere to the syntax guidelines enforced by the linters. +- Code must be developed following the branching model and change log policies defined below. +- For any new feature added, unit tests must be provided, following the example of the ones already created. In order to start contributing: -1. Fork this repository clicking on the "Fork" button on the upper-right area of the page. -2. Clone your just forked repository: + +1. Fork this repository clicking on the "Fork" button on the upper-right area of the page. +2. Clone your just forked repository: ```bash git clone https://github.com/your-github-username/iotagent-json.git ``` -3. Add the main iotagent-json repository as a remote to your forked repository (use any name for your remote -repository, it does not have to be iotagent-json, although we will use it in the next steps): +3. Add the main iotagent-json repository as a remote to your forked repository (use any name for your remote + repository, it does not have to be iotagent-json, although we will use it in the next steps): + ```bash git remote add iotagent-json https://github.com/telefonicaid/iotagent-json.git ``` @@ -24,60 +30,69 @@ git remote add iotagent-json https://github.com/telefonicaid/iotagent-json.git Before starting contributing, remember to synchronize the `master` branch in your forked repository with the `master` branch in the main iotagent-json repository, by following this steps -1. Change to your local `master` branch (in case you are not in it already): +1. Change to your local `master` branch (in case you are not in it already): ```bash git checkout master ``` -2. Fetch the remote changes: + +2. Fetch the remote changes: ```bash git fetch iotagent-json ``` -3. Merge them: + +3. Merge them: ```bash git rebase iotagent-json/master ``` Contributions following this guidelines will be added to the `master` branch, and released in the next version. The -release process is explaind in the *Releasing* section below. +release process is explaind in the _Releasing_ section below. ## Branching model + There is one special branches in the repository: -* `master`: contains the last stable development code. New features and bug fixes are always merged to `master`. +- `master`: contains the last stable development code. New features and bugfixes are always merged to `master`. In order to start developing a new feature or refactoring, a new branch should be created with name `task/`. This branch must be created from the current version of the `master` branch. Once the new functionality has been -completed, a Pull Request will be created from the feature branch to `master`. Remember to check both the linters -and the tests before creating the Pull Request. +completed, a Pull Request will be created from the feature branch to `master`. Remember to check both the linters and +the tests before creating the Pull Request. -Bug fixes work the same way as other tasks, with the exception of the branch name, that should be called `bug/`. +Bugfixes work the same way as other tasks, with the exception of the branch name, that should be called `bug/`. -In order to contribute to the repository, these same scheme should be replicated in the forked repositories, so the -new features or fixes should all come from the current version of `master` and end up in `master` again. +In order to contribute to the repository, these same scheme should be replicated in the forked repositories, so the new +features or fixes should all come from the current version of `master` and end up in `master` again. All the `task/*` and `bug/*` branches are temporary, and should be removed once they have been merged. There is another set of branches called `release/`, one for each version of the product. This branches point to each of the released versions of the project, they are permanent and they are created with each release. -## Changelog +## Change log + The project contains a version changelog, called CHANGES_NEXT_RELEASE, that can be found in the root of the project. Whenever a new feature or bug fix is going to be merged with `develop`, a new entry should be added to this changelog. The new entry should contain the reference number of the issue it is solving (if any). -When a new version is released, the changelog is cleared, and remains fixed in the last commit of that version. The -content of the changelog is also moved to the release description in the Github release. +When a new version is released, the change log is cleared, and remains fixed in the last commit of that version. The +content of the change log is also moved to the release description in the GitHub release. ## Releasing + The process of making a release consists of the following steps: -1. Create and PR into `master` a new task branch with the following changes: - * Change the development version number in the package.json (with a sufix `-next`), to the new target version (without any sufix) - * Make sure all the dependencies have fixed versions (usually the IoTAgent library will be on `master`). -2. Create a tag from the last version of `master` named with the version number and push it to the repository. -3. Create the release in Github, from the created tag. In the description, add the contents of the Changelog. -4. Create a release branch from the last version of `master` named with the version number. -5. Create a new task for preparing the next release, adding the sufix `-next` to the current version number (to signal -this as the development version). + +1. Create and PR into `master` a new task branch with the following changes: + +- Change the development version number in the package.json (with a sufix `-next`), to the new target version (without + any sufix) +- Make sure all the dependencies have fixed versions (usually the IoTAgent library will be on `master`). + +2. Create a tag from the last version of `master` named with the version number and push it to the repository. +3. Create the release in Github, from the created tag. In the description, add the contents of the change log. +4. Create a release branch from the last version of `master` named with the version number. +5. Create a new task for preparing the next release, adding the sufix `-next` to the current version number (to signal + this as the development version). diff --git a/docs/deprecated.md b/docs/deprecated.md index 96908cce..11fdaf01 100644 --- a/docs/deprecated.md +++ b/docs/deprecated.md @@ -1,41 +1,40 @@ # Deprecated functionality -Deprecated features are features that iotagent-json stills support but that are -not maintained or evolved any longer. In particular: - -- Bugs or issues related with deprecated features and not affecting - any other feature are not addressed (they are closed in github.com - as soon as they are spotted). -- Documentation on deprecated features is removed from the repository documentation. - Documentation is still available in the documentation set associated to older versions - (in the repository release branches). -- Deprecated functionality is eventually removed from iotagent-json. Thus you - are strongly encouraged to change your implementations using iotagent-json - in order not rely on deprecated functionality. +Deprecated features are features that iotagent-json stills support but that are not maintained or evolved any longer. In +particular: + +- Bugs or issues related with deprecated features and not affecting any other feature are not addressed (they are + closed in github.com as soon as they are spotted). +- Documentation on deprecated features is removed from the repository documentation. Documentation is still available + in the documentation set associated to older versions (in the repository release branches). +- Deprecated functionality is eventually removed from iotagent-json. Thus you are strongly encouraged to change your + implementations using iotagent-json in order not rely on deprecated functionality. A list of deprecated features and the version in which they were deprecated follows: -* Support to NGSIv1. -* Support to Node.js v4 in iotagent-json 1.9.0. The use of Node.js v8 is highly recommended. +- Support to NGSIv1. +- Support to Node.js v4 in iotagent-json 1.9.0. The use of Node.js v8 is highly recommended. ## Using old iotagent-json versions -Although you are encouraged to use always the newest iotagent-json version, take into account the following -information in the case you want to use old versions: +Although you are encouraged to use always the newest iotagent-json version, take into account the following information +in the case you want to use old versions: -* Code corresponding to old releases is available at the [iotagent-json github repository](https://github.com/telefonicaid/iotagent-json). Each release number - (e.g. 1.8.0 ) has associated the following: - * A tag, e.g. `1.8.0 `. It points to the base version. - * A release branch, `release/1.8.0 `. The HEAD of this branch usually matches the aforementioned tag. However, if some - hotfixes were developed on the base version, this branch contains such hotfixes. -* Documentation corresponding to old versions can be found at [readthedocs.io](https://fiware-iotagent-json.readthedocs.io). Use the panel in the right bottom corner to navigate to the right version. - -* Docker images corresponding to iotagent-json can be found at [Dockerhub](https://hub.docker.com/r/fiware/iotagent-json/tags/). +- Code corresponding to old releases is available at the + [iotagent-json GitHub repository](https://github.com/telefonicaid/iotagent-json). Each release number (e.g. 1.8.0 ) + has associated the following: - A tag, e.g. `1.8.0`. It points to the base version. - A release branch, + `release/1.8.0`. The HEAD of this branch usually matches the aforementioned tag. However, if some hotfixes were + developed on the base version, this branch contains such hotfixes. +- Documentation corresponding to old versions can be found at + [readthedocs.io](https://fiware-iotagent-json.readthedocs.io). Use the panel in the right bottom corner to navigate + to the right version. +- Docker images corresponding to iotagent-json can be found at + [Dockerhub](https://hub.docker.com/r/fiware/iotagent-json/tags/). The following table provides information about the last iotagent-json version supporting currently removed features: -| **Removed feature** | **Last iotagent-json version supporting feature** | **That version release date** | -|----------------------------------------------------------------------------|-------------------------------------------|---------------------------------| -| NGSIv1 API | Not yet defined | Not yet defined -| Support to Node.js v6 | Not yet defined but it will be done by May 2019 | Not yet defined -| Support to Node.js v4 | 1.9.0 | December 19th, 2018 | +| **Removed feature** | **Last iotagent-json version supporting feature** | **That version release date** | +| --------------------- | ------------------------------------------------- | ----------------------------- | +| NGSIv1 API | Not yet defined | Not yet defined | +| Support to Node.js v6 | Not yet defined but it will be done by May 2019 | Not yet defined | +| Support to Node.js v4 | 1.9.0 | December 19th, 2018 | diff --git a/docs/index.md b/docs/index.md index dac26daa..5c9b90b2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,10 @@ [![FIWARE IoT Agents](https://nexus.lab.fiware.org/repository/raw/public/badges/chapters/iot-agents.svg)](https://www.fiware.org/developers/catalogue/) [![](https://nexus.lab.fiware.org/repository/raw/public/badges/stackoverflow/iot-agents.svg)](https://stackoverflow.com/questions/tagged/fiware+iot) -This Internet of Things Agent is a bridge that can be used to communicate devices using a simple JSON protocol and NGSI Context Brokers (like [Orion](https://github.com/Fiware/context.Orion)). This protocol is based on simple single level JSON Objects codifying (attribute, value) pairs. This protocol is aimed for simplicity and ease of use, for those scenarios where there are no hard resource constraints. +This Internet of Things Agent is a bridge that can be used to communicate devices using a simple JSON protocol and NGSI +Context Brokers (like [Orion](https://github.com/Fiware/context.Orion)). This protocol is based on simple single level +JSON Objects codifying (attribute, value) pairs. This protocol is aimed for simplicity and ease of use, for those +scenarios where there are no hard resource constraints. -Github's [README.md](https://github.com/telefonicaid/iotagent-json/blob/master/README.md) provides a good documentation summary. -The [User Manual](usermanual.md) and the [Admin Guide](installationguide.md) cover more advanced topics. +Github's [README.md](https://github.com/telefonicaid/iotagent-json/blob/master/README.md) provides a good documentation +summary. The [User Manual](usermanual.md) and the [Admin Guide](installationguide.md) cover more advanced topics. diff --git a/docs/installationguide.md b/docs/installationguide.md index efd5bef9..5805ded7 100644 --- a/docs/installationguide.md +++ b/docs/installationguide.md @@ -1,19 +1,22 @@ # Installation & Administration Guide -* [Installation](#installation) -* [Usage](#usage) -* [Configuration](#configuration) +- [Installation](#installation) +- [Usage](#usage) +- [Configuration](#configuration) ### Installation + There are three ways of installing the JSON IoT Agent: using Git, RPMs or Docker image. #### Using GIT + In order to install the TT Agent, just clone the project and install the dependencies: ```bash git clone https://github.com/telefonicaid/iotagent-json.git npm install ``` + In order to start the IoT Agent, from the root folder of the project, type: ```bash @@ -21,6 +24,7 @@ bin/iotagent-json ``` #### Using RPM + The project contains a script for generating an RPM that can be installed in Red Hat 6.5 compatible Linux distributions. The RPM depends on Node.js 0.10 version, so EPEL repositories are advisable. @@ -41,27 +45,33 @@ The IoTA will then be installed as a linux service, and can ve started with the ```bash service iotaJSON start ``` + #### Using Docker -A docker container is available on docker hub. It will start the container with the default settings defined -in `config.js`. + +A docker container is available on docker hub. It will start the container with the default settings defined in +`config.js`. ```bash docker run -it --init fiware/iotagent-json ``` + To use your own configuration you can mount a local configuration file: ```bash docker run -it --init -v :/opt/iotajson/new_config.js fiware/iotagent-json -- new_config.js ``` -As an alternative, it is also possible to pass configuration using environmental variables, as explained in [Configuration with environment variables](#configuration-with-environment-variables) subsection. +As an alternative, it is also possible to pass configuration using environmental variables, as explained in +[Configuration with environment variables](#configuration-with-environment-variables) subsection. ### Usage + In order to execute the JSON IoT Agent just execute the following command from the root folder: ```bash bin/iotagentMqtt.js ``` + This will start the JSON IoT Agent in the foreground. Use standard linux commands to start it in background. When started with no arguments, the IoT Agent will expect to find a `config.js` file with the configuration in the root @@ -69,100 +79,115 @@ folder. An argument can be passed with the path to a new configuration file (rel used instead of the default one. ### Configuration + #### Overview -All the configuration for the IoT Agent is stored in a single configuration file (typically installed in the root folder). + +All the configuration for the IoT Agent is stored in a single configuration file (typically installed in the root +folder). This configuration file is a JavaScript file and contains three configuration chapters: -* **iota**: this object stores the configuration of the North Port of the IoT Agent, and is completely managed by the -IoT Agent library. More information about this options can be found [here](https://github.com/telefonicaid/iotagent-node-lib#configuration). -* **mqtt**: this object stores MQTT's specific configuration. A detailed description can be found in the next section. -* **http**: this object stores HTTP's specific configuration. A detailed description can be found in the next section. + +- **iota**: this object stores the configuration of the North Port of the IoT Agent, and is completely managed by the + IoT Agent library. More information about this options can be found + [here](https://github.com/telefonicaid/iotagent-node-lib#configuration). +- **mqtt**: this object stores MQTT's specific configuration. A detailed description can be found in the next section. +- **http**: this object stores HTTP's specific configuration. A detailed description can be found in the next section. There are also some global configuration options: -* **configRetrieval**: this flag indicates whether the incoming notifications to the IoTAgent should be processed -using the bidirectionality plugin from the latest versions of the library or the JSON-specific configuration retrieval -mechanism (described in the User Manual). Simultaneous use of both mechanisms is not allowed. -* **compressTimestamp**: this flags enables the timestamp compression mechanism, described in the User Manual. + +- **configRetrieval**: this flag indicates whether the incoming notifications to the IoTAgent should be processed + using the bidirectionality plugin from the latest versions of the library or the JSON-specific configuration + retrieval mechanism (described in the User Manual). Simultaneous use of both mechanisms is not allowed. +- **compressTimestamp**: this flags enables the timestamp compression mechanism, described in the User Manual. #### MQTT configuration These are the currently available MQTT configuration options: -* **protocol**: protocol to use for connecting with the MQTT broker (`mqtt`, `mqtts`, `tcp`, `tls`, `ws`, `wss`). -* **host**: host of the MQTT broker. -* **port**: port where the MQTT broker is listening. -* **defaultKey**: default API Key to use when a device is provisioned without a configuration. -* **ca**: ca certificates to use for validating server certificates (optional). Default is to trust the well-known CAs curated by Mozilla. Mozilla's CAs are completely replaced when CAs are explicitly specified using this option. -* **cert**: cert chains in PEM format to use for authenticating into the MQTT broker (optional). Only used when using `mqtts`, `tls` or `wss` as connnection protocol. -* **key**: optional private keys in PEM format to use on the client side for connecting with the MQTT broker (optional). Only used when using `mqtts`, `tls` or `wss` as connection protocol. -* **rejectUnauthorized**: whether to reject any connection which is not authorized with the list of supplied CAs. This option only has an effect when using `mqtts`, `tls` or `wss` protocols (default is `true`). -* **username**: user name that identifies the IOTA against the MQTT broker (optional). -* **password**: password to be used if the username is provided (optional). -* **qos**: QoS level: at most once (0), at least once (1), exactly once (2). (default is 0). -* **retain**: retain flag (default is false). - -TLS options (i.e. **ca**, **cert**, **key**, **rejectUnauthorized**) are directly linked with the ones supported by the [tls module of Node.js](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options). - +- **protocol**: protocol to use for connecting with the MQTT broker (`mqtt`, `mqtts`, `tcp`, `tls`, `ws`, `wss`). +- **host**: host of the MQTT broker. +- **port**: port where the MQTT broker is listening. +- **defaultKey**: default API Key to use when a device is provisioned without a configuration. +- **ca**: ca certificates to use for validating server certificates (optional). Default is to trust the well-known CAs + curated by Mozilla. Mozilla's CAs are completely replaced when CAs are explicitly specified using this option. +- **cert**: cert chains in PEM format to use for authenticating into the MQTT broker (optional). Only used when using + `mqtts`, `tls` or `wss` as connnection protocol. +- **key**: optional private keys in PEM format to use on the client-side for connecting with the MQTT broker + (optional). Only used when using `mqtts`, `tls` or `wss` as connection protocol. +- **rejectUnauthorized**: whether to reject any connection which is not authorized with the list of supplied CAs. This + option only has an effect when using `mqtts`, `tls` or `wss` protocols (default is `true`). +- **username**: username that identifies the IOTA against the MQTT broker (optional). +- **password**: password to be used if the username is provided (optional). +- **qos**: QoS level: at most once (0), at least once (1), exactly once (2). (default is 0). +- **retain**: retain flag (default is false). + +TLS options (i.e. **ca**, **cert**, **key**, **rejectUnauthorized**) are directly linked with the ones supported by the +[tls module of Node.js](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options). #### AMQP Binding configuration The `config.amqp` section of the config file contains all the information needed to connect to the AMQP Broker from the IoT Agent. The following attributes are accepted: -* **host**: Host where the AMQP Broker is located. -* **port**: Port where the AMQP Broker is listening -* **username**: user name that identifies the IOTA against the AMQP broker (optional). -* **password**: password to be used if the username is provided (optional). -* **exchange**: Exchange in the AMQP broker -* **queue**: Queue in the AMQP broker -* **durable**: durable queue flag (default is `false`). -* **retries**: Number of AMQP connection error retries (default is 5). -* **retryTime**: Time between AMQP connection retries (default is 5 seconds). +- **host**: Host where the AMQP Broker is located. +- **port**: Port where the AMQP Broker is listening +- **username**: username that identifies the IOTA against the AMQP broker (optional). +- **password**: password to be used if the username is provided (optional). +- **exchange**: Exchange in the AMQP broker +- **queue**: Queue in the AMQP broker +- **durable**: durable queue flag (default is `false`). +- **retries**: Number of AMQP connection error retries (default is 5). +- **retryTime**: Time between AMQP connection retries (default is 5 seconds). #### HTTP Binding configuration + The `config.http` section of the config file contains all the information needed to start the HTTP server for the HTTP transport protocol binding. The following options are accepted: -* **port**: South Port where the HTTP listener will be listening for information from the devices. -* **timeout**: HTTP Timeout for the HTTP endpoint (in miliseconds). +- **port**: South Port where the HTTP listener will be listening for information from the devices. +- **timeout**: HTTP Timeout for the HTTP endpoint (in miliseconds). #### Configuration with environment variables + Some of the more common variables can be configured using environment variables. The ones overriding general parameters -in the `config.iota` set are described in the [IoTA Library Configuration manual](https://github.com/telefonicaid/iotagent-node-lib#configuration). +in the `config.iota` set are described in the +[IoTA Library Configuration manual](https://github.com/telefonicaid/iotagent-node-lib#configuration). The ones relating specific JSON bindings are described in the following table. -| Environment variable | Configuration attribute | -|:----------------------------- |:----------------------------------- | -| IOTA_MQTT_PROTOCOL | mqtt.protocol | -| IOTA_MQTT_HOST | mqtt.host | -| IOTA_MQTT_PORT | mqtt.port | -| IOTA_MQTT_CA | mqtt.ca | -| IOTA_MQTT_CERT | mqtt.cert | -| IOTA_MQTT_KEY | mqtt.key | -| IOTA_MQTT_REJECT_UNAUTHORIZED | mqtt.rejectUnauthorized | -| IOTA_MQTT_USERNAME | mqtt.username | -| IOTA_MQTT_PASSWORD | mqtt.password | -| IOTA_MQTT_QOS | mqtt.qos | -| IOTA_MQTT_RETAIN | mqtt.retain | -| IOTA_AMQP_HOST | amqp.host | -| IOTA_AMQP_PORT | amqp.port | -| IOTA_AMQP_USERNAME | amqp.username | -| IOTA_AMQP_PASSWORD | amqp.password | -| IOTA_AMQP_EXCHANGE | amqp.exchange | -| IOTA_AMQP_QUEUE | amqp.queue | -| IOTA_AMQP_DURABLE | amqp.durable | -| IOTA_AMQP_RETRIES | amqp.retries | -| IOTA_AMQP_RETRY_TIME | amqp.retryTime | -| IOTA_HTTP_HOST | http.host | -| IOTA_HTTP_PORT | http.port | -| IOTA_HTTP_TIMEOUT | http.timeout | +| Environment variable | Configuration attribute | +| :---------------------------- | :---------------------- | +| IOTA_MQTT_PROTOCOL | mqtt.protocol | +| IOTA_MQTT_HOST | mqtt.host | +| IOTA_MQTT_PORT | mqtt.port | +| IOTA_MQTT_CA | mqtt.ca | +| IOTA_MQTT_CERT | mqtt.cert | +| IOTA_MQTT_KEY | mqtt.key | +| IOTA_MQTT_REJECT_UNAUTHORIZED | mqtt.rejectUnauthorized | +| IOTA_MQTT_USERNAME | mqtt.username | +| IOTA_MQTT_PASSWORD | mqtt.password | +| IOTA_MQTT_QOS | mqtt.qos | +| IOTA_MQTT_RETAIN | mqtt.retain | +| IOTA_AMQP_HOST | amqp.host | +| IOTA_AMQP_PORT | amqp.port | +| IOTA_AMQP_USERNAME | amqp.username | +| IOTA_AMQP_PASSWORD | amqp.password | +| IOTA_AMQP_EXCHANGE | amqp.exchange | +| IOTA_AMQP_QUEUE | amqp.queue | +| IOTA_AMQP_DURABLE | amqp.durable | +| IOTA_AMQP_RETRIES | amqp.retries | +| IOTA_AMQP_RETRY_TIME | amqp.retryTime | +| IOTA_HTTP_HOST | http.host | +| IOTA_HTTP_PORT | http.port | +| IOTA_HTTP_TIMEOUT | http.timeout | (HTTP-related environment variables will be used in the upcoming HTTP binding) -`IOTA_MQTT_CA`, `IOTA_MQTT_CERT`, `IOTA_MQTT_KEY` environment variables should provide the file name of the file whose contents will be used for the configuration attribute. +`IOTA_MQTT_CA`, `IOTA_MQTT_CERT`, `IOTA_MQTT_KEY` environment variables should provide the filename of the file whose +contents will be used for the configuration attribute. ## Packaging + The only package type allowed is RPM. In order to execute the packaging scripts, the RPM Build Tools must be available in the system. @@ -172,5 +197,6 @@ From the root folder of the project, create the RPM with the following commands: cd rpm ./create-rpm.sh -v -r ``` + Where `` is the version (x.y.z) you want the package to have and `` is an increasing number dependent in previous installations. diff --git a/docs/operations.md b/docs/operations.md index bcf2bf30..e91d88f2 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -1,99 +1,106 @@ # Operations Manual: logs and alarms -* [Overview](#overview) -* [Logs](#logs) -* [Alarms](#alarms) -* [Error naming code](#error-naming-code) - +- [Overview](#overview) +- [Logs](#logs) +- [Alarms](#alarms) +- [Error naming code](#error-naming-code) ## Overview + The following document shows all the errors that can appear in the IoTAgent Ultralight 2.0 log file, and gives a brief idea of the severity and how to react to those errors. ## Logs + The following section contains the error log entries that can appear in the IoTA logs, grouped by category. ### Command errors -#### COMMAND-001: Command execution could not be handled, as device for entity [%s] [%s] wasn\'t found +#### COMMAND-001: Command execution could not be handled, as device for entity \[%s]\[%s] wasn\'t found + Indicates that a command has been received for a non-registered entity. This could mean the device was removed from the IoT Agent without removing the registration in the Context Broker. Check for the existence of a provisioned device for the entity, and, if it doesn't exist, remove the Context Broker registration for that unexistent device. -#### COMMANDS-002: Couldn\'t update command status in the Context broker for device [%s] with apiKey [%s]: %s +#### COMMANDS-002: Couldn\'t update command status in the Context broker for device \[%s] with apiKey \[%s]: %s + There was some communication error connecting with the Context Broker that made it impossible to update the command -status. If this error appears, the command status will be left inconsistent. If this log appears frequently, it may be -a signal of network problems between the IoTAgent and the Context Broker. Check the IoTAgent network connection, and -the configured Context Broker port and host. +status. If this error appears, the command status will be left inconsistent. If this log appears frequently, it may be a +signal of network problems between the IoTAgent and the Context Broker. Check the IoTAgent network connection, and the +configured Context Broker port and host. ### Configuration retrieval #### CONFIG-001: Couldn\'t get the requested values from the Context Broker: %s The client device requested some attributes that didn't exist in the Context Broker. This usually means there was an -error in the client side (either the client did not write the appropriate values in the CB or the device sent different +error in the client-side (either the client did not write the appropriate values in the CB or the device sent different IDs in the request). Occasionally it may reflect an error in the communication with the Context Broker. -#### CONFIG-002: There was an error subscribing device [%s] to attributes [%j] +#### CONFIG-002: There was an error subscribing device \[%s] to attributes \[%j] The IoTAgent could not subscribe to the requested entity. Most of the times this will indicate a problem communicating with the Context Broker (check it by looking for other Context Broker communication-related problems). -#### CONFIG-003: Unknown command type from device [%s] +#### CONFIG-003: Unknown command type from device \[%s] A configuration request was received from a device with a type that is not one of the available values: "configuartion" -or "subscription". This is always an error on the client side. +or "subscription". This is always an error on the client-side. ### Thinking Things errors #### TTHINGS-001: Too few fields parsing Battery module: %s -Parse error reading a battery payload. This is always an error on the client side (redirect it to the documentation). +Parse error reading a battery payload. This is always an error on the client-side (redirect it to the documentation). #### TTHINGS-002: Too few fields parsing GSM module: %s -Parse error reading a GSM payload. This is always an error on the client side (redirect it to the documentation). +Parse error reading a GSM payload. This is always an error on the client-side (redirect it to the documentation). #### TTHINGS-003: Too few fields parsing C1 module: %s -Parse error reading a C1 payload. This is always an error on the client side (redirect it to the documentation). - +Parse error reading a C1 payload. This is always an error on the client-side (redirect it to the documentation). ### Measure errors #### MEASURES-001: Bad payload received while processing timestamps + The Timestamp insertion plugin found an object with a wrong format that prevented the plugin from writing the Timestamp. This object is written by internal code so this shouldn't happen. If it does, it will be as a consecuence of a previous error, or it will indicate a bug in the code. #### MEASURES-002: Couldn\'t send the updated values to the Context Broker due to an error: %s -There was some communication error connecting with the Context Broker that made it impossible to send the measures. -If this log appears frequently, it may be a signal of network problems between the IoTAgent and the Context Broker. -Check the IoTAgent network connection, and the configured Context Broker port and host. + +There was some communication error connecting with the Context Broker that made it impossible to send the measures. If +this log appears frequently, it may be a signal of network problems between the IoTAgent and the Context Broker. Check +the IoTAgent network connection, and the configured Context Broker port and host. #### MEASURES-003: Impossible to handle malformed message: %s + The received MQTT message did not contain a valid JSON payload. This will usually be caused by an error in the client side: either the JSON itself is not well-formed, or it has been encoded in a way the IoTAgent was not able to decode. -#### MEASURES-004: Device not found for topic [%s] +#### MEASURES-004: Device not found for topic \[%s] + This error log will appear whenever a measure arrives to the IoT Agent for a device that has not been provisioned or for an API Key that has not been registered in the IoT Agent. This could have several origins: the may be a typo in the DeviceId or APIKey used by the customer; or either the Configuration or the Device for the corresponding measure may have been removed; or the customer may have forgotten to provision both the Configuration and the Device. -#### MEASURES-005: Couldn\'t process message [%s] due to format issues. +#### MEASURES-005: Couldn\'t process message \[%s] due to format issues. + Implies a message was received in an invalid MQTT Topic. Normally, this is an error that can only be addressed by the client itself. - ### Global errors #### GLOBAL-001: Error subscribing to topics: %s + Error subscribing the IoT Agent to the appropriate MQTT Topics. This error can only happen at startup time, and should -prevent the IoT Agent from starting. If this error occurs, check the Mosquitto MQTT broker is up and running and check the -connectivity from the IoTAgent to the broker. +prevent the IoT Agent from starting. If this error occurs, check the Mosquitto MQTT broker is up and running and check +the connectivity from the IoTAgent to the broker. -#### GLOBAL-002: Configuration error. Configuration object [config.http] is missing +#### GLOBAL-002: Configuration error. Configuration object \[config.http] is missing Indicates the mandatory "config.http" configuration parameter was not found while starting the IoTAgent. This will prevent the IoTAgent from starting. Check the configuration files and fix them to be valid. @@ -101,26 +108,27 @@ prevent the IoTAgent from starting. Check the configuration files and fix them t ## Alarms The following table shows the alarms that can be raised in the JSON IoTAgent library. All the alarms are signaled by an -error log starting with the prefix "Raising [%s]:" (where %s is the alarm name). All the alarms are released by an info -log with the prefix "Releasing [%s]". These texts appear in the `msg=` field of the generic log record format. +error log starting with the prefix "Raising \[%s]:" (where %s is the alarm name). All the alarms are released by an info +log with the prefix "Releasing \[%s]". These texts appear in the `msg=` field of the generic log record format. -| Alarm name | Severity | Description | -|:--------------------- |:-------------|:---------------------- | -| MQTTB-ALARM | **Critical** | Indicates a persistent error accessing the Mosquitto MQTT Broker | +| Alarm name | Severity | Description | +| :---------- | :----------- | :--------------------------------------------------------------- | +| MQTTB-ALARM | **Critical** | Indicates a persistent error accessing the Mosquitto MQTT Broker | while the 'Severity' criterium is as follows: -* **Critical** - The system is not working -* **Major** - The system has a problem that degrades the service and must be addressed -* **Warning** - It is happening something that must be notified +- **Critical** - The system is not working +- **Major** - The system has a problem that degrades the service and must be addressed +- **Warning** - It is happening something that must be notified ## Error naming code + Every error has a code composed of a prefix and an ID, codified with the following table: -| Prefix | Type of operation | -|:---------------- |:---------------------- | -| GLOBAL | Global errors | -| TTHINGS | Thinking Things plugin errors | -| CONFIG | Errors related with the configuration retrieval mechanism | -| MEASURES | Errors related with measure processing | -| COMMANDS | Errors related with command processing | +| Prefix | Type of operation | +| :------- | :-------------------------------------------------------- | +| GLOBAL | Global errors | +| TTHINGS | Thinking Things plugin errors | +| CONFIG | Errors related with the configuration retrieval mechanism | +| MEASURES | Errors related with measure processing | +| COMMANDS | Errors related with command processing | diff --git a/docs/roadmap.md b/docs/roadmap.md index 260d7c3e..ea76c906 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,41 +1,50 @@ -# IoT Agent for a JSON-based Protocol Roadmap +# IoT Agent for a JSON-based Protocol Roadmap -This product is a FIWARE Generic Enabler. If you would like to learn about the overall Roadmap of FIWARE, please check "Roadmap" on the [FIWARE Catalogue](https://www.fiware.org/developers/catalogue/). +This product is a FIWARE Generic Enabler. If you would like to learn about the overall Roadmap of FIWARE, please check +"Roadmap" on the [FIWARE Catalogue](https://www.fiware.org/developers/catalogue/). ### Introduction -This section elaborates on proposed new features or tasks which are expected to be added to the product in the foreseeable future. There should be no assumption of a commitment to deliver these features on specific dates or in the order given. The development team will be doing their best to follow the proposed dates and priorities, but please bear in mind that plans to work on a given feature or task may be revised. All information is provided as general guidelines only, and this section may be revised to provide newer information at any time. +This section elaborates on proposed new features or tasks which are expected to be added to the product in the +foreseeable future. There should be no assumption of a commitment to deliver these features on specific dates or in the +order given. The development team will be doing their best to follow the proposed dates and priorities, but please bear +in mind that plans to work on a given feature or task may be revised. All information is provided as general guidelines +only, and this section may be revised to provide newer information at any time. Disclaimer: -* This section has been last updated in January 2019. Please take into account its - content could be obsolete. -* Note we develop this software in Agile way, so development plan is continuously - under review. Thus, this roadmap has to be understood as rough plan of features - to be done along time which is fully valid only at the time of writing it. This - roadmap has not be understood as a commitment on features and/or dates. -* Some of the roadmap items may be implemented by external community developers, - out of the scope of GE owners. Thus, the moment in which these features will be - finalized cannot be assured. - +- This section has been last updated in January 2019. Please take into account its content could be obsolete. +- Note we develop this software in Agile way, so development plan is continuously under review. Thus, this roadmap has + to be understood as rough plan of features to be done along time which is fully valid only at the time of writing + it. This roadmap has not be understood as a commitment on features and/or dates. +- Some of the roadmap items may be implemented by external community developers, out of the scope of GE owners. Thus, + the moment in which these features will be finalized cannot be assured. + ### Short term -The following list of features are planned to be addressed in the short term, and incorporated in a next release of the product: -- Docker image protects username and password using environment variables. -- Removal of warnings and deprecation warnings. -- Creation of tutorial (to be contributed by members of the Community beyond GE owners) +The following list of features are planned to be addressed in the short term, and incorporated in a next release of the +product: +- Docker image protects username and password using environment variables. +- Removal of warnings and deprecation warnings. +- Creation of tutorial (to be contributed by members of the Community beyond GE owners) ### Medium term -The following list of features are planned to be addressed in the medium term, typically within the subsequent release(s) generated in the next 9 months after the next planned release: -- Support to FIWARE complex data models. -- Deployment instructions for high availability scenarios. -- Incremental introduccion of ECMAScript6 syntax (previous analysis of which sub-set of interesting aspect we want to take) -- Implementation of lazy attributes. -- Removal support for NGSIv1 (which currently is deprecated) +The following list of features are planned to be addressed in the medium term, typically within the subsequent +release(s) generated in the next 9 months after the next planned release: + +- Support to FIWARE complex data models. +- Deployment instructions for high availability scenarios. +- Incremental introduccion of ECMAScript6 syntax (previous analysis of which sub-set of interesting aspect we want to + take) +- Implementation of lazy attributes. +- Removal support for NGSIv1 (which currently is deprecated) ### Long term -The following list of features are proposals regarding the longer-term evolution of the product even though the development of these features has not yet been scheduled for a release in the near future. Please feel free to contact us if you wish to get involved in the implementation or influence the roadmap: -- Implementation of device (southbound) authentication and authorization. +The following list of features are proposals regarding the longer-term evolution of the product even though the +development of these features has not yet been scheduled for a release in the near future. Please feel free to contact +us if you wish to get involved in the implementation or influence the roadmap: + +- Implementation of device (southbound) authentication and authorization. diff --git a/docs/stepbystep.md b/docs/stepbystep.md index 82af1978..c72c9b5b 100644 --- a/docs/stepbystep.md +++ b/docs/stepbystep.md @@ -1,22 +1,21 @@ -Step by Step guide -================== +# Step by Step guide -* [Introduction](#introduction) -* [Provisioning a single device with the default API Key](#provisioning-a-single-device-with-the-default-api-key) -* [Provisioning multiple devices with a Configuration](#provisioning-multiple-devices-with-a-configuration) -* [Using ACLs to secure provisioning access](#using-acls-to-secure-provisioning-access) +- [Introduction](#introduction) +- [Provisioning a single device with the default API Key](#provisioning-a-single-device-with-the-default-api-key) +- [Provisioning multiple devices with a Configuration](#provisioning-multiple-devices-with-a-configuration) +- [Using ACLs to secure provisioning access](#using-acls-to-secure-provisioning-access) ## Introduction -This guide will show, step-by-step, how to deploy and configure an MQTT-JSON IoT Agent for its use to connect devices -to an external NGSI Broker (aka Context Broker). +This guide will show, step-by-step, how to deploy and configure an MQTT-JSON IoT Agent for its use to connect devices to +an external NGSI Broker (aka Context Broker). The MQTT-JSON IoT Agent acts as a gateway for communicating devices using the MQTT protocol with NGSI brokers (or any -other piece which uses the NGSI protocol). The communication is based on a series of unidirectional MQTT topics -(i.e.: each topic is used to *publish* device information or to *subscribe* to entity updates, but not both). Every -topic has the same prefix, of the form: +other piece which uses the NGSI protocol). The communication is based on a series of unidirectional MQTT topics (i.e.: +each topic is used to _publish_ device information or to _subscribe_ to entity updates, but not both). Every topic has +the same prefix, of the form: -``` +```text ///topicSpecificPart ``` @@ -26,51 +25,52 @@ specifically for a given group of devices (as will be explained in the following A detailed specification of the protocol can be found [here](usermanual.md). -This guide will give a step-by-step example for the most common scenarios of use of the agent, from the IoT Agent -setup to the measure reporting (both for the case where individual devices are provisioned and the case where a group -of devices with a new API Key is provisioned first). Please, make sure you fulfil all the requirements from the next +This guide will give a step-by-step example for the most common scenarios of use of the agent, from the IoT Agent setup +to the measure reporting (both for the case where individual devices are provisioned and the case where a group of +devices with a new API Key is provisioned first). Please, make sure you fulfil all the requirements from the next section before starting the guides. -Before we start the tutorial we need some information about the service we are going to deploy. We will use the following -data, simulating a Smart Home application: +Before we start the tutorial we need some information about the service we are going to deploy. We will use the +following data, simulating a Smart Home application: -* *Service*: myhome -* *Subservice*: /environment -* *DevId*: sensor01, sensor02 and actuator01 +- _Service_: myhome +- _Subservice_: /environment +- _DevId_: sensor01, sensor02 and actuator01 ### Prerequisites -This step-by-step guide assumes you are going to install all the software in a single machine, with a Red Hat 6.5 -Linux installation. As such, it may not be an appropriate architecture for production purposes, but it should -serve as a development machine to test the MQTT IoT Agent. All the commands are meant to be executed from the same -machine (even curls and mosquitto-pub commands), but changing them to execute them from an external machine should be -a trivial task. -The selected MQTT Broker for this tutorial was Mosquitto, although it could be substituted by any other standard -MQTT broker. The Mosquitto command tools will also be used along this guide to test the installation and show the -information interchanged between simulated devices and the Context Broker. +This step-by-step guide assumes you are going to install all the software in a single machine, with a Red Hat 6.5 Linux +installation. As such, it may not be an appropriate architecture for production purposes, but it should serve as a +development machine to test the MQTT IoT Agent. All the commands are meant to be executed from the same machine (even +curls and mosquitto-pub commands), but changing them to execute them from an external machine should be a trivial task. + +The selected MQTT Broker for this tutorial was Mosquitto, although it could be substituted by any other standard MQTT +broker. The Mosquitto command tools will also be used along this guide to test the installation and show the information +interchanged between simulated devices and the Context Broker. The following list shows the prerequisite software and versions: -* Orion Context Broker (v0.26) -* Node.js (v0.12.0) -* Mosquitto (v1.4.7) (out-of-the-box setup) -* Curl (v7.19.7) -* Git (v1.7.1) +- Orion Context Broker (v0.26) +- Node.js (v0.12.0) +- Mosquitto (v1.4.7) (out-of-the-box setup) +- Curl (v7.19.7) +- Git (v1.7.1) -These are the versions that were used while writing this tutorial, but any version above the ones given here should -work as well (previous versions could also work, but also may not, so we encourage you to use versions above). +These are the versions that were used while writing this tutorial, but any version above the ones given here should work +as well (previous versions could also work, but also may not, so we encourage you to use versions above). -To enhance readability all the commands will be executed as root. To use other users, give it the appropriate permissions -and use `sudo` as usual (installation from the RPM package creates a special user for the agent, but it will not be -used along this tutorial). +To enhance readability all the commands will be executed as root. To use other users, give it the appropriate +permissions and use `sudo` as usual (installation from the RPM package creates a special user for the agent, but it will +not be used along this tutorial). ## Provisioning a single device with the default API Key ### Installing the IoT Agent + There are different ways to install the IoT Agent. In this tutorial, we will clone the last version of the agent from the repository. For different setups, check the installation guide in the main `README.md` file. -We will install our IoT Agent in the '/opt' repository. To do so, go to the folder and clone the repository with the +We will install our IoT Agent in the '/opt' repository. To do so, go to the folder and clone the repository with the following commands: ```bash @@ -99,7 +99,7 @@ netstat -ntpl | grep 4041 You should see an output like this: -``` +```text tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 18388/node ``` @@ -113,10 +113,10 @@ The result will be a JSON document indicating the MQTT-JSON IoTA version and the ```json { - "libVersion":"0.9.5", - "port":4041, - "baseRoot":"/", - "version":"0.1.5" + "libVersion": "0.9.5", + "port": 4041, + "baseRoot": "/", + "version": "0.1.5" } ``` @@ -127,16 +127,17 @@ You can also check the logs in the `/var/log/iotAgent` file created with the noh All the configuration of the IoTAgent can be done modifying a single file, `config.js`. The default values should meet the needs of this tutorial. -For a detailed description of these values, check the [iotagent-node-lib configuration documentation](https://github.com/telefonicaid/iotagent-node-lib/blob/master/doc/installationguide.md). +For a detailed description of these values, check the +[iotagent-node-lib configuration documentation](https://github.com/telefonicaid/iotagent-node-lib/blob/master/doc/installationguide.md). There is a configuration value that you may want to change while following this tutorial, and that's the `logLevel`. If -you have any problems following the instructions, or you simply want to know more of what's going on in the IoTA internals, -set its value to `DEBUG`. +you have any problems following the instructions, or you simply want to know more of what's going on in the IoTA +internals, set its value to `DEBUG`. Also note that the configuration type of the `deviceRegistry` is set to `memory`. This means all the contents of the -Device Registry will be wiped out from memory when the IoTAgent restarts. This is meant to be used in testing environments -and it will force you to provision again all your devices once you have restarted the agent. For persistent registries, -check the documentation to see how to connect the IoTA to a MongoDB instance. +Device Registry will be wiped out from memory when the IoTAgent restarts. This is meant to be used in testing +environments and it will force you to provision again all your devices once you have restarted the agent. For persistent +registries, check the documentation to see how to connect the IoTA to a MongoDB instance. ### Using the command-line clients @@ -144,7 +145,7 @@ The IoT Agent comes with a command-line client that can be used for an initial t offers commands to simulate MQTT requests with measures, device and configuration provisioning requests and NGSI queries to the Context Broker, that can be used to test the results. -In order to start the command line client, just type: +In order to start the command-line client, just type: ```bash bin/iotaJsonTester.js @@ -170,11 +171,12 @@ Mosquitto-pub can be used to send information to a topic. This will be a typical mosquitto_pub -h -t ///attrs -m '{"L":4,"T": "31.5","H":30}' ``` -If you execute both commands in different windows, when you run the latter command, you should see the string `{"L":4,"T": "31.5","H":30}` -appearing in the former. +If you execute both commands in different windows, when you run the latter command, you should see the string +`{"L":4,"T": "31.5","H":30}` appearing in the former. -This tutorial will use mainly the mosquitto clients and curl commands, to give a detailed view of how the APIs - -NGSI traffic north of the IoT Agent and MQTT (with a JSON payload) south of the IoT Agent. Whenever a command is needed, the exact command to be executed will be given. +This tutorial will use mainly the mosquitto clients and curl commands, to give a detailed view of how the APIs - NGSI +traffic north of the IoT Agent and MQTT (with a JSON payload) south of the IoT Agent. Whenever a command is needed, the +exact command to be executed will be given. ### Provisioning the device @@ -199,15 +201,16 @@ curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" - ' 'http://localhost:4041/iot/devices' ``` -This command will create the simplest kind of device, with just two declared active attributes: Temperature and Luminosity. +This command will create the simplest kind of device, with just two declared active attributes: Temperature and +Luminosity. -We have not created a specific configuration for our devices yet, so *the API Key will be the default one* for the IoTA +We have not created a specific configuration for our devices yet, so _the API Key will be the default one_ for the IoTA (i.e.: 1234). This default API Key can be changed in the config file. ### Sending measures with the device Now we can simulate some measures from the device. Since our device has DeviceID `sensor01` and the API Key we are using -is the default one, `1234`, we can send a measure with the mosquitto command line client using the following command: +is the default one, `1234`, we can send a measure with the mosquitto command-line client using the following command: ```bash mosquitto_pub -t /1234/sensor01/attrs -m '{"l":4,"t": "31.5"}' @@ -232,41 +235,42 @@ The resulting response should look like the following: ```json { - "contextResponses" : [ - { - "contextElement" : { - "type" : "multiSensor", - "isPattern" : "false", - "id" : "LivingRoomSensor", - "attributes" : [ - { - "name" : "Luminosity", - "type" : "lumens", - "value" : "4" - }, - { - "name" : "Temperature", - "type" : "celsius", - "value" : "31.5" - } - ] - }, - "statusCode" : { - "code" : "200", - "reasonPhrase" : "OK" - } - } - ] + "contextResponses": [ + { + "contextElement": { + "type": "multiSensor", + "isPattern": "false", + "id": "LivingRoomSensor", + "attributes": [ + { + "name": "Luminosity", + "type": "lumens", + "value": "4" + }, + { + "name": "Temperature", + "type": "celsius", + "value": "31.5" + } + ] + }, + "statusCode": { + "code": "200", + "reasonPhrase": "OK" + } + } + ] } ``` ### Retrieving configuration parameters from the Context Broker -The MQTT-JSON IoT Agent offers a special mechanism to retrieve information from the device entity, for device configuration -purposes. This mechanism is based on two special topics, with suffix `/configuration/commands` and `/configuration/values`. +The MQTT-JSON IoT Agent offers a special mechanism to retrieve information from the device entity, for device +configuration purposes. This mechanism is based on two special topics, with suffix `/configuration/commands` and +`/configuration/values`. -In order to test this functionality, we will, first of all, add some configuration attributes to the Context Broker entity -representing the device. We will add the `sleepTime` attribute with the following NGSI request: +In order to test this functionality, we will, first of all, add some configuration attributes to the Context Broker +entity representing the device. We will add the `sleepTime` attribute with the following NGSI request: ```bash curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Cache-Control: no-cache" -d '{ @@ -274,9 +278,9 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" - }' 'http://localhost:1026/v1/contextEntities/LivingRoomSensor/attributes/sleepTime' ``` -When the IoTAgent is asked for configuration values, it will ask the Context Broker for those values. Once it has collected -them, it will send them to the device in the topic with suffix '/configuration/values'. To check this operation with our -simulated device, execute the following line: +When the IoTAgent is asked for configuration values, it will ask the Context Broker for those values. Once it has +collected them, it will send them to the device in the topic with suffix '/configuration/values'. To check this +operation with our simulated device, execute the following line: ```bash mosquitto_sub -t /1234/sensor01/configuration/values @@ -293,7 +297,7 @@ mosquitto_pub -t /1234/sensor01/configuration/commands -m '{ "type": "configurat If we return now to the subscription window, we should be able to see the value of the `sleepTime` command: ```json -{"sleepTime":"300","dt":"20160209T111442Z"} +{ "sleepTime": "300", "dt": "20160209T111442Z" } ``` Along with all the information requested by the device, the IoTAgent will report the server time in the `dt` field of @@ -302,9 +306,9 @@ the response. ## Provisioning multiple devices with a Configuration In those cases where a group of devices with similar characteristics will be provisioned, a common configuration can be -created for them. This configuration provision can be used to separate device messages between services, by -establishing a specific API Key for each group. This can be used to secure access for specific groups of devices (an -example of how to do that will be shown in the last section for the Mosquitto MQTT broker). +created for them. This configuration provision can be used to separate device messages between services, by establishing +a specific API Key for each group. This can be used to secure access for specific groups of devices (an example of how +to do that will be shown in the last section for the Mosquitto MQTT broker). ### Provisioning the configuration @@ -325,14 +329,14 @@ curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" - ' 'http://localhost:4041/iot/services' ``` -This will make devices provisioned for that service, subservice and type use the provided APIKey as its APIKey prefix -in the MQTT topics. +This will make devices provisioned for that service, subservice and type use the provided APIKey as its APIKey prefix in +the MQTT topics. ### Provisioning the device For IoT Agents that support automatic device provisioning, provisioning a configuration is enough to start using devices -that use that configuration. For those who don't, each specific device must be provisioned, in order to save its deviceID -in the Device Registry. The provision of the device is quite similar to the one of the single device: +that use that configuration. For those who don't, each specific device must be provisioned, in order to save its +deviceID in the Device Registry. The provision of the device is quite similar to the one of the single device: ```bash curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ @@ -370,7 +374,8 @@ mosquitto_pub -t /AAFF9977/sensor02/attrs -m '{"humidity": 76,"happiness": "Not Note in this case the APIKey is not the default one, but the one we defined in the Configuration API. We can check everything went OK calling the Context Broker again: -``` + +```bash curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { @@ -419,15 +424,16 @@ That shows the information we sent with the measures has been written to the Con ## Using ACLs to secure provisioning access ### Overview -The use of special APIKeys gives the IoTAgent administrator the opportunity to set different MQTT-Broker level permissions -for each group of devices, using different authorization mechanisms to sepparate access between groups. + +The use of special APIKeys gives the IoTAgent administrator the opportunity to set different MQTT-Broker level +permissions for each group of devices, using different authorization mechanisms to sepparate access between groups. With the plain out-of-the-box Mosquitto setup, any device (any MQTT client, in fact) can send information impersonating other devices or read the information in their entities, just knowing their API-Key and deviceId. To avoid this problem, we will create an ACL that will give special permissions for our Configuration, and a set of credentials for the devices -of the group (that should be secretly shared with the devices). To make it simple, we will use a set of user and password -credentials, the same for all the devices of the group (other means of authentication could have been used instead, as -certificates, check Mosquitto documentation for other options). +of the group (that should be secretly shared with the devices). To make it simple, we will use a set of user and +password credentials, the same for all the devices of the group (other means of authentication could have been used +instead, as certificates, check Mosquitto documentation for other options). The same problem of device impersonation can occur in the case of the IoTA access (as the IoTA is other MQTT client, anonymous by default). To protect the interactions for the IoTA, another user will be created. @@ -444,10 +450,10 @@ mosquitto_passwd -b /etc/mosquitto/pwfile potteduser pottedpass This will create two sets of credentials (login/password): iota/iota and potteduser/pottedpass. -The permissions for different topics can be given with ACL files. To create one, just create a new `/etc/mosquitto/aclfile` -file with the following contents: +The permissions for different topics can be given with ACL files. To create one, just create a new +`/etc/mosquitto/aclfile` file with the following contents: -``` +```text topic read $SYS/# topic write /1234/+/attrs @@ -469,29 +475,30 @@ pattern write $SYS/broker/connection/%c/state There are three sections of interest in this file: -* In the first section, a set of topics is defined for the default APIKey (`1234` in this case). These topics are marked - with write or read depending on the action devices wil do with that topic. Access for actions other than the ones defined - as well as publishing to a read topic or viceversa is forbidden. This ensures no device will be able to impersonate the - IoT Agent, but this doesn't forbid one device impersonating others. This access is anonymous. +- In the first section, a set of topics is defined for the default APIKey (`1234` in this case). These topics are + marked with write or read depending on the action devices wil do with that topic. Access for actions other than the + ones defined as well as publishing to a read topic or viceversa is forbidden. This ensures no device will be able to + impersonate the IoT Agent, but this doesn't forbid one device impersonating others. This access is anonymous. -* An authenticated `iota` user can access everything, as it is supposed to be the owner of the broker (and just administrators -should have access to this user). +- An authenticated `iota` user can access everything, as it is supposed to be the owner of the broker (and just + administrators should have access to this user). -* For the `potteduser` account, the permissions are similar to those of the anonymous devices, but with a different APIKey - as the prefix. This ensures that no device coming from other group (that is supposed not to have valid credentials as - `potteduser`) will impersonate a device of the group, or subscribe to information sent by the group devices. +- For the `potteduser` account, the permissions are similar to those of the anonymous devices, but with a different + APIKey as the prefix. This ensures that no device coming from other group (that is supposed not to have valid + credentials as `potteduser`) will impersonate a device of the group, or subscribe to information sent by the group + devices. There are two more changes needed before we restart our test. First of all, we should add the IoTA Mosquitto credentials -to the IoTA Configuration, to give it full access to the MQTT Broker topics. To do so, edit the `/opt/iotajson/config.js` - file and change the `config.mqtt` section to look like this: +to the IoTA Configuration, to give it full access to the MQTT Broker topics. To do so, edit the +`/opt/iotajson/config.js` file and change the `config.mqtt` section to look like this: ```javascript config.mqtt = { - host: 'localhost', + host: "localhost", port: 1883, - defaultKey: '1234', - username: 'iota', - password: 'iota' + defaultKey: "1234", + username: "iota", + password: "iota" }; ``` @@ -522,11 +529,12 @@ and rerun the IoT Agent (you can check its PID with `ps` or `netstat` and kill i ### Testing #### Configuration and Device Provisioning + In order to test the ACL files, first of all, provision the configuration and device as we did in the previous chapter, but using a different device, with data: - * *Name*: DaisyPot - * *DevId*: sensor03 +- _Name_: DaisyPot +- _DevId_: sensor03 It's important that you provision the configuration with the exact same APIKey you declared in the ACL. @@ -580,8 +588,8 @@ curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" - ``` Checking the IoTAgent logs you will see that the request was completely ignored. The problem was that the client was -trying to make an anonymous publish in a ACL protected topic that let only the user `potteduser`publish new messages. -If we try again using the credentials we generated for the user: +trying to make an anonymous publish in a ACL protected topic that let only the user `potteduser`publish new messages. If +we try again using the credentials we generated for the user: ```bash mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' -u potteduser -P pottedpass @@ -591,30 +599,30 @@ And execute the queryContext again, we will get the updated entity: ```json { - "contextResponses" : [ - { - "contextElement" : { - "type" : "potSensor", - "isPattern" : "false", - "id" : "DaisyPot", - "attributes" : [ - { - "name" : "happiness", - "type" : "subjective", - "value" : " " - }, - { - "name" : "humidity", - "type" : "degrees", - "value" : " " - } - ] - }, - "statusCode" : { - "code" : "200", - "reasonPhrase" : "OK" - } - } - ] + "contextResponses": [ + { + "contextElement": { + "type": "potSensor", + "isPattern": "false", + "id": "DaisyPot", + "attributes": [ + { + "name": "happiness", + "type": "subjective", + "value": " " + }, + { + "name": "humidity", + "type": "degrees", + "value": " " + } + ] + }, + "statusCode": { + "code": "200", + "reasonPhrase": "OK" + } + } + ] } ``` diff --git a/docs/usermanual.md b/docs/usermanual.md index a8fcc27b..2f1b1f9c 100644 --- a/docs/usermanual.md +++ b/docs/usermanual.md @@ -1,255 +1,287 @@ # User & Programmers Manual -* [API Overview](#api-overview) - + [HTTP binding](#http-binding) - + [MQTT binding](#mqtt-binding) - + [AMQP binding](#amqp-binding) - + [Value conversion](#value-conversion) - + [Thinking Things plugin](#thinking-things-plugin) -* [Development documentation](#development-documentation) -* [New transport development](#new-transport-development) +- [API Overview](#api-overview) + - [HTTP binding](#http-binding) + - [MQTT binding](#mqtt-binding) + - [AMQP binding](#amqp-binding) + - [Value conversion](#value-conversion) + - [Thinking Things plugin](#thinking-things-plugin) +- [Development documentation](#development-documentation) +- [New transport development](#new-transport-development) ## API Overview + The JSON protocol uses plain JSON objects to send information formatted as key-value maps over any of the accepted transports (HTTP, MQTT or AMQP). Along this document we will refer some times to "plain JSON objects" or "single-level JSON objects". With that, we mean: -* valid JSON objects serialized as unescaped strings. -* JSON objects with a single level, i.e.: all the first level attributes of the JSON object are Strings or Numbers (not - arrays or other objects). -**IMPORTANT NOTE**: current version of the agent only supports active attributes, i.e. those attributes actively reported -by the device to the agent. Passive or lazy attributes, i.e. those attributes whose value is only given upon explicit -request from the agent, are not implemented. Please check the issue -[#89](https://github.com/telefonicaid/iotagent-json/issues/89) for more details and updates regarding its implementation. +- valid JSON objects serialized as unescaped strings. +- JSON objects with a single level, i.e.: all the first level attributes of the JSON object are Strings or Numbers + (not arrays or other objects). + +**IMPORTANT NOTE**: current version of the agent only supports active attributes, i.e. those attributes actively +reported by the device to the agent. Passive or lazy attributes, i.e. those attributes whose value is only given upon +explicit request from the agent, are not implemented. Please check the issue +[#89](https://github.com/telefonicaid/iotagent-json/issues/89) for more details and updates regarding its +implementation. + +### HTTP binding -### HTTP binding HTTP binding is based on directly interfacing the agent from a HTTP client in the device. Json payloads are, therefore, directly put into Http messages. #### Measure reporting -The payload consists of a simple plain JSON object, where each attribute of the object will be mapped to an attribute -in the NGSI entity. The value of all the attributes will be copied as a String (as all simple attribute values in -NGSIv1 are strings). E.g.: + +The payload consists of a simple plain JSON object, where each attribute of the object will be mapped to an attribute in +the NGSI entity. The value of all the attributes will be copied as a String (as all simple attribute values in NGSIv1 +are strings). E.g.: ```json { - "h": "45%", - "t": "23", - "l": "1570" + "h": "45%", + "t": "23", + "l": "1570" } ``` + The attribute names in the payload can be mapped to different attribute names in the entity, by using alias in the device provisioning (see the [Provisioning API](https://github.com/telefonicaid/iotagent-node-lib#provisioningapi) for details). -A device can report new measures to the IoT Platform using an HTTP POST request to the `/iot/json` path with the following -query parameters: -* **i (device ID)**: Device ID (unique for the API Key). -* **k (API Key)**: API Key for the service the device is registered on. -* **t (timestamp)**: Timestamp of the measure. Will override the automatic IoTAgent timestamp (optional). +A device can report new measures to the IoT Platform using an HTTP POST request to the `/iot/json` path with the +following query parameters: + +- **i (device ID)**: Device ID (unique for the API Key). +- **k (API Key)**: API Key for the service the device is registered on. +- **t (timestamp)**: Timestamp of the measure. Will override the automatic IoTAgent timestamp (optional). #### Commands -MQTT devices commands are always push. For HTTP Devices commands to be push they **must** be provisioned with the `endpoint` attribute, that will contain the URL where the IoT Agent will send the received commands. Otherwise the command will be poll. -When using the HTTP transport, the command handling have two flavours: - -* **Push commands**: The request payload format will be a plain JSON, as described -in the "Payload" section. The device will reply with a 200OK response containing the result of the command in the JSON -result format. - -* **Polling commands**: in this case, the Agent does not send any messages to the device, being the later responsible -of retrieving them from the IoTAgent whenever the device is ready to get commands. In order to retrieve commands from -the IoT Agent, the device will send the query parameter 'getCmd' with value '1' as part of a normal measure. As a result -of this action, the IoTAgent, instead of returning an empty body (the typical response to a measurement report), will -return a list of all the commands available for the device, in JSON format: each attribute will represent a command, and -its value the command value. The use of a JSON return object implies that only one value can be returned for each command -(last value will be returned for each one). Implementation imposes another limitation in the available values for the -commands: a command value can't be an empty string, or a string composed exclusively by whitespaces. Whenever the device -has completed the execution of the command, it will send the response in the same way measurements are reported, but using the -**command result format** as exposed in the [Protocol section](#protocol). + +MQTT devices commands are always push. For HTTP Devices commands to be push they **must** be provisioned with the +`endpoint` attribute, that will contain the URL where the IoT Agent will send the received commands. Otherwise the +command will be poll. When using the HTTP transport, the command handling have two flavours: + +- **Push commands**: The request payload format will be a plain JSON, as described in the "Payload" section. The + device will reply with a 200OK response containing the result of the command in the JSON result format. + +- **Polling commands**: in this case, the Agent does not send any messages to the device, being the later responsible + of retrieving them from the IoTAgent whenever the device is ready to get commands. In order to retrieve commands + from the IoT Agent, the device will send the query parameter 'getCmd' with value '1' as part of a normal measure. As + a result of this action, the IoTAgent, instead of returning an empty body (the typical response to a measurement + report), will return a list of all the commands available for the device, in JSON format: each attribute will + represent a command, and its value the command value. The use of a JSON return object implies that only one value + can be returned for each command (last value will be returned for each one). Implementation imposes another + limitation in the available values for the commands: a command value can't be an empty string, or a string composed + exclusively by whitespaces. Whenever the device has completed the execution of the command, it will send the + response in the same way measurements are reported, but using the **command result format** as exposed in the + [Protocol section](#protocol). Some additional remarks regarding polling commands: -* Commands can be also retrieved without needed of sending a mesaure. In other words, the device is not forced to send a -measure in order to get the accumulated commands. However, in this case note that `GET` method is used to carry the -`getCmd=1` query parameter (as they are no actual payload for measures, `POST` wouldn't make too much sense). +- Commands can be also retrieved without needed of sending a mesaure. In other words, the device is not forced to send + a measure in order to get the accumulated commands. However, in this case note that `GET` method is used to carry + the `getCmd=1` query parameter (as they are no actual payload for measures, `POST` wouldn't make too much sense). #### Configuration retrieval + The protocol offers a mechanism for the devices to retrieve its configuration (or any other value it needs from those stored in the Context Broker). This mechanism combines calls to the IoTA HTTP endpoint with direct calls to the provided device endpoint. ##### Configuration commands + The IoT Agent listens in this path for configuration requests coming from the device: -``` +```text http://:/configuration/commands ``` + The messages must contain a JSON document with the following attributes: -* **type**: indicates the type of command the device is sending. See below for accepted values. -* **fields**: array with the names of the values to be retrieved from the Context Broker entity representing the device. +- **type**: indicates the type of command the device is sending. See below for accepted values. +- **fields**: array with the names of the values to be retrieved from the Context Broker entity representing the + device. This command will trigger a query to the CB that will, as a result, end up with a new request to the device endpoint, with the `configuration/values` path (described bellow). E.g.: + ```json { - "type": "configuration", - "fields": [ - "sleepTime", - "warningLevel" - ] + "type": "configuration", + "fields": ["sleepTime", "warningLevel"] } ``` There are two accepted values for the configuration command types: -* `subscription`: this command will generate a subscription in the Context Broker that will be triggered whenever any of -the selected values change. In case the value has changed, all the attributes will be retrieved. -* `configuration`: this commands will generate a single request to the Context Broker from the IoTAgent, that will trigger -a single request to the device endpoint. + +- `subscription`: this command will generate a subscription in the Context Broker that will be triggered whenever any + of the selected values change. In case the value has changed, all the attributes will be retrieved. +- `configuration`: this commands will generate a single request to the Context Broker from the IoTAgent, that will + trigger a single request to the device endpoint. ##### Configuration information retrieval + Every device should listen in the following path, so it can receive configuration information: -``` + +```text /configuration/values ``` + Whenever the device requests any information from the IoTA, the information will be posted in this path. The information is sent in the same format used in multiple measure reporting: a plain JSON with an attribute per value requested. An additional parameter called `dt` is added with the system current time. E.g.: + ```json { - "sleepTime": "200", - "warningLevel": "80", - "dt": "20160125T092703Z" + "sleepTime": "200", + "warningLevel": "80", + "dt": "20160125T092703Z" } ``` ### MQTT binding + MQTT binding is based on the existence of a MQTT broker and the usage of different topics to separate the different destinations and types of the messages (the different possible interactions are described in the following sections). All the topics used in the protocol are prefixed with the APIKey of the device group and the Device ID of the device -involved in the interaction; i.e.: there is a different set of topics for each service (e.g: `/FF957A98/MyDeviceId/attrs`). -The API Key is a secret identifier shared among all the devices of a service, and the DeviceID is an ID that uniquely -identifies the device in a service. API Keys can be configured with the IoTA Configuration API or the public default -API Key of the IoT Agent can be used in its stead. The Device ID must be provisioned in advance in the IoT Agent before -information is sent. +involved in the interaction; i.e.: there is a different set of topics for each service (e.g: +`/FF957A98/MyDeviceId/attrs`). The API Key is a secret identifier shared among all the devices of a service, and the +DeviceID is an ID that uniquely identifies the device in a service. API Keys can be configured with the IoTA +Configuration API or the public default API Key of the IoT Agent can be used in its stead. The Device ID must be +provisioned in advance in the IoT Agent before information is sent. #### Measure reporting + There are two ways of reporting measures: -* **Multiple measures**: In order to send multiple measures, a device can publish a JSON payload to an MQTT topic with the -following structure: +- **Multiple measures**: In order to send multiple measures, a device can publish a JSON payload to an MQTT topic with + the following structure: -``` +```text /{{api-key}}/{{device-id}}/attrs ``` -The message in this case must contain a valid JSON object of a single level; for each key/value pair, the key represents -the attribute name and the value the attribute value. Attribute type will be taken from the device provision information. +The message in this case must contain a valid JSON object of a single level; for each key-value pair, the key represents +the attribute name and the value the attribute value. Attribute type will be taken from the device provision +information. -For instance, if using [Mosquitto](https://mosquitto.org/) with a device with ID `id_sen1`, API Key `ABCDEF` and attribute -IDs `h` and `t`, then all measures (humidity and temperature) are reported this way: +For instance, if using [Mosquitto](https://mosquitto.org/) with a device with ID `id_sen1`, API Key `ABCDEF` and +attribute IDs `h` and `t`, then all measures (humidity and temperature) are reported this way: - $ mosquitto_pub -t /ABCDEF/id_sen1/attrs -m '{"h": 70, "t": 15}' -h -p -u -P +```bash +$ mosquitto_pub -t /ABCDEF/id_sen1/attrs -m '{"h": 70, "t": 15}' -h -p -u -P +``` -* **Single measures**: In order to send single measures, a device can publish the direct value to an MQTT topic with -the following structure: +- **Single measures**: In order to send single measures, a device can publish the direct value to an MQTT topic with + the following structure: -``` +```text /{{api-key}}/{{device-id}}/attrs/ ``` Indicating in the topic the name of the attribute to be modified. -In both cases, the key is the one provisioned in the IoT Agent through the Configuration API, and the Device ID the ID that -was provisioned using the Provisioning API. API Key **must** be present, although can be any string in case the Device was -provisioned without a link to any particular configuration. +In both cases, the key is the one provisioned in the IoT Agent through the Configuration API, and the Device ID the ID +that was provisioned using the Provisioning API. API Key **must** be present, although can be any string in case the +Device was provisioned without a link to any particular configuration. -For instance, if using [Mosquitto](https://mosquitto.org/) with a device with ID `id_sen1`, API Key `ABCDEF` and attribute -IDs `h` and `t`, then humidity measures are reported this way: +For instance, if using [Mosquitto](https://mosquitto.org/) with a device with ID `id_sen1`, API Key `ABCDEF` and +attribute IDs `h` and `t`, then humidity measures are reported this way: ```bash $ mosquitto_pub -t /ABCDEF/id_sen1/attrs/h -m 70 -h -p -u -P ``` #### Configuration retrieval + The protocol offers a mechanism for the devices to retrieve its configuration (or any other value it needs from those stored in the Context Broker). Two topics are created in order to support this feature: a topic for configuration -commands and a topic to receive configuration information. This mechanism can be enabled or disabled using a configuration -flag, `configRetrieval`. +commands and a topic to receive configuration information. This mechanism can be enabled or disabled using a +configuration flag, `configRetrieval`. This mechanism and the bidirectionality plugin cannot be simultaneously activated. ##### Configuration command topic -``` + +```text /{{apikey}}/{{deviceid}}/configuration/commands ``` -The IoT Agent listens in this topic for requests coming from the device. The messages must contain a JSON document -with the following attributes: -* **type**: indicates the type of command the device is sending. See below for accepted values. -* **fields**: array with the names of the values to be retrieved from the Context Broker entity representing the device. +The IoT Agent listens in this topic for requests coming from the device. The messages must contain a JSON document with +the following attributes: + +- **type**: indicates the type of command the device is sending. See below for accepted values. +- **fields**: array with the names of the values to be retrieved from the Context Broker entity representing the + device. -This command will trigger a query to the CB that will, as a result, end up with a new message posted to the Configuration -information topic (described bellow). +This command will trigger a query to the CB that will, as a result, end up with a new message posted to the +Configuration information topic (described bellow). E.g.: + ```json { - "type": "configuration", - "fields": [ - "sleepTime", - "warningLevel" - ] + "type": "configuration", + "fields": ["sleepTime", "warningLevel"] } ``` There are two accepted values for the configuration command types: -* `subscription`: this command will generate a subscription in the Context Broker that will be triggered whenever any of -the selected values change. In case the value has changed, all the attributes will be retrieved. -* `configuration`: this commands will generate a single request to the Context Broker from the IoTAgent, that will trigger -a single publish message in the values topic. + +- `subscription`: this command will generate a subscription in the Context Broker that will be triggered whenever any + of the selected values change. In case the value has changed, all the attributes will be retrieved. +- `configuration`: this commands will generate a single request to the Context Broker from the IoTAgent, that will + trigger a single publish message in the values topic. ##### Configuration information topic -``` + +```text /{{apikey}}/{{deviceid}}/configuration/values ``` + Every device must subscribe to this topic, so it can receive configuration information. Whenever the device requests any information from the IoTA, the information will be posted in this topic. The information is published in the same format used in multiple measure reporting: a plain JSON with an attribute per value requested. An aditional parameter called `dt` is added with the system current time. E.g.: + ```json { - "sleepTime": "200", - "warningLevel": "80", - "dt": "20160125T092703Z" + "sleepTime": "200", + "warningLevel": "80", + "dt": "20160125T092703Z" } ``` #### Commands -The IoT Agent implements IoTAgent commands, as specified in the [IoTAgent library](https://github.com/telefonicaid/iotagent-node-lib). + +The IoT Agent implements IoTAgent commands, as specified in the +[IoTAgent library](https://github.com/telefonicaid/iotagent-node-lib). Commands using the MQTT transport protocol binding always work in PUSH mode: the server publishes a message in a topic -where the device is subscribed: the *commands topic*. Once the device has finished with the command, it publishes it result -to another topic. +where the device is subscribed: the _commands topic_. Once the device has finished with the command, it publishes it +result to another topic. When a command is receivied in the IoT Agent, a message is published in the following topic: -``` + +```text ///cmd ``` -The message payload is a plain JSON object, with an attribute per command, and the parameters of the command as the value -of that attribute. + +The message payload is a plain JSON object, with an attribute per command, and the parameters of the command as the +value of that attribute. Once the device has executed the command, the device can report the result information publishing a new mesage in the following topic: -``` + +```text ///cmdexe ``` @@ -261,31 +293,31 @@ to the Context Broker regarding an entity called `sen1` of type `sensor`: ```json { - "updateAction": "UPDATE", - "contextElements": [ - { - "id": "sen1", - "type": "sensor", - "isPattern": "false", - "attributes": [ + "updateAction": "UPDATE", + "contextElements": [ { - "name": "ping", - "type": "command", - "value": { - "data": "22" - } + "id": "sen1", + "type": "sensor", + "isPattern": "false", + "attributes": [ + { + "name": "ping", + "type": "command", + "value": { + "data": "22" + } + } + ] } - ] - } - ] + ] } ``` -If the API key associated to de device is `ABCDEF`, and the device ID related to `sen1` entity is `id_sen1`, this -will generate a message in the `/ABCDEF/id_sen1/cmd` topic with the following payload: +If the API key associated to de device is `ABCDEF`, and the device ID related to `sen1` entity is `id_sen1`, this will +generate a message in the `/ABCDEF/id_sen1/cmd` topic with the following payload: ```json -{"ping":{"data":"22"}} +{ "ping": { "data": "22" } } ``` If using [Mosquitto](https://mosquitto.org/), such a command is received by running the `mosquitto_sub` script: @@ -301,7 +333,7 @@ Once the device has executed the command, it can publish its results in the `/AB payload with the following format: ```json -{"ping": "1234567890"} +{ "ping": "1234567890" } ``` If using [Mosquitto](https://mosquitto.org/), such command result is sent by running the `mosquitto_pub` script: @@ -314,27 +346,28 @@ In the end, Context Broker will have updated the values of `ping_info` and `ping respectively. `ping` attribute is never updated. #### Bidirectionality Syntax + The latest versions of the Provisioning API allow for the definition of reverse expressions to keep data shared between -the Context Broker and the device in sync (regardless of whether the data originated in plain data from the device or -in a transformation expression in the IoTAgent). In this cases, when a reverse expression is defined, whenever the +the Context Broker and the device in sync (regardless of whether the data originated in plain data from the device or in +a transformation expression in the IoTAgent). In this cases, when a reverse expression is defined, whenever the bidirectional attribute is modified, the IoTAgent sends a command to the original device, with the name defined in the reverse expression attribute and the ID of the device (see Commands Syntax, just above). #### AMQP binding -[AMQP](https://www.amqp.org/) stands for Advance Message Queuing Protocol, and is one of the most popular protocols for message-queue systems. -Although the protocol itself is software independent and allows for a great architectural flexibility, this transport -binding has been designed to work with the [RabbitMQ](https://www.rabbitmq.com/) broker, in a way that closely -resembles the MQTT binding (in the previous section). In fact, for IoT Platform deployments in need of an scalable MQTT -Broker, RabbitMQ with the MQTT plugin will be used, connecting the IoT Agent to RabbitMQ through AMQP and the clients -to RabbitMQ through MQTT. +[AMQP](https://www.amqp.org/) stands for Advance Message Queuing Protocol, and is one of the most popular protocols for +message-queue systems. Although the protocol itself is software independent and allows for a great architectural +flexibility, this transport binding has been designed to work with the [RabbitMQ](https://www.rabbitmq.com/) broker, in +a way that closely resembles the MQTT binding (in the previous section). In fact, for IoT Platform deployments in need +of an scalable MQTT Broker, RabbitMQ with the MQTT plugin will be used, connecting the IoT Agent to RabbitMQ through +AMQP and the clients to RabbitMQ through MQTT. -The binding connects the IoT Agent to an exchange (usually `amq.topic`) and creates two queues (to share between all -the instances of the IoTAgents in a cluster environment): one for the incoming measures, and another for command -result update messages (named as the measure one, adding the `_commands` sufix). +The binding connects the IoT Agent to an exchange (usually `amq.topic`) and creates two queues (to share between all the +instances of the IoTAgents in a cluster environment): one for the incoming measures, and another for command result +update messages (named as the measure one, adding the `_commands` sufix). -For both measure reporting and command update status the mechanism is much the same as in the case of the MQTT binding: all -the messages must be published to the selected exchange, using the following routing keys: +For both measure reporting and command update status the mechanism is much the same as in the case of the MQTT binding: +all the messages must be published to the selected exchange, using the following routing keys: | Key pattern | Meaning | | ------------------------------------- | -------------------------- | @@ -346,36 +379,46 @@ the messages must be published to the selected exchange, using the following rou The payload is the same as for the other bindings. ### Value conversion + The IoTA may perform some ad-hoc conversion for specific types of values, in order to minimize the parsing logic in the device. This section lists those conversions. #### Timestamp compression -Any attribute coming to the IoTA with the "timeInstant" name will be expected to be a timestamp in ISO8601 complete basic -calendar representation (e.g.: 20071103T131805). The IoT Agent will automatically transform this values to the extended -representation (e.g.: +002007-11-03T13:18:05) for any interaction with the Context Broker (updates and queries). + +Any attribute coming to the IoTA with the "timeInstant" name will be expected to be a timestamp in ISO8601 complete +basic calendar representation (e.g.: 20071103T131805). The IoT Agent will automatically transform this values to the +extended representation (e.g.: +002007-11-03T13:18:05) for any interaction with the Context Broker (updates and +queries). This feature can be enabled and disabled by using the `compressTimestamp` configuration flag. ### Thinking Things plugin -This IoT Agent retains some features from the Thinking Things Protocol IoT Agent to ease the transition from one protocol -to the other. This features are built in a plugin, that can be activated using the `mqtt.thinkingThingsPlugin` flag. -When the plugin is activated, the following rules apply to all the incoming MQTT-JSON requests: -* If an attribute named P1 is found, its content will be parsed as a Phone Cell position, as described [here](https://github.com/telefonicaid/iotagent-thinking-things#p1). -* If an attribute named C1 is found, its content will be parsed as if they would be a P1 attribute, but with all its -fields codified in hexadecimal with a fixed 4 character length, without comma separation. -* If an attribute named B is found, its content will be parsed as if they would be Battery information as described -[here](https://github.com/telefonicaid/iotagent-thinking-things#b). This implementation admits also an extended version -of this attribute, adding the "batteryType" and "percentage" fields to the entity. - - -## Development documentation + +This IoT Agent retains some features from the Thinking Things Protocol IoT Agent to ease the transition from one +protocol to the other. This features are built-in a plugin, that can be activated using the `mqtt.thinkingThingsPlugin` +flag. When the plugin is activated, the following rules apply to all the incoming MQTT-JSON requests: + +- If an attribute named P1 is found, its content will be parsed as a Phone Cell position, as described + [here](https://github.com/telefonicaid/iotagent-thinking-things#p1). +- If an attribute named C1 is found, its content will be parsed as if they would be a P1 attribute, but with all its + fields codified in hexadecimal with a fixed 4 character length, without comma separation. +- If an attribute named B is found, its content will be parsed as if they would be Battery information as described + [here](https://github.com/telefonicaid/iotagent-thinking-things#b). This implementation admits also an extended + version of this attribute, adding the "batteryType" and "percentage" fields to the entity. + +## Development documentation + ### Contributions -All contributions to this project are welcome. Developers planning to contribute should follow the [Contribution Guidelines](./docs/contribution.md) + +All contributions to this project are welcome. Developers planning to contribute should follow the +[Contribution Guidelines](contribution.md) ### Project build + The project is managed using npm. For a list of available task, type + ```bash npm run ``` @@ -383,7 +426,8 @@ npm run The following sections show the available options in detail. ### Testing -[Mocha](http://visionmedia.github.io/mocha/) Test Runner + [Should.js](https://shouldjs.github.io/) Assertion Library. + +[Mocha](https://mochajs.org/) Test Runner + [Should.js](https://shouldjs.github.io/) Assertion Library. The test environment is preconfigured to run BDD testing style. @@ -396,10 +440,10 @@ npm test ``` ### Coding guidelines + jshint -Uses provided .jshintrc flag file. -To check source code style, type +Uses provided .jshintrc flag file. To check source code style, type ```bash npm run lint @@ -407,8 +451,7 @@ npm run lint ### Continuous testing -Support for continuous testing by modifying a src file or a test. -For continuous testing, type +Support for continuous testing by modifying a src file or a test. For continuous testing, type ```bash npm run test:watch @@ -421,6 +464,7 @@ npm run watch ``` ### Code Coverage + Istanbul Analizes the code coverage of your tests. @@ -432,9 +476,29 @@ To generate an HTML coverage report under `site/coverage/` and to print out a su npm run test:coverage ``` +### Documentation guidelines + +remark + +To check consistency of the Markdown markup, type + +```bash +npm run lint:md +``` + +textlint + +Uses the provided `.textlintrc` flag file. To check for spelling and grammar errors, dead links and keyword consistency, +type + +```bash +npm run lint:text +``` + ### Clean -Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is restored. +Removes `node_modules` and `coverage` folders, and `package-lock.json` file so that a fresh copy of the project is +restored. ```bash # Use git-bash on Windows @@ -451,9 +515,17 @@ placement and breakup of long lines etc.) within the codebase. npm run prettier ``` +To ensure consistent Markdown formatting run the following: + +```bash +# Use git-bash on Windows +npm run prettier:text +``` + ## New transport development ### Overview + This IoT Agent is prepared to serve its protocol (Plain JSON) over multiple transport protocols (MQTT, HTTP...), sharing most of the code betweend the different protocols. To do so, all the transport-specific code is encapsulated in a series of plugins, added to the `./bindings/` folder. Each plugin must consist of a single Node.js module with the API defined @@ -461,17 +533,20 @@ in the section below. The IoTA scans this full directory upon start, so there is simple restart should be enough). In order to distinguish which device uses which attribute, a new field, `transport`, will be added to the device -provisioning. When a command or a notification arrives to the IoTAgent, this field is read to guess what plugin to invoke -in order to execute the requested task. If the field is not found, the value of the configuration parameter +provisioning. When a command or a notification arrives to the IoTAgent, this field is read to guess what plugin to +invoke in order to execute the requested task. If the field is not found, the value of the configuration parameter `defaultTransport` will be used instead. In order to associate a module with a device, the value of the `transport` attribute of the device provisioning must match the value of the `protocol` field of the binding. ### API + Every plugin in the `plugins/` folder must adhere to the following API (exporting the following functions and attributes). #### function start(callback) + ##### Description + Start the binding, doing all the appropriate initializations. The configuration is not passed as a parameter, so it should be retrieved from the configuration service. @@ -479,30 +554,39 @@ All the functions are passed a callback, that **must** be called once the action itself is not described (in that case, the standard Node.js for callbacks applies). #### function stop(callback) + ##### Description + Stops all the resources created in the `start()` function, releasing the resources when needed. #### function sendConfigurationToDevice(apiKey, deviceId, results, callback) + ##### Description + Send to the device the configuration information requested from the Context Broker. ##### Parameters -* **apiKey**: API Key of the device that is requesting the information. -* **deviceId**: Device ID of the device that is requesting the information. -* **results**: Array containing the results of the query to the Context Broker. + +- **apiKey**: API Key of the device that is requesting the information. +- **deviceId**: Device ID of the device that is requesting the information. +- **results**: Array containing the results of the query to the Context Broker. #### function executeCommand(apiKey, device, serializedPayload, callback) + ##### Description + Execute a command in a remote device with the specified payload. ##### Parameters -* **apiKey**: API Key of the device that is requesting the information. -* **device**: Object containing all the data of the device that is requesting the information. -* **serializedPayload**: String serialization of the command identification and parameters that is going to be send -using the transport protocol. + +- **apiKey**: API Key of the device that is requesting the information. +- **device**: Object containing all the data of the device that is requesting the information. +- **serializedPayload**: String serialization of the command identification and parameters that is going to be send + using the transport protocol. #### protocol + The `protocol` attribute is a single constant string attribute that will be used to identify the transport for a certain -device. This parameter is mainly used when a command or notification comes to the IoT Agent, as the device itself is -in charge of selecting its endpoint for incoming active measures or actions. The value of the `protocol` attribute for -a binding must match the `transport` field in the provisioning of each device that will be using the IoTA. +device. This parameter is mainly used when a command or notification comes to the IoT Agent, as the device itself is in +charge of selecting its endpoint for incoming active measures or actions. The value of the `protocol` attribute for a +binding must match the `transport` field in the provisioning of each device that will be using the IoTA. diff --git a/package.json b/package.json index c585bb48..0f944140 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,10 @@ "test": "mocha --recursive 'test/**/*.js' --reporter spec --timeout 3000 --ui bdd --exit", "test:watch": "npm run test -- -w ./lib", "lint": "jshint lib/ --config .jshintrc && jshint test/ --config test/.jshintrc", + "lint:md": "remark -f 'README.md' docs", + "lint:text": "textlint 'README.md' 'docs/*.md' 'docs/**/*.md'", "prettier": "prettier --config .prettierrc.json --write '**/**/**/*.js' '**/**/*.js' '**/*.js' '*.js'", + "prettier:text": "prettier 'README.md' 'docs/*.md' 'docs/**/*.md' --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", "test:coverage": "istanbul cover _mocha -- --recursive 'test/**/*.js' --reporter spec --exit", "test:coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", "watch": "watch 'npm test && npm run lint' ./lib ./test" @@ -32,17 +35,24 @@ "devDependencies": { "coveralls": "~3.0.2", "husky": "~1.1.0", + "istanbul": "~0.4.5", + "jshint": "~2.9.6", "lint-staged": "~7.3.0", - "nock": "10.0.1", "mocha": "5.2.0", - "should": "13.2.3", - "sinon": "~6.1.0", - "istanbul": "~0.4.5", + "nock": "10.0.1", "prettier": "~1.14.2", "proxyquire": "2.1.0", + "remark-cli": "~6.0.1", + "remark-preset-lint-recommended": "~3.0.2", "moment": "~2.22.2", - "watch": "~1.0.2", - "jshint": "~2.9.6" + "textlint": "~11.0.1", + "textlint-rule-common-misspellings": "~1.0.1", + "textlint-rule-no-dead-link": "~4.4.1", + "textlint-rule-terminology": "~1.1.30", + "textlint-rule-write-good": "~1.6.2", + "should": "13.2.3", + "sinon": "~6.1.0", + "watch": "~1.0.2" }, "keywords": [], "dependencies": { @@ -66,6 +76,23 @@ "*.js": [ "prettier --config .prettierrc.json --write", "git add" + ], + "*.md": [ + "prettier --no-config --tab-width 4 --print-width 120 --write --prose-wrap always", + "git add" + ], + "*.yml": [ + "prettier --no-config --write", + "git add" + ] + }, + "remarkConfig": { + "settings": { + "bullet": "-", + "paddedTable": true + }, + "plugins": [ + "remark-preset-lint-recommended" ] } }