{"id":13506101,"url":"https://github.com/lets-fiware/custom-iotagent-sakuraio","last_synced_at":"2026-01-20T17:55:57.382Z","repository":{"id":101394608,"uuid":"281819009","full_name":"lets-fiware/custom-iotagent-sakuraio","owner":"lets-fiware","description":"IoT Agent for sakura.io (UltraLight  based protocol over sakura.io channels with WebSocket)","archived":false,"fork":false,"pushed_at":"2024-01-01T07:33:34.000Z","size":389,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-01T04:35:03.254Z","etag":null,"topics":["fiware","iot","iot-agent","ngsi","sakuraio"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lets-fiware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-23T01:20:14.000Z","updated_at":"2022-12-30T23:12:54.000Z","dependencies_parsed_at":"2024-01-01T08:54:23.674Z","dependency_job_id":"33521782-cc86-4823-8ee5-ae75be3cf33d","html_url":"https://github.com/lets-fiware/custom-iotagent-sakuraio","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lets-fiware%2Fcustom-iotagent-sakuraio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lets-fiware%2Fcustom-iotagent-sakuraio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lets-fiware%2Fcustom-iotagent-sakuraio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lets-fiware%2Fcustom-iotagent-sakuraio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lets-fiware","download_url":"https://codeload.github.com/lets-fiware/custom-iotagent-sakuraio/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246273533,"owners_count":20750904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fiware","iot","iot-agent","ngsi","sakuraio"],"created_at":"2024-08-01T01:00:34.617Z","updated_at":"2026-01-20T17:55:57.335Z","avatar_url":"https://github.com/lets-fiware.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized","Open-Source FIWARE from third parties"],"sub_categories":["Uncategorized","Processing"],"readme":"[![Let's FIWARE Banner](https://github.com/lets-fiware/custom-iotagent-sakuraio/blob/gh-pages/images/lets-fiware-logo-non-free.png)](https://www.letsfiware.jp/)\n\n# Custom IoT Agent for sakura.io\n\n![FIWARE IoT Agents](https://nexus.lab.fiware.org/repository/raw/public/badges/chapters/iot-agents.svg)\n[![License: APGL](https://img.shields.io/github/license/lets-fiware/custom-iotagent-sakuraio.svg)](https://opensource.org/licenses/AGPL-3.0)\n[![NGSI v2](https://img.shields.io/badge/NGSI-v2-5dc0cf.svg)](https://fiware-ges.github.io/orion/api/v2/stable/)\n\nThe custom IoT Agent for sakura.io is a bridge between the [sakura.io](#about-sakuraio)\nWebSocket API and NGSI. It supports the UltraLight based protocol over sakura.io channels\nwith WebSocket. It is based on the [IoT Agent Node.js Library](https://github.com/telefonicaid/iotagent-node-lib).\n\n## Contents\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDetails\u003c/strong\u003e\u003c/summary\u003e\n\n-   [Architecture](#architecture)\n-   [UltraLight based protocol over sakura.io channels format](#ultralight-based-protocol-over-sakuraio-channels-format)\n    -   [Make a custom payload on an IoT device](#make-a-custom-payload-on-an-iot-device)\n    -   [Make attributes on IoT Agent](#make-attributes-on-iot-agent)\n-   [How to build a docker container image](#how-to-build-a-docker-container-image)\n-   [How to run](#how-to-run)\n-   [Iot Device](#iot-device)\n-   [About sakura.io](#about-sakuraio)\n    -   [Reference](#reference)\n-   [Third-party library](#third-party-library)\n-   [Copyright and License](#copyright-and-license)\n\n\u003c/details\u003e\n\n## Architecture\n\nThe custom IoT Agent for sakura.io can exchange the UltraLight based messages with devices by communicating with\nthe sakura.io platform. The transport mechanism between the IoT Agent and the sakura.io platform is WebSocket.\nThe sakura.io platform plays the role of a server and the IoT Agent plays the role of a client in the WebSocket\ncommunication. The message format is the sakura.io channels which wrap a UltraLight payload.\n\n![](https://github.com/lets-fiware/custom-iotagent-sakuraio/blob/gh-pages/images/iota-sakuraio-architecture-non-free.png)\n\nIn the current version, the custom IoT Agent for sakura.io supports the active attributes. The lazy attributes\nand commands are not supported yet.\n\n## UltraLight based protocol over sakura.io channels format\n\nThe custom IoT Agent for sakura.io supports the following measure payload syntax. It is composed of a list of\nkey-value pairs separated by the `|` character. E.g.:\n\n```\nt|32.63|h|34.44|p|1001.49\n```\n\n### Make a custom payload on an IoT device\n\nAn IoT Device makes a custom payload as shown:\n\n```\nA1234?t|32.63|h|34.44|p|1001.49A\n```\n\nAn IoT Device makes a custom payload. It is concatenated an `api key` and a UltraLight payload with `?` \nand it is added a header and a trailer to confirm the integrity of data and to indicate which is an attribute type.\nA 'A' indicates an active attribute.\n\nThe sakura.io channels has multiple channels. The channel can be stored 8 bytes of hex data so that a payload is\ndivided into 8 bytes as shown:\n\n| Custom payload | sakura.io channels | hex              |\n| -------------- | ------------------ | ---------------- |\n| A1234?t\\|      | channel 0          | 41313233343f747c |\n| 32.63\\|h\\|     | channel 1          | 33322e36337c687c |\n| 34.44\\|p\\|     | channel 2          | 33342e34347c707c |\n| 1001.49A       | channel 3          | 313030312e343941 |\n\nThe following is an encode routine run in an IoT device.\n\n```\nkey = os.environ.get('IOTA_KEY', '1234');\ntemperature = bme280.get_temperature()\npressure = bme280.get_pressure()\nhumidity = bme280.get_humidity()\n\nmeasures = 'A{}?t|{:05.2f}|h|{:05.2f}|p|{:05.2f}A'.format(key, temperature, humidity, pressure)\n\nfor i in range(math.ceil(len(measures) / 8)):\n    sakuraio.enqueue_tx(i, measures[i * 8:i * 8 + 8])\nsakuraio.send()\n```\n\n### Make attributes on IoT Agent\n\nThe IoT Agent receives the following JSON data from the sakura.io platform as shown:\n\n```\n{\n  \"module\": \"xCr8vqsJ0Zbe\",\n  \"type\": \"channels\",\n  \"datetime\": \"2020-07-28T08:09:49.266964572Z\",\n  \"payload\": {\n    \"channels\": [\n      {\n        \"channel\": 0,\n        \"type\": \"b\",\n        \"value\": \"41313233343f747c\",\n        \"datetime\": \"2020-07-28T08:09:49.167965338Z\"\n      },\n      {\n        \"channel\": 1,\n        \"type\": \"b\",\n        \"value\": \"33322e36337c687c\",\n        \"datetime\": \"2020-07-28T08:09:49.192965338Z\"\n      },\n      {\n        \"channel\": 2,\n        \"type\": \"b\",\n        \"value\": \"33342e34347c707c\",\n        \"datetime\": \"2020-07-28T08:09:49.217965338Z\"\n      },\n      {\n        \"channel\": 3,\n        \"type\": \"b\",\n        \"value\": \"313030312e343941\",\n        \"datetime\": \"2020-07-28T08:09:49.242965338Z\"\n      }\n    ]\n  }\n}\n```\n\nThe `module` attribute value in the JSON data is a device ID. To decode a custom payload, the IoT Agent\nconcatenates hex data divided into each channel in the JSON data and converts the hex data to a string.\nThe following is an decode routine.\n\n```\nlet hex = '';\nfor (let i = 0; i \u003c payload.channels.length; i++) {\n    if (payload.channels[i].channel == 0) {\n        hex = '';\n    }\n    hex +=  payload.channels[i].value;\n}\nconst bin = Uint8Array.from(Buffer.from(hex, \"hex\"));\nconst index = bin.indexOf(0);\nlet ul = new TextDecoder().decode((index == -1) ? bin : bin.subarray(0, index));\n\niotAgentLib.logModule.debug(context,`${ul}`);\n\nif (ul.slice(0 ,1) != ul.slice(-1)) {\n    iotAgentLib.logModule.error(context,`Data integrity error: ${ul}`);\n    return;\n}\nul = ul.slice(1).slice(0, -1);\n\nconst query = {\n    i : data.module,                    // device ID\n    k : ul.slice(0, ul.indexOf('?')),   // API key\n    d : ul.slice(ul.indexOf('?') + 1),  // Ultralight payload\n    t: payload.channels[0].datetime\n};\n```\n\nAs a result, the following data can be retrieved from the JSON data.\n\n```\n{\n  \"i\": \"xCr8vqsJ0Zbe\",\n  \"k\": \"1234\",\n  \"d\": \"t|32.63|h|34.44|p|1001.49\",\n  \"t\": \"2020-07-28T08:09:49.167965338Z\"\n}\n```\n\nFinally, the IoT Agent calls the parseUl function to parse UltaLight payload and make attributes.\n\n```\n[\n  {\n    \"name\": \"temperature\",\n    \"type\": \"Number\",\n    \"value\": 32.63,\n    \"metadata\": {\n      \"TimeInstant\": {\n        \"type\": \"DateTime\",\n        \"value\": \"2020-07-28T08:09:49.167Z\"\n      }\n    }\n  },\n  {\n    \"name\": \"relativeHumidity\",\n    \"type\": \"Number\",\n    \"value\": 34.44,\n    \"metadata\": {\n      \"TimeInstant\": {\n        \"type\": \"DateTime\",\n        \"value\": \"2020-07-28T08:09:49.167Z\"\n      }\n    }\n  },\n  {\n    \"name\": \"atmosphericPressure\",\n    \"type\": \"Number\",\n    \"value\": 1001.49,\n    \"metadata\": {\n      \"TimeInstant\": {\n        \"type\": \"DateTime\",\n        \"value\": \"2020-07-28T08:09:49.167Z\"\n      }\n    }\n  }\n]\n```\n\n## How to build a docker container image\n\nRun the following commands to build a docker container image for IoT Agent for sakura.io.\n\n```\ncd docker\nmake build\n```\n\nThe IoT Agent container is driven by environment variables as shown:\n\n| Key                   | Value                   | Description                                                                                                                                           |\n| --------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| IOTA_WEBSOCKET        | `ws://localhost:8080/`  | The sakura.io WebSocket URL                                                                                                                           |\n| IOTA_CB_HOST          | `orion`                 | Hostname of the context broker to update context                                                                                                      |\n| IOTA_CB_PORT          | `1026`                  | Port that context broker listens on to update context                                                                                                 |\n| IOTA_NORTH_PORT       | `4041`                  | Port used for Configuring the IoT Agent and receiving context updates from the context broker                                                         |\n| IOTA_REGISTRY_TYPE    | `mongodb`              | Whether to hold IoT device info in memory or in a database                                                                                            |\n| IOTA_MONGO_HOST       | `mongo`                 | The hostname of mongoDB - used for holding device information                                                                                         |\n| IOTA_MONGO_PORT       | `27017`                 | The port mongoDB is listening on                                                                                                                      |\n| IOTA_MONGO_DB         | `iotasakuraio`          | The mongDB database name                                                                                                                              |\n| IOTA_PROVIDER_URL     | `http://iot-agent:4041` | URL passed to the Context Broker when commands are registered, used as a forwarding URL location when the Context Broker issues a command to a device |\n| IOTA_LOG_LEVEL        | `DEBUG`                 | The log level of the IoT Agent                                                                                                                        |\n\n## How to run\n\nThere is the `IOTA_WEBSOCKET` environment variable in docker/docker-compose.yml. Replace the value with a\nWebSocket URL that you get from sakura.io control panel and run `docker-compose up -d` in docker directory.\n\n```\nversion: \"3\"\n\nservices:\n\n    orion:\n        image: fiware/orion:2.4.0\n        ports:\n            - 1026:1026\n        depends_on:\n            - mongo\n        command:\n            -dbhost mongo\n            -db orion\n\n    mongo:\n        image: mongo:3.6.16\n        command: --nojournal --smallfiles\n        volumes:\n            - ./data/mongo-data:/data/db\n\n    iot-agent:\n        image: fisuda/custom-iot-agent-sakuraio:latest\n        ports:\n            - 4041:4041\n        depends_on:\n            - mongo\n        environment:\n            - IOTA_LOG_LEVEL=DEBUG\n            # - IOTA_WEBSOCKET=wss://api.sakura.io/ws/v1/00000000-0000-0000-0000-000000000000\n            # - IOTA_CB_HOST=orion\n            # - IOTA_CB_PORT=1026\n            # - IOTA_NORTH_PORT=4041\n            # - IOTA_REGISTRY_TYPE=mongodb\n            # - IOTA_MONGO_HOST=mongo\n            # - IOTA_MONGO_PORT=27017\n            # - IOTA_MONGO_DB=iotasakuraio\n            # - IOTA_SERVICE=openiot\n            # - IOTA_SUBSERVICE=/sakuraio\n            # - IOTA_PROVIDER_URL=http://iot-agent:4041\n            # - IOTA_DEVICE_REGISTRY_DURATION=P1M\n            # - IOTA_DEFAULT_TYPE=Thing\n```\n\n## IoT Device\n\nThe source code of the IoT device that supports this IoT Agent is [here](https://github.com/lets-fiware/fiware-sakuraio)\n(FIWARE-sakuraio - Github).\n\n\n## About sakura.io\n\n[SAKURA internet Inc.](https://www.sakura.ad.jp/en/corporate/) is a provider of internet infrastructures in Japan.\nThey provides [sakura.io service](https://sakura.io/). It's composed of the sakura.io platform and communication module.\nThe communication module supports 4G-LTE data communication and it can be attached on Raspberry Pi, Arduino and so on.\n\n![](https://github.com/lets-fiware/custom-iotagent-sakuraio/blob/gh-pages/images/sakuraio-module-on-raspberrypi-non-free.png)\n\n### Reference\n-    [sakura.io - GitHub](https://github.com/sakuraio)\n-    [sakura.io documents](https://sakura.io/docs/)\n\n## Third-party library\n\nThe following third-party library is used under license:\n\n1.  [iotagent-node-lib](https://github.com/telefonicaid/iotagent-node-lib) - **AGPL-3.0 License**\n    © 2014-2020 Telefonica Investigación y Desarrollo, S.A.U\n2.  [ws: a Node.js WebSocket library](https://github.com/websockets/ws) - **MIT License**\n\n---\n\n## Copyright and License\n\nCopyright (c) 2020-2024 Kazuhito Suda\u003cbr\u003e\nCustom IoT Agent for sakura.io is licensed under [Affero General Public License (GPL) version 3](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flets-fiware%2Fcustom-iotagent-sakuraio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flets-fiware%2Fcustom-iotagent-sakuraio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flets-fiware%2Fcustom-iotagent-sakuraio/lists"}