UIFlow2でUDPを使って、Float型の値をOSC形式で送る(M5stickCplus2)
前提と流れ
OSC形式というのはUDPのソケット通信で送る中身の書式というだけなので、特別なライブラリなくとも書くことができ、実際にUIFlowで制御できたという例を知った。(ありがたい記事↓)
VRChatがOSCに対応したので、M5StackのUIFLowでライブラリなしのOSC通信してみた
・https://zenn.dev/tkyko13/articles/2debed47b51080
しかし、今回僕は UIFlow2、かつ、Floatの値を送信 したかったため、
- UIFlow2にはコードを実行(Exec Code)がない
- 上記事で付け足してる記号のことがよくわからん
- 少なくとも内部機能のUDP送信で、そのままうつすだけだけだと、True,Falseすら送れなかった
(なんかOSCの受け取り先でサイズが違う?というエラーが起きた)
となった結果色々調べると、Alpha版ではあるが、Custom Block機能(自分ででコードブロックを作れる機能)があるらしい。今回はこれを使って、3個のノードで送れるようになった。
- Initノード
-
IPアドレス
とポート
を指定するノード - UDPで送る
/M5stickCplus2/Dist
+Float値
自身のコーディング経験が少ないため、興ざめなことにChatGPT全頼りなので、一部不必要なコード等あるかもしれないですが、逆に誰でも改変できるということなので少し用途が違う人も試してみてください。
使い方
↓ここからOSCSender.pyとOSCSender.m5b2をダウンロードしてください
UiFlow2(https://uiflow2.m5stack.com/ )を開いて、左下のCustomというのをクリック、
+押して、AddFileからOSCSender.m5b2のほうを入れる。
Confirm押したら追加される
ノードが追加されたので、
こういう感じでやってください、特に、host(xxx.xx.x.xxみたいなやつ)、ポートは自分で設定してください、hostは開いてる側のやつのパソコン内でシステムからネットワークというのを見ればいけます。ポートはどちらも同じになるようにしてください。
これで実行したらうまくいくと思います。
エラーがあったら
OSCSender.pyがないよ、というエラーが出たこともあったのですが、その時には、Run後に、ファイルマークを押して、そこにOSCSender.pyというのがないのが問題なので、SendFile to Hereから、OSCSender.pyの方を手動で追加してください。
作り方など、改変したい場合
OSCSender.pyの中身ををUiFlow2(https://uiflow2.m5stack.com/ )を開いて、左下のCustomというのをクリック押して出てくる、BlockDesigner開いて、上のところからPython選んで貼り付けてUpdateBlocksおして、その後、上のところからBlockに戻って、そしたら左下をクリックして、出てきたとこからソケットの形を後から変えられるんで、そのあと、右上からSave m5b2を押したらいけます。
このコード、実質は、後半の部分だけで、4バイトで区切れるようにつけたしてるのと、値をビッグエンディアンという並べ方?にしているだけなので、がんばればUIFlow2内できる人もいるのかな?わかんないです。というか、ライブラリを手動で追加する?みたいなことができたら、もっと複雑な送り方もできるんですかね、よくわかんないです。
"""
file OscSender
time 2025-05-01
author
email
license
"""
class OscSender:
"""
note:
en: Send float via OSC (UDP)
details:
color: '#ff9900'
link: ''
image: ''
category: Custom
example: ''
"""
def __init__(self):
"""
label:
en: '%1 init'
"""
import socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.host = None # 初期状態では未設定
self.port = None # 初期状態では未設定
def set_host_and_port(self, host: str, port: int = 0):
"""
label:
en: 'Set Adress: %1 host: %2 port: %3'
params:
host:
name: host
type: str
port:
name: port
type: int
default: '0'
"""
self.host = host
self.port = port
def send_float(self, address: str, value: float = 0):
"""
label:
en: 'send Address %1 name %2 value: %3'
params:
address:
name: address
type: str
value:
name: value
type: float
default: '0'
"""
if self.host is None or self.port is None:
raise ValueError("Host and port must be set before sending OSC messages")
import struct
def osc_pad(s):
s_bytes = s.encode('utf-8') + b'\x00'
while len(s_bytes) % 4 != 0:
s_bytes += b'\x00'
return s_bytes
addr = osc_pad(address)
types = osc_pad(",f")
val = struct.pack(">f", value)
msg = addr + types + val
self.sock.sendto(msg, (self.host, self.port))
Discussion