HoloLens2が受信側になってUDP通信をしている事例はたくさん見つかりましたが,HoloLens2が送信側の例はあまりなく,実現まで少してこずったので残しておきます.
HoloLensにビルドしたアプリはUWPという形式になりますが,このUWPではソケットというものを使ってひと手間加えないとUDP通信ができないようです(この辺は調べても私にはあまりよくわかりませんでした).
【追記】
上記打ち消し部分について,ググってもよくわからないので同僚のChatGPTちゃんに聞いてみた結果は以下になります.なんとなく合ってる気はしますが,真偽のほどは定かではないです.
つまり,最近は普通にSystem.Net.SocketsをインクルードすればUdpClientも使えます.
とりあえず動いたので,そのコードを載せておきます.
送信側
送信側のHoloLens2 (Unity) コードは以下になります.
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
public class UdpSender : MonoBehaviour {
public string targetIpAddress = "ここにESP32のIPアドレスを入力";
//ESP32に書き込んだときシリアルモニタに表示されるESP32のIPアドレスを入力
public int targetPort = 3333;
private UdpClient udpClient;
void Start() {
udpClient = new UdpClient();
}
public void SendLedOn() {
Send("LED_ON");
}
public void SendLedOff() {
Send("LED_OFF");
}
private void Send(string message) {
try
{
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.Send(data, data.Length, targetIpAddress, targetPort);
}
catch (SocketException e) {
Debug.LogError($"SocketException: {e}");
}
}
private void OnDestroy() {
udpClient.Close();
}
}
Unityのインスペクタもしくはコードエディタを開いて,上記コードのESPのIPアドレス指定部分に,通信したいESP32のIPアドレスを入力してください.
ESP32のIPアドレスは,後述するプログラムをマイコンボードに書き込むときにあらかじめ「シリアルモニタ」を開いておくことで確認できます.
関数を実行できれば方法はなんでもOKです.私は,空のオブジェクトにスクリプトをアタッチし,MRTKのボタンからSendLedOn()とSendLedOff()関数を実行するようにしました.
この記事の最後にデモ動画を載せておきます.
受信側
受信側のESP32のコードは以下になります.SSIDとpasswordの部分を書き換えて,Arduino IDEからESP32に書き込んでください.
#include <WiFi.h>
#include <WiFiUdp.h>
//必要な場合はライブラリをインストールしてください
#ifndef LED_BUILTIN
#define LED_BUILTIN 2 //ESP32の場合、内蔵LEDは通常GPIO2に接続されています
#endif
const char* ssid = "SSID";
const char* password = "password";
const int udpPort = 3333;
WiFiUDP Udp; //グローバル変数としてWiFiUDPインスタンスを宣言
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
Serial.println(WiFi.localIP());
Udp.begin(udpPort);
}
void loop() {
int packetSize = Udp.parsePacket();
if (packetSize) {
char incomingPacket[255];
int len = Udp.read(incomingPacket, 255);
incomingPacket[len] = '\0';
Serial.printf("UDP packet contents: %s\n", incomingPacket);
//LEDを制御するコード
if (strcmp(incomingPacket, "LED_ON") == 0) {
digitalWrite(LED_BUILTIN, HIGH);
} else if (strcmp(incomingPacket, "LED_OFF") == 0) {
digitalWrite(LED_BUILTIN, LOW);
}
}
}
書き込む前にシリアルモニタを開いておくことで,接続状況やESP32のIPアドレスを確認できます.
デモ
実際の動作は以下のようになります.
わかりにくいですが,青色の光がESP32の内蔵LEDです.
うまくいかないときに確認すべきこと
- HoloLens2とESP32を同じWi-Fiに接続しているか?
- IPアドレス,ポート番号は正しいか?
- HoloLens2 (Unity)側で通信の許可をしているか?
- Unity側でUDPを送る関数の実行はされているか?
- Arduino IDEに必要なライブラリがインストールされているか?
関連話題のリンク
検索用
ChatGPTさんの解説
質問「UWPアプリでUdpclientが使えるようになったのはいつですか.」
GPT-4の回答「私の知識の範囲では、UWP(Universal Windows Platform)アプリでは、.NET Coreが導入されたことで、UdpClientを含むSystem.Net.Sockets名前空間の機能が利用可能になりました。これは、UWPアプリでUdpClientを利用できるようにするための重要な変更でした。
.NET Core 3.0は2019年9月にリリースされましたが、UWPアプリのソケットサポートは以前から存在していました。ただし、それらはWindows.Networking.Sockets名前空間にあるクラス(DatagramSocketなど)を使用していました。
したがって、.NET Core 3.0のリリースにより、UWPアプリでより一般的なSystem.Net.Sockets名前空間のUdpClientが使えるようになりました。」