RaspberryPiとESP32でOSC通信

今日はRaspberryPiとESP32でOSC通信をしてみます!💪

前回の予告通り、UDP通信を基本にOSCのエンコード、デコードで通信をしてみます。UDP通信がバイナリーで送られて来るので、エンコード、デコードのプログラムは自分で作ってしまうこともできるんだけど、ライブリーを見つけたのでそれを使ってみます!

1、RaspberryPI側

import socket
import struct
import time
from contextlib2 import closing
from pythonosc import osc_message_builder
from pythonosc import osc_message

UDP_IP="192.168.43.41"
UDP_PORT=9000
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
sock.bind((UDP_IP,UDP_PORT))
count =0
with closing(sock):
   while True:
       count +=1
       data,addr = sock.recvfrom(1024)
       #print("Send from ESP",addr,"-",data)
       osc_msg = osc_message.OscMessage(data)
       print('\nreceive data')
       print(osc_msg.address)
       print(osc_msg.params)
       time.sleep(1)
       
       builder = osc_message_builder.OscMessageBuilder(address="/LED")
       builder.add_arg('Hello')
       builder.add_arg(count)
       builder.add_arg(100)
       msg = builder.build()
       print('\nsend data')
       print(msg._dgram)
       sock.sendto(msg._dgram,addr)
       #mes = msg._dgram.encode()
       #sock.sendto(mes,addr)

UDP通信で受信したバイナリーデータを.address、.paramsのオブジェクトでアドレスとデータを取り出せます。

osc_msg = osc_message.OscMessage(data)
 
       print(osc_msg.address)
       print(osc_msg.params)

実行した結果は以下のようになります。データはリストとして保管されます。

$  receive data
/SW
[1,Hello]

次に送信データは以下の部分で作成しています。

このデータを送信している。[count]は変数

/LED Hello [count] 100
builder = osc_message_builder.OscMessageBuilder(address="/LED")
       builder.add_arg('Hello')
       builder.add_arg(count)
       builder.add_arg(100)

上記でメッセージを作成してUDP通信で送信しています。


2、ESP32側

使ったライブラリーはこちら


#include <WiFi.h>
#include <WiFiUDP.h>
#include <OSCMessage.h>
#include <OSCBundle.h>

const char ssid[] = "your ssid"; // SSID
const char pass[] = "your password";  // password
static WiFiUDP Udp; 
static const char *kRemoteIpadr = "192.168.43.41";
static const int kRmoteUdpPort = 9000; //送信先のポート
static void WiFi_setup()
{
 static const int kLocalPort = 7000;  //自身のポート
 WiFi.begin(ssid, pass);
 while( WiFi.status() != WL_CONNECTED) {
   delay(500);  
 }  
 Udp.begin(kLocalPort);
}
static void Serial_setup()
{
 Serial.begin(115200);
 Serial.println(""); // to separate line  
}

//メッセージの確認
void mes_recive(OSCMessage &mess) {

 char str[64];
 int i;
 
 mess.getString(0,str,16);
 int val = mess.getInt(1);
 int val2 = mess.getInt(2);
 
 Serial.println("receive data");
 Serial.println("LED/");
 Serial.printf("%s,%d,%d\n",str,val,val2);
 
}

void setup() {
 Serial_setup();
 WiFi_setup();
}

void loop() 
{

OSCErrorCode error;
int count=0;
 
 while(1){
 OSCMessage rmsg;
 int size = Udp.parsePacket();
 if (size > 0) {
   while (size--) {
     rmsg.fill(Udp.read());
   }
     if (!rmsg.hasError()) {
     rmsg.dispatch("/LED", mes_recive, 0);
     rmsg.empty();
   }
   else {
     error = rmsg.getError();
     Serial.print("error: ");
     Serial.println(error);
   }
 }
 
 OSCMessage mess("/sw");
 mess.add(count);
 mess.add("Hello");
 Udp.beginPacket(kRemoteIpadr, kRmoteUdpPort);
 mess.send(Udp);
 Udp.endPacket();
 mess.empty();
 count++;
 delay(3000);
 }
}

長いプログラムですが、ほどんどは今まで出てきた、Wifi 設定やUDP通信の部分です。

受信バッファrmsgを定義し、UDP通信で受信したデータをfillで書き込み、dispatchでアドレス"/LED"で送られてきた場合、mes_reciveモジュールを呼び出します。

OSCMessage rmsg;
 int size = Udp.parsePacket();
 if (size > 0) {
   while (size--) {
     rmsg.fill(Udp.read());
   }
     if (!rmsg.hasError()) {
     rmsg.dispatch("/LED", mes_recive, 0);
     rmsg.empty();
   }


データの取り出しは下記で行ってます。

 mess.getString(0,str,16);
 int val = mess.getInt(1);
 int val2 = mess.getInt(2);

実行結果は

receive data
LED/
Hello 1,100

となります。送られて来るデータの型によってエンコードを変えなくてはならないのでデータフォーマットは予め取り決めしておく必要がありますね。

送信データは下記で作成しています。

OSCMessage mess("/sw");
 mess.add(count);
 mess.add("Hello")

送受信後データバッファは下記で空にします。

rmsg.empty();

mess.empty();


3、まとめ

今回はRaspberryPiとESP32で行いましたが、今回のプログラムはESP32ーESP32、RaspberryPiーRaspberryPiでも通信が行えます。

OSC通信は汎用フォーマットなので、クリエーター系ソフトのprocessingやRaspberryPiの音楽ソフトSonic Piなどもコントロールできるようです。

OSCはスマホアプリも沢山あるので、お気に入りのスマホアプリなどからESP32をコンロトールしても面白いですね。😊

では🤚


いいなと思ったら応援しよう!