Raspberry PiでNode.jsを動作させ、Node.js上でSensorTagの、加速度計、ジャイロスコープ、磁力計の各センサー情報を受け取り、受け取ったセンサー情報を、WebSocketを用いて、PCで動作しているUnityに入力データとして転送します。
Node.js上でのSensorTagのセンサー情報の入力は、「node.js環境でのSensortagの情報の読み出し 」を参考にしてください。
UnityでWebSocketによるデータの受け渡しは、以前作成したwebsocket-sharp を使用しました。詳細については、「UnityとRaspberry Pi間でWebSocket通信 」に示します。

SensorTagの加速度計、ジャイロスコープ、磁力計の入力ソフト

RaspberryPiでこのソフト「unity.js」を動作します。UnityからWebSocketにより接続を受け取ると、SensorTagのセンサー情報の収集を開始します。まず、SensorTagを起動して接続を行います。接続が完了するとそれぞれのセンサーをアクティブにして、以降5秒ごとに各センサ値を読み出して、WebSoketを用いてUnityにセンサ値を転送します。
具体的には、受け取ったセンサー情報を変数SensorDataに保存し 、sendメソッドを用いてUnityに転送しています。

unity.js

var WebSocketServer = require('ws').Server, wss = new WebSocketServer({port: 8125});
var util = require('util');
var async = require('async');
var SensorTag = require('./index');
var SensorData = ''; 

wss.on('connection', function(ws) {
  ws.send('Start SensorTag');
  
  SensorTag.discover(function(sensorTag) {
    sensorTag.on('disconnect', function() {
      console.log('disconnected!');
      process.exit(0);
    });
    console.log('connectAndSetUp');
    sensorTag.connectAndSetUp(function() {
      console.log('enableAccelerometer');
      sensorTag.enableAccelerometer(function() {
        console.log('enableMagnetometer');
        sensorTag.enableMagnetometer(function() {
          console.log('enableGyroscope');
          sensorTag.enableGyroscope(function() {

            setInterval(function() { 
            
              async.series([
                  
              function(callback) {
                console.log('readAccelerometer');
                sensorTag.readAccelerometer(function(error, x, y, z) {
                  console.log('\tkx = %d G', x.toFixed(1));
                  console.log('\ty = %d G', y.toFixed(1));
                  console.log('\tz = %d G', z.toFixed(1));
		          SensorData = 'Accelerometer x:' + x.toFixed(1) + ' y:' + y.toFixed(1) + ' z:' + z.toFixed(1);
                  callback();
                 });
              },
              function(callback) {
                console.log('readMagnetometer');
                sensorTag.readMagnetometer(function(error, x, y, z) {
                  console.log('\tx = %d μT', x.toFixed(1));
                  console.log('\ty = %d μT', y.toFixed(1));
                  console.log('\tz = %d μT', z.toFixed(1)); 
		          SensorData += ' Magnetometer x:' + x.toFixed(1) + ' y:' + y.toFixed(1) + ' z:' + z.toFixed(1);
                  callback();
                });
              },
              function(callback) {
                console.log('readGyroscope');
                sensorTag.readGyroscope(function(error, x, y, z) { 
                  console.log('\tlx = %d °/s', x.toFixed(1)); 
                  console.log('\ty = %d °/s', y.toFixed(1));
                  console.log('\tz = %d °/s', z.toFixed(1));
                  SensorData += ' Gyroscope x:' + x.toFixed(1) + ' y:' + y.toFixed(1) + ' z:' + z.toFixed(1);
                  ws.send(SensorData);
                  callback();
                }); 
              }]
              
            );
            
            }, 1000*5);
            
          });
        });
      });
    });
  });
});

UnityでSensorTagからのセンサー値を受け取るソフト

このソフトは、PCで動作するUnityのオブジェクトの入力データとしてセンサー情報を受け取るソフトです。Unityのプログラムを起動するとStartメソッドが呼ばれます。ここで、受信のイベント処理を登録し、ws.Connectメソッドにより、RaspberryPiに接続しに行きます。RaspberryPiからはセンサー情報は文字列で送られてくるので、受信のイベント処理の中でprintメソッドにより受け取った情報を、consoleウインドウに表示しています。

using UnityEngine;
using System.Collections;
using WebSocketSharp;

public class q1 : MonoBehaviour {
      private WebSocket ws;
	// Use this for initialization
	void Start () {
          this.ws = new WebSocket("ws://192.168.0.50:8125");
          this.ws.OnMessage += (object sender, MessageEventArgs e) =>
          {
            print(e.Data);
          };
          this.ws.Connect();
        }
	
	// Update is called once per frame
	void Update () {
		rigidbody.MovePosition (new Vector3(Mathf.Sin(Time.time),0,0));
    }
}

RaspberryPiでのプログラムの実行

作成したunity.jsをnodeコマンドで実行します。次に、Unityのプログラムを実行します。bluetoothのアダプタ「PlanexのBT-Micro4」のドングルが青く光るので、SensorTagの側面のボタンを押すと、「connectAndSetUp」と端末に表示され、以降、次のように、受け取ったセンサ情報のダンプが繰り返されます。

$ sudo node unity.js
connectAndSetUp
enableAccelerometer
enableMagnetometer
enableGyroscope
readAccelerometer
        kx = -0.1 G
        y = 0.3 G
        z = 4.1 G
readMagnetometer
        x = -78.4 μT
        y = 35.7 μT
        z = 62.3 μT
readGyroscope
        lx = -2 °/s
        y = 2.1 °/s
        z = -0.5 °/s
readAccelerometer
        kx = -0.1 G
        y = 0.3 G
        z = 4.1 G
readMagnetometer
        x = -78.5 μT
        y = 35.8 μT
        z = 62.3 μT
readGyroscope
        lx = -2 °/s
        y = 2.1 °/s
        z = -0.6 °/s
readAccelerometer
        kx = -0.1 G
        y = 0.3 G
        z = 4 G
readMagnetometer
        x = -78.6 μT
        y = 35.7 μT
        z = 62.1 μT
readGyroscope
        lx = -2.2 °/s
        y = 2.2 °/s
        z = -0.5 °/s
            .
            .
            .

UnityのConsoleウインドウへの表示

RaspberryPiから転送されたSensorTagのセンサー情報を受け取ると、Consoleウインドウに表示されます。

Start SensorTag
Accelerometer x:-0.1 y:0.3 z:4.1 Magnetometer x:-78.4 y:35.7 z:62.3 Gyroscope x:-2.0 y:2.1 z:-0.5
Accelerometer x:-0.1 y:0.3 z:4.1 Magnetometer x:-78.4 y:35.7 z:62.3 Gyroscope x:-2.0 y:2.1 z:-0.5Accelerometer x:-0.1 y:0.3 z:4.1 Magnetometer x:-78.5 y:35.8 z:62.3 Gyroscope x:-2.0 y:2.1 z:-0.6
Accelerometer x:-0.1 y:0.3 z:4.1 Magnetometer x:-78.4 y:35.7 z:62.3 Gyroscope x:-2.0 y:2.1 z:-0.5Accelerometer x:-0.1 y:0.3 z:4.1 Magnetometer x:-78.5 y:35.8 z:62.3 Gyroscope x:-2.0 y:2.1 z:-0.6Accelerometer x:-0.1 y:0.3 z:4.0 Magnetometer x:-78.6 y:35.7 z:62.1 Gyroscope x:-2.2 y:2.2 z:-0.5
            .
            .

エラーメッセージ「throw er; // Unhandled ‘error’ event」

このエラーメッセージは、RaspberryPi側で実行しているnode.jsで起こったもので、次のように表示されます。

$ sudo node unity.js
events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: listen EADDRINUSE
    at exports._errnoException (util.js:746:11)
    at Server._listen2 (net.js:1156:14)
    at listen (net.js:1182:10)
    at net.js:1280:9
    at dns.js:85:18
    at process._tickCallback (node.js:355:11)
    at Function.Module.runMain (module.js:503:11)
    at startup (node.js:129:16)
    at node.js:814:3

原因は、node.jsが動作して終了してない状態で、再度node.jsを起動したときに発生します。従って、次のようにpsコマンドで実行しているunity.jsのプロセスIDを見つけて、killコマンドで削除すれば解決します。

$ ps aux | grep node
root      6139  0.0  0.5   4592  2652 pts/0    T    05:23   0:00 sudo node unity.js
root      6140  1.7  5.2  41668 23408 pts/0    T    05:23   0:10 node unity.js
root      6141  0.0  0.4   3384  1864 pts/0    T    05:23   0:00 /home/pi/node_modules/unity/node_modules/noble-device/node_modules/noble/lib/linux/../../build/Release/hci-ble
pi        6168  0.0  0.3   3548  1732 pts/0    S+   05:33   0:00 grep --color=auto node
$ sudo kill -9 6139
[1]+  Killed                  sudo node unity.js

エラーメッセージ「(node) warning: possible EventEmitter memory leak detected」

このエラーメッセージは、RaspberryPi側で実行しているnode.jsで起こったもので、次のように表示されます。

$ sudo node unity.js
(node) warning: possible EventEmitter memory leak detected. 11 discover listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at EventEmitter.addListener (events.js:179:15)
    at Function.constructor.discoverAll (/home/pi/node_modules/unity/node_modules/noble-device/lib/util.js:49:27)
    at Function.SensorTag.discoverAll (/home/pi/node_modules/unity/lib/sensortag.js:8:19)
    at Function.SensorTag.discover (/home/pi/node_modules/unity/lib/sensortag.js:24:13)
    at WebSocketServer. (/home/pi/node_modules/unity/unity.js:9:11)
    at WebSocketServer.emit (events.js:107:17)
    at /home/pi/node_modules/ws/lib/WebSocketServer.js:79:14
    at completeHybiUpgrade2 (/home/pi/node_modules/ws/lib/WebSocketServer.js:262:5)
    at completeHybiUpgrade1 (/home/pi/node_modules/ws/lib/WebSocketServer.js:287:13)
    at WebSocketServer.handleHybiUpgrade (/home/pi/node_modules/ws/lib/WebSocketServer.js:315:3)
(node) warning: possible EventEmitter memory leak detected. 11 discover listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at EventEmitter.addListener (events.js:179:15)
    at Function.constructor.discoverAll (/home/pi/node_modules/unity/node_modules/noble-device/lib/util.js:49:27)
    at Function.SensorTag.discoverAll (/home/pi/node_modules/unity/lib/sensortag.js:9:19)
    at Function.SensorTag.discover (/home/pi/node_modules/unity/lib/sensortag.js:24:13)
    at WebSocketServer. (/home/pi/node_modules/unity/unity.js:9:11)
    at WebSocketServer.emit (events.js:107:17)
    at /home/pi/node_modules/ws/lib/WebSocketServer.js:79:14
    at completeHybiUpgrade2 (/home/pi/node_modules/ws/lib/WebSocketServer.js:262:5)
    at completeHybiUpgrade1 (/home/pi/node_modules/ws/lib/WebSocketServer.js:287:13)
    at WebSocketServer.handleHybiUpgrade (/home/pi/node_modules/ws/lib/WebSocketServer.js:315:3)
^Z
[1]+  Stopped                 sudo node unity.js

原因は、Unity側のソフトで、上記に示すws.Connectメソッドが、Updateメソッドで呼び出されていたため、フレームごとにws.Connectメソッドが実行され、WebSocketが大量に作成されてリソースが足りなくなり、警告が発生しました。これは、上記のソースコードに示すように、startメソッドから呼び出すことにより解決しました。