From 519af0d72e48f83cab8573b5b0e8509c2ed6f0a7 Mon Sep 17 00:00:00 2001 From: vitrinekast Date: Tue, 3 Dec 2024 00:47:51 +0100 Subject: [PATCH] Created barebones translator --- .gitignore | 2 ++ OSC_Tester.pd | 29 +++++++++++++++++++ README.md | 24 ++++++++++++++++ app.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 ++ 5 files changed, 131 insertions(+) create mode 100644 .gitignore create mode 100644 OSC_Tester.pd create mode 100644 README.md create mode 100644 app.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fe8c69 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +venv +secrets.py \ No newline at end of file diff --git a/OSC_Tester.pd b/OSC_Tester.pd new file mode 100644 index 0000000..0bda459 --- /dev/null +++ b/OSC_Tester.pd @@ -0,0 +1,29 @@ +#N canvas 406 119 1010 673 12; +#X msg 191 171 1 2 3; +#X msg 212 220 set dog ferret; +#X text 349 242 creation arguments are OSC address, f 18; +#X msg 208 335 disconnect; +#X obj 178 364 netsend -u -b; +#X obj 178 251 oscformat cat horse pig; +#X obj 195 285 loadbang; +#X text 281 365 send as UDP \, binary; +#X text 327 205 set message changes address, f 15; +#X obj 264 285 bng 19 250 50 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000; +#X obj 172 79 metro 1000; +#X obj 173 108 bng 19 250 50 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000; +#X obj 165 37 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1; +#X msg 195 309 connect 127.0.0.1 5001; +#X msg 198 197 set volume; +#X msg 178 144 40; +#X connect 0 0 5 0; +#X connect 1 0 5 0; +#X connect 3 0 4 0; +#X connect 5 0 4 0; +#X connect 6 0 13 0; +#X connect 9 0 13 0; +#X connect 10 0 11 0; +#X connect 11 0 15 0; +#X connect 12 0 10 0; +#X connect 13 0 4 0; +#X connect 14 0 5 0; +#X connect 15 0 5 0; diff --git a/README.md b/README.md new file mode 100644 index 0000000..f69ad84 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# OSC2MQTT + +This OSC2MQTT translates any OSC message on a server to MQTT. + +The server will listen to ALL OSC messages coming in at a specified port, and forwards these to an MQTT address. +If the OSC address is /synthesizer/volume, it will be forwarded to the MQTADDRESS of OSC/synthesizer/volume, so make sure to subscribe to OSC. + +### Running + +1. Create a secrets.py with the following + +``` +mqtt_username = "yourusername" +mqtt_password = "yourpass" +``` + +2. Need to create a virtual environment for python? `python -m venv venv` & activate using `source venv/bin/activate` +3. Install the needed packages using `pip install -r requirements.txt` +4. Set your OSC & MQTT information in app.py +5. Run `python app.py` + +### Testing + +I've included a small pure data script that can trigger some OSC messages, for testing purposes. Of course, you are more then welcome to use any OSC software you'd like! diff --git a/app.py b/app.py new file mode 100644 index 0000000..bde651a --- /dev/null +++ b/app.py @@ -0,0 +1,74 @@ +import asyncio +import argparse +import math +import secrets +import paho.mqtt.client as mqtt + +from pythonosc.dispatcher import Dispatcher +from pythonosc import osc_server + +import secrets +import paho.mqtt.client as mqtt + +# constants +MY_OSC_SERVER = "127.0.0.1" +MY_OSC_PORT = 5001 +MY_MQTT_SERVER = "mqtt.klank.school" +MY_MQTT_PORT = 7000 +MY_OSC_MQTT_CHANNEL = "OSC" + +mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) + + +def publish(topic, msg): + result = mqttc.publish(topic, msg) + status = result[0] + if not status == 0: + print(f"Failed to send message to topic {topic}") + + +def print_anything(address, args): + print(address, args) + publish(MY_OSC_MQTT_CHANNEL + address, args) + + +def on_connect(client, userdata, flags, reason_code, properties): + publish(MY_OSC_MQTT_CHANNEL + "/activate", "Hai! OSC2MQTT is here!") + + +def on_message(client, userdata, msg): + print(msg.topic + " " + str(msg.payload)) + + +async def main(): + global loop + loop = asyncio.get_running_loop() # Store the main event loop + + dispatcher = Dispatcher() + + dispatcher.map("/*", print_anything) + + server = osc_server.ThreadingOSCUDPServer( + (MY_OSC_SERVER, MY_OSC_PORT), dispatcher) + print("Serving on {}".format(server.server_address)) + + mqttc.on_connect = on_connect + mqttc.on_message = on_message + + mqttc.username_pw_set(secrets.mqtt_username, secrets.mqtt_password) + print("connect to klank.school") + mqttc.connect(MY_MQTT_SERVER, MY_MQTT_PORT, 60) + + # Start the MQTT loop in a background thread + mqttc.loop_start() + + server.serve_forever() + + # asyncio.run_coroutine_threadsafe(do_a_gesture(data.topics[0].removeprefix('main')), loop) + + # # Keep the asyncio event loop running + await asyncio.Event().wait() + + +# Run the main function +asyncio.run(main()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..97d9597 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +paho_mqtt==2.1.0 +python_osc==1.8.3