🙆‍♀️

UIFlow2でUDPを使って、Float型の値をOSC形式で送る(M5stickCplus2)

に公開

前提と流れ

OSC形式というのはUDPのソケット通信で送る中身の書式というだけなので、特別なライブラリなくとも書くことができ、実際にUIFlowで制御できたという例を知った。(ありがたい記事↓)

VRChatがOSCに対応したので、M5StackのUIFLowでライブラリなしのOSC通信してみた
https://zenn.dev/tkyko13/articles/2debed47b51080

しかし、今回僕は UIFlow2、かつ、Floatの値を送信 したかったため、

  1. UIFlow2にはコードを実行(Exec Code)がない
  2. 上記事で付け足してる記号のことがよくわからん
  3. 少なくとも内部機能のUDP送信で、そのままうつすだけだけだと、True,Falseすら送れなかった
    (なんかOSCの受け取り先でサイズが違う?というエラーが起きた)


となった結果色々調べると、Alpha版ではあるが、Custom Block機能(自分ででコードブロックを作れる機能)があるらしい。今回はこれを使って、3個のノードで送れるようになった。

  • Initノード
  • IPアドレスポートを指定するノード
  • UDPで送る /M5stickCplus2/Dist + Float値

自身のコーディング経験が少ないため、興ざめなことにChatGPT全頼りなので、一部不必要なコード等あるかもしれないですが、逆に誰でも改変できるということなので少し用途が違う人も試してみてください。

使い方

↓ここからOSCSender.pyとOSCSender.m5b2をダウンロードしてください
https://www.dropbox.com/scl/fo/vmuqjs00ua3xoubxhp1ps/AFHVVs3cqoESwhSle_8o5qg?rlkey=wnbe7v9nacrr6250xxwg8s0ua&st=bv71kh5x&dl=0

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