{"id":13834492,"url":"https://github.com/zkmkarlsruhe/thoscy","last_synced_at":"2026-02-15T22:17:56.465Z","repository":{"id":38949615,"uuid":"486548970","full_name":"zkmkarlsruhe/thoscy","owner":"zkmkarlsruhe","description":"thoscy: THingsboard OSC relaY","archived":false,"fork":false,"pushed_at":"2022-07-28T19:58:57.000Z","size":962,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-08-05T14:15:28.051Z","etag":null,"topics":["intelligent-museum","networking","osc","python","thingsboard","zkm"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zkmkarlsruhe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.txt","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-04-28T10:32:51.000Z","updated_at":"2023-10-09T06:05:14.000Z","dependencies_parsed_at":"2022-09-04T15:13:44.026Z","dependency_job_id":null,"html_url":"https://github.com/zkmkarlsruhe/thoscy","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkmkarlsruhe%2Fthoscy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkmkarlsruhe%2Fthoscy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkmkarlsruhe%2Fthoscy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkmkarlsruhe%2Fthoscy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zkmkarlsruhe","download_url":"https://codeload.github.com/zkmkarlsruhe/thoscy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225618850,"owners_count":17497592,"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":["intelligent-museum","networking","osc","python","thingsboard","zkm"],"created_at":"2024-08-04T14:00:35.717Z","updated_at":"2026-02-15T22:17:56.407Z","avatar_url":"https://github.com/zkmkarlsruhe.png","language":"Python","funding_links":[],"categories":["Integrations"],"sub_categories":["IoT systems"],"readme":"thoscy\n======\n\n![thoscy logo](media/icon.png)\n\n_thoscy: **th**ingsboard **osc** rela**y**_\n\nRelay messages between a ThingsBoard server and OSC.\n\nThis code base has been developed by [ZKM | Hertz-Lab](https://zkm.de/en/about-the-zkm/organization/hertz-lab) as part of the project [»The Intelligent Museum«](#the-intelligent-museum). \n\nCopyright (c) 2022 ZKM | Karlsruhe.  \nCopyright (c) 2022 Dan Wilcox.  \n\nBSD Simplified License.\n\nDescription\n-----------\n\nThis set of scripts act as relay servers for forwarding device events between a ThingsBoard server using MQTT/WebSockets and OSC (Open Sound Control) messages. `thoscy-send` forwards messages from OSC to a ThingsBoard host over MQTT while `thoscy-recv` listens for ThingsBoard device events on a WebSocket and forwards them over OSC. This is useful for creative coding tools which work with OSC messages natively, but do not have built-in MQTT or WebSocket support.\n\nFrom [thingsboard.io](https://thingsboard.io):\n\n\u003eThingsBoard is an open-source IoT platform for data collection, processing, visualization, and device management.\n\u003eIt enables device connectivity via industry standard IoT protocols - MQTT, CoAP and HTTP and supports both cloud and on-premises deployments. ThingsBoard combines scalability, fault-tolerance and performance so you will never lose your data.\n\nFrom [opensoundcontrol.org](OpenSoundControl.org):\n\n\u003eOpenSoundControl (OSC) is a data transport specification (an encoding) for realtime message communication among applications and hardware.\n\nDependencies\n------------\n\n* Python 3\n* [tb-mqtt-client](https://github.com/thingsboard/thingsboard-python-client-sdk)\n* [python-osc](https://github.com/attwad/python-osc)\n* [websockets](https://github.com/aaugustin/websockets)\n* [requests](https://github.com/psf/requests)\n\nSetup\n-----\n\nInstall Python 3, if not already available. For instance, on macOS using [Homebrew](http://brew.sh):\n\n```shell\nbrew install python3\n```\n\nCreate a virtual environment and install the script's dependencies:\n\n```shell\nmake\n```\n\nThingsBoard\n-----------\n\nIf starting with ThingsBoard from scratch, it's highly recommended to first consult the official ThingsBoard Community [Getting Started Guide](https://thingsboard.io/docs/getting-started-guides/helloworld/).\n\nOtherwise, a _very basic_ overview follows.\n\n### Creating a device\n\nBasic steps for creating a device (as of Spring 2022):\n\n1. Create an account \u0026 log into the ThingsBoard server\n2. Click on Devices in the sidebar\n3. In the Devices panel, click the + in the upper right and choose \"Add new device\"\n4. Enter a name (such as \"Test device\", \"Foo\", etc) and click Add\n\nOnce a device is created, sending and receiving via the server host and device access token / id should be possible using the thoscy tools.\n\nAdditionally, to send to multiple devices from a single thoscy-send session, a gateway device is required. Follow the steps to create a new device as before, then:\n\n5. (Optional) In the Devices panel, check \"Is gateway\" for the new gateway device\n\n### Device access token and id\n\nTo find the device access token and id:\n\n1. Log into the ThingsBoard server\n2. Click on Devices in the sidebar\n3. In the Devices panel, choose the device in the list\n4. In the Device details, choose the Details tab\n5. Click either the \"Copy device id\" or \"Copy access token\"\n6. Paste text somewhere on your system, ie. in TexEdit, onto the console, etc\n\n`thoscy-send` uses the device access token\n\n`thoscy-recv` uses the device id \n\n### Watching device telemetry in realtime\n\nTo view the current device telemetry values in \"realtime\" without setting up a ThingsBoard Dashboard:\n\n1. Log into the ThingsBoard server\n2. Click on Devices in the sidebar\n3. In the Devices panel, choose the device in the list\n4. In the Device details, choose the Telemetry tab\n\n_Note: This shows *all* received key/pair pairs, even those not currently in use._\n\nRunning\n-------\n\nSend and receive functionality is split into two separate scripts: `thoscy-send` and `thoscy-recv`.\n\n### thoscy-send\n\n~~~\nusage: thoscy-send.py [-h] [-a ADDRESS] [-p PORT] [-f FILE] [-v] [HOST] [TOKEN] [NAME ...]\n\nOSC -\u003e Thingsboard MQTT relay server\n\npositional arguments:\n  HOST                  ThingsBoard server host name, ie. thingsboard.mydomain.com\n  TOKEN                 ThingsBoard device access token, must be gateway device if providing additional names\n  NAME                  ThingsBoard device name(s), requires gateway device\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -a ADDRESS, --address ADDRESS\n                        OSC receive address, default: 127.0.0.1\n  -p PORT, --port PORT  OSC receive port, default: 7777\n  -f FILE, --file FILE  JSON configuration file\n  -v, --verbose         enable verbose printing, use -vv for debug verbosity\n~~~\n\nStart an OSC send server on the commandline via the virtual environment wrapper script:\n\n    ./thoscy-send HOST TOKEN\n\n`HOST` is the ThingsBoard server host name, ie. thingsboard.mydomain.com.\n\n`TOKEN` is the ThingsBoard device access token (not id).\n\n`NAME` is a ThingsBoard device name string, multiple device names can be given (see section below)\n\nTo stop thoscy-send, use CTRL+C to issue an interrupt signal.\n\n#### Sending\n\nOnce running, thoscy-send automatically parses OSC messages into telemetry messages to send to the device on ThingsBoard via MQTT. Message handling is as follows:\n\nSend single values: `\"/value 123\" -\u003e {\"value\": 123}`\n* Last address component used as entity key\n* First argument uses as entity value\n* Message must contain at least one argument\n\nSend multiple values: `\"/values 1 2 3\" -\u003e {\"values\": [1, 2, 3]}`\n* Last address component used as entity key\n* Arguments used as list\n* Message must contain at least two arguments\n\nSend multiple key/value pairs: `\"/telemetry value1 123 value2 456\" -\u003e {\"value1\": 123, \"value2\": 456}`\n* Last address component `telemetry`\n* Arguments are treated as entity key/value pairs\n* Each argument key must be a string type\n* Message must contain at least two arguments (key/value pair)\n\n#### Multiple-Device Handling\n\nthoscy-send can send to multiple devices through a single ThingsBoard gateway device. Start thoscy-send with the access token to the gateway, then provide one or more device names as shown in the ThingsBoard UI. For example:\n\n    ./thoscy-send thingsboard.zkm.de ABcdeF... \"device 1\" \"device 2\"\n\n_Note: Make sure to escape any names which include spaces by using double-quotes on the commandline._\n\nThe device names are used as the first component in the OSC address: `\"/device1/value 123 -\u003e {\"value\": 123} to \"device 1\"`\n* OSC address must be prepended with the device name prefix\n* Device names are made lowercase and stripped of non-alphanumeric chars, ie. \"device 1\" becomes \"/device1\"\n\nAny device names which do not exist on the ThingsBoard server will automatically be created through the gateway.\n\n### thosy-recv\n\n~~~\nusage: thoscy-recv.py [-h] [--user USER] [--password PASSWORD] [-a ADDRESS] [-p PORT] [-t] [--prefix] [-f FILE] [-v] [HOST] [ID ...]\n\nOSC \u003c- ThingsBoard websocket relay server\n\npositional arguments:\n  HOST                  ThingsBoard server host name, ie. thingsboard.mydomain.com\n  ID                    ThingsBoard device id(s)\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --user USER           ThingsBoard user name\n  --password PASSWORD   ThingsBoard user password\n  -a ADDRESS, --address ADDRESS\n                        OSC send address, default: 127.0.0.1\n  -p PORT, --port PORT  OSC send port, default: 7788\n  -t, --telemetry       send all key/value pairs in a single /telemetry message\n  --prefix              force OSC address device name prefix for single device\n  -f FILE, --file FILE  JSON configuration file\n  -v, --verbose         enable verbose printing, use -vv for debug verbosity\n~~~\n\nStart an OSC receive server on the commandline via the virtual environment wrapper script:\n\n    ./thoscy-recv HOST ID...\n\n`HOST` is the ThingsBoard server host name, ie. thingsboard.mydomain.com\n\n`ID` is a ThingsBoard device id (not access token), multiple device ids can be given (see section below)\n\nTo stop thoscy-recv, use CTRL+C to issue an interrupt signal.\n\n#### Login Credentials\n\nThingsBoard account login credentials are required and can be given via the following (in order of precedence):\n* the `THOSCY_USER` \u0026 `THOSCY_PASS` environment variables\n* a JSON config file\n* the `--user` and `--password` options\n\nIf the user or password are unset, thoscy-recv will ask for each on the commandline when it is run, ex:\n\n~~~\n% ./thoscy-recv --user user@mydomain.com thingsboard.mydomain.com e5a69b00-...\npassword:\n~~~\n\nThe environment variables can be given either directly on the commandline:\n\n    THOSCY_PASS=MYPASSWORD ./thoscy-recv --user user@mydomain.com thingsboard.mydomain.com e5a69b00-...\n\nor via exporting into the current environment, ex. within a script:\n\n```shell\n#! /bin/sh\nexport THOSCY_USER=user@mydomain.com\nexport THOSCY_PASS=MYPASSWORD\nthoscy-recv thingsboard.mydomain.com e5a69b00-...\n```\n\n_Note: neither user nor password are saved between thoscy-recv sessions._\n\n#### Receiving\n\nOnce running, thoscy-recv automatically parses ThingsBoard device telemetry messsages received over a WebSocket into OSC messages. Message handling is as follows:\n\nReceive single values: `{\"value\": 123} -\u003e \"/value 123\"`\n* Key/value pairs sent in individual OSC messages\n* Entity key used as address component\n* JSON key/value pairs are ignored\n\nReceieve multiple values: `{\"values\": [1, 2, 3]} -\u003e \"/values 1 2 3\"`\n* Values in array used sent as message arguments\n* JSON key/value pairs are ignored\n\nReceive multiple key/value pairs: `{\"value1\": 123, \"value2\": 456} -\u003e \"/telemetry value1 123 value2 456\"`\n* Key/value pairs sent in a single OSC message\n* Key/value pairs appended as arguments\n* Value types: string or float\n* JSON key/value pairs are ignored\n\n_Note: Forwarding telemetry messages as a `/telemetry` OSC message with multiple values requires using the `-t/--telemetry` commandline option or JSON config \"telemetry\" key._\n\n#### Multiple-Device Handling\n\nWhen starting thoscy-recv with multiple device ids, the device names are fetched from the server and used as the first component in the OSC address: `{\"value\": 123} from \"device 1\" -\u003e \"/device1/value 123\"`\n* OSC address is prepended with the device name prefix\n* Device names are made lowercase and stripped of non-alphanumeric chars, ie. \"device 1\" becomes \"/device1\"\n\n_Note: When starting thoscy-recv with a **single device**, the device prefix is not used by default. This behavior can be changed via the `--prefix` commandline option or JSON config \"prefix\" key._\n\n### JSON config file\n\nConfiguration variables can be given to either thoscy tool via a JSON file which consists of a dictionary with the following keys/values:\n\n* **host**: _string_, ThingsBoard server host name, ie. thingsboard.mydomain.com\n* **user**: _string_, ThingsBoard user name (receiving)\n* **password**: _string_, ThingsBoard user password (receiving)\n* **verbose**: _bool_, enable verbose printing?\n* **devices**: _dict_, device info dicts by keyname \n  - **name**: _string_, device name as shown in the ThingsBoard UI\n  - **id**: _string_, ThingsBoard device id\n* **send**: _dict_, send-specific values\n  - **address**: _string_, OSC receive address\n  - **port**: _int_, OSC receive port (\u003e1024)\n  - **token**: _string_, ThingsBoard device access token\n  - **devices**: _array_, devices to send to by keyname in the main devices dict\n* **receive**: _dict_, receive-specific values\n  - **address**: _string_, OSC send address\n  - **port**: _int_, OSC send port (\u003e1024)\n  - **telemetry**: _bool_, send key/value pairs in single /telemetry message\n  - **prefix**: _bool_, force OSC address device name prefix for single device\n  - **devices**: _array_, devices to receive from by keyname in the main devices dict\n\n_Note: Values are be overridden when the corresponding commandline option is used._\n\nSimple example:\n\n```json\n{\n    \"host\": \"thingsboard.mydomain.com\",\n    \"devices\": {\n        \"dev1\": {\"name\": \"device 1\", \"id\": \"12345-...\"},\n        \"dev2\": {\"name\": \"device 2\", \"id:\": \"67890-...\"}\n    },\n    \"send\": {\n        \"token\": \"ABcdeF...\",\n        \"devices\": [\"dev1\"]\n    },\n    \"receive\": {\n        \"address\": \"192.168.0.101\",\n        \"devices\": [\"dev2\"]\n    }\n}\n```\n\nA larger example is also included: `doc/config.json`\n\n### Calling Python script directly\n\nThe Python scripts can be called directly without the wrapper script, but requires manually enabling or disabling the virtual environment:\n\nActivate the virtual environment before the first run in a new commandline session:\n\n    source venv/bin/activate\n\nUse:\n\n    ./thoscy-send.py -h\n\nWhen finished, deactivate the virtual environment with:\n\n    deactivate\n\nExample Clients\n---------------\n\n![example use cases](media/example%20use%20cases.png)\n\nA set of example clients are included:\n\n* `pd/sendclient.pd`: Pure Data patch which sends OSC messages\n* `pd/recvclient.pd`: Pure Data patch which receives OSC messages\n\nBoth examples should work together with the default address \u0026 ports on the same localhost:\n\n    pd/sendclient.pd --OSC-\u003e thoscy-send.py ----MQTT---\u003e ThingsBoard server\n    pd/recvclient.pd \u003c-OSC-- thoscy-recv.py \u003c-WebSocket- ThingsBoard server\n\nFirst start thoscy-send or thoscy-recv, then start the affiliated client, ie. sendclient.pd \u0026 thoscy-send. To see data changing on the server, create/open a ThingsBoard Dashboard with widgets that show the device entity values.\n\n### Multi\n\nAdditionally, a set of clients are included for working with multiple devices:\n\n* `pd/multi-sendclient.pd`: Pure Data patch which sends OSC messages\n* `pd/multi-recvclient.pd`: Pure Data patch which receives OSC messages\n\nLike the clients above, they send to and receive from a ThingsBoard server, however these clients work with multiple devices and therefore require that:\n\n1. thoscy-send is started with a gateway device token and one or more device name strings\n2. thoscy-recv is started with one or more device ids\n\n### Loopback\n\nThere is the `pd/loopback.pd` patch which pairs a sender and receiver with basic latency measurement.\n\nTurn on random temperature messages and lower the message frequency in ms to see how quickly messages can be sent and received before matched send/recv pairs start to mix. Add maybe 20-50 ms on top of that for a basic effective update frequency. This value is likely based on network configuration, if sending over a local LAN or over the internet, ThingsBoard server resources, etc.\n\nPython Modules\n--------------\n\nThe MQTT send, WebSocket receive, and OSC \u0026 JSON parsers are written as seaprate Python modules within the `thoscy` library directory and can be reused within other projects.\n\nFor example, to recieve from a ThingsBoard server use the `thoscy/TBReceiver` class which wraps up the authentication and communication with the server.\n\nThe Intelligent Museum\n----------------------\n\nAn artistic-curatorial field of experimentation for deep learning and visitor participation\n\nThe [ZKM | Center for Art and Media](https://zkm.de/en) and the [Deutsches Museum Nuremberg](https://www.deutsches-museum.de/en/nuernberg/information/) cooperate with the goal of implementing an AI-supported exhibition. Together with researchers and international artists, new AI-based works of art will be realized during the next four years (2020-2023).  They will be embedded in the AI-supported exhibition in both houses. The Project „The Intelligent Museum” is funded by the Digital Culture Programme of the [Kulturstiftung des Bundes](https://www.kulturstiftung-des-bundes.de/en) (German Federal Cultural Foundation) and funded by the [Beauftragte der Bundesregierung für Kultur und Medien](https://www.bundesregierung.de/breg-de/bundesregierung/staatsministerin-fuer-kultur-und-medien) (Federal Government Commissioner for Culture and the Media).\n\nAs part of the project, digital curating will be critically examined using various approaches of digital art. Experimenting with new digital aesthetics and forms of expression enables new museum experiences and thus new ways of museum communication and visitor participation. The museum is transformed to a place of experience and critical exchange.\n\n![Logo](media/Logo_ZKM_DMN_KSB.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkmkarlsruhe%2Fthoscy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzkmkarlsruhe%2Fthoscy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkmkarlsruhe%2Fthoscy/lists"}