ESP32-CAMのStream動画をA-FrameのVR空間に表示する

M5Camera Xの動画をA-FrameのVR空間内に表示させたいと思ったが、Motion JPEG stream形式だと、デフォルトの機能(image、video)では対応できなかった。

で、調べたところドンピシャのページを発見。仕組みはよく分からんけど、サンプル通りのコンポーネント作ったらすんなり表示できた!!

>> Use Motion JPEG stream as a source of 360 deg image

AFRAME.registerComponent('box', {
    schema: {
        width: { type: 'number', default: 1 },
        height: { type: 'number', default: 1 },
        depth: { type: 'number', default: 1 },
        color: { type: 'color', default: '#AAA' }
    },

    init: function () {
        var data = this.data;
        var el = this.el;

        this.loader = new THREE.TextureLoader();

        this.geometry = new THREE.BoxBufferGeometry(data.width, data.height, data.depth);
        this.material = new THREE.MeshPhongMaterial({
            map: this.getImage()
        });
        this.material.needsUpdate = true;
        this.mesh = new THREE.Mesh(this.geometry, this.material);
        el.setObject3D('mesh', this.mesh);
    },

    tick: function (time, timeDelta) {
        this.mesh.material.map.img = this.getImage();
        this.mesh.material.map.needsUpdate = true;
    },

    getImage: function() {
        return this.loader.load("ストリーム動画のパス");
    }

サンプルでは立方体だが、下記の部分をいじれば、他のプリミティブでもいける。

this.geometry = new THREE.BoxBufferGeometry(data.width, data.height, data.depth);

M5CameraXをカメラサーバにする

M5CameraXを買ってみたが、Wifi接続しなきゃならんってのが不便極まりない。ググったらステーションモードにできるらしいと分かったので、早速、先人の方々の情報を参考に、ArdinoIDE(1.8.13)のCameraWebSerberのスケッチを書き込んでみた。

書き込み自体はあっさり成功したが、シリアルモニタが文字化けしてて、アクセス先が分からない…通信速度を「115200bps」にしないとアカンのね。

参考サイト

バランスwiiボードをNode.jsで使ってみる

中古のバランスwiiボードを貰ったので、なんかに活用できないかと色々調べてみたが、微妙に情報が古かったり環境の設定が結構面倒なものばかりだった。
…が、「wii-balance-board-pi」って気になるNode.jsのモジュールがあったのでラズパイ4入れてみたところサクッと使えた。

【検証環境】

  • Raspberry Pi 4
  • raspbian 10.4
  • Node.js 8.15

【設定方法】
基本的には、Githubのページに書いてある通りにするだけ。
サンプルスクリプトもシンプルだが、これだけで十分な内容。

  1. モジュールをインストール
    npm i -s wii-balance-board-pi
  2. 通信用のPythonプログラムを入れる
    sudo apt-get --assume-yes install bluez python-bluez python-gobject python-dbus
  3. ラズパイを再起動
    sudo reboot
  4. サンプルスクリプトを実行
    const BalanceBoard = require("wii-balance-board-pi");
    
    var balanceBoard = new BalanceBoard();
    
    balanceBoard.connect();
    
    balanceBoard.on("data", data => {
      console.log(data);
    });
  5. バランスWiiボードの電池カバー開け、シンクロボタン(赤いやつ)を押す。
  6. ちょっと待ってると自動的にラズパイと繋がって、各センサ直がコンソールに表示される。
    {
        connected: boolean,
        topLeft: float,
        topRight: float,
        bottomLeft: float,
        bottomRight: float,
        totalWeight: float,
        buttonPressed: boolean,
        buttonReleased: boolean
    }

4角にあるセンサ値と全体の重さ(kg)、前面にあるボタンの状態がJSONで取得できるので、あとは好きに料理するだけ!
これはお手軽で便利だ。

オレオレ認証サイトをChromeで見る方法

Chromeのアップデートに伴い、Node.jsでオレオレ認証のサーバに完全にアクセスできなくなってしまった。
ちょっと前までは、リクス覚悟で見るか?ってリンクが出てたので、それでアクセスできたけれど、そのリンクも出なくなった…

クリアできる証明書の作り方もある様だが、こちらの技量ではお手上げレベルなので困ってたが、アクセスをブロックしてる旨のページのどこでも良いので、
ページ内の適当な箇所をクリックして、「thisisunsafe」とタイプ & Enterで、見事にアクセスできた!

それにしても、G社のおかげで、こっちの世界もどんどん面倒臭くなるな。

参考サイト

ラズパイ & Node.js でMQTTサーバを立てる

HEROKUを使えば、サクッとMQTTサーバができるらしいが、色々自前でやりたいので調べてみたら、「mosca」ってのを使えば、Node.jsでサーバ作れるし、「mqtt.js」を使えば、クライアント側もできるらしいので、早速やってみた。
Node.jsはすごいねぇ。

Brokerサーバの構築

1.moscaのインストール
npm install mosca
2.基本的なスクリプト
var mosca = require('mosca');
var server = new mosca.Server({
	port: <サーバのポート番号>,
});

/*準備完了*/
server.on('ready', function(){
	console.log('Server is ready.');
});

/*クライアントが接続された*/
server.on('clientConnected', function(client){
	console.log('broker.on.connected.', 'client:', client.id);
});

/*クライアントが切断されrた*/
server.on('clientDisconnected', function(client){
	console.log('broker.on.disconnected.', 'client:', client.id);
});

/*Subscriberからデータの配信要望が来た*/
	server.on('subscribed', function(topic, client){
	console.log('broker.on.subscribed.', 'client:', client.id, 'topic:', topic);
});

/*Subscriberからデータの配信停止要望が来た*/
	server.on('unsubscribed', function(topic, client){
	console.log('broker.on.unsubscribed.', 'client:', client.id); 
});
	
/*Publisherからデータが送信された*/
server.on('published', function(packet, client){
	if (/\/new\//.test(packet.topic)){
		return;
	}
	if (/\/disconnect\//.test(packet.topic)){
		return;
	}
	console.log('broker.on.published.', 'client:', client.id);
});

/*MQTTサーバをHTTP サーバに結びつける*/
var http = require('http');
var httpServer = http.createServer();
server.attachHttpServer(httpServer);
httpServer.listen(<サーバのポート番号>);

Node.jsでのクライアント機能の実装

1. mqtt.jsのインストール
npm install mqtt

※ブラウザから実行する場合は埋め込み利用も可

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
2. 初期化スクリプト
const mqtt = require('mqtt');
var client = mqtt.connect({
	host: ' ',
	port: ,
	clientId: '<自分のID>'	//任意(無しの場合は自動設定)
});

/*Brokerサーバに接続*/
client.on('connect', function(){
	console.log('publisher.connected.');
});

データの送信(Publisher)

/*データ配信*/
client.publish('<任意のTOPIC>',<送信データ>);

データの受信(Subscriber)

/*購読希望リクエスト*/
client.subscribe('<購読希望TOPIC>');

/*データ受信*/
client.on("message", (topic, payload) => {
	console.log(topic);
	var message = payload.toString('utf-8');
	//var message = String.fromCharCode.apply(null, payload);
	console.log(message);
});

参考サイト


無事MQTTサーバができたので、micro:bitとHalocodeを双方向で通信させてみた。

BlueJelly と bleno でBLE通信する際の文字列の取り回しについて

ブラウザでお手軽BLEをするのに、BlueJellyがすごく便利なんだが、Peripheral化させたラズパイ(Node.js + bleno)とデータのやり取りする時に、Byte Arrayとかなんとかメンドクサイのが出て来て訳が分からんので、とりあえず簡単に使う方法を整理。

●データを受ける(Read)

Peripheral側から飛んできたデータはArray Bufferになってるので、文字列に戻す

//Bluejelly イベント
ble.onRead = function (data, uuid){
 let xVal = buffToString(data.buffer);
 console.log(xVal);
}

/*ArrayBufferから値を読んで文字列に変換*/
const buffToString = function(xBuffer) {
  let xArrayBuffer = new Uint8Array(xBuffer);
  let xRes = String.fromCharCode.apply(null,xArrayBuffer);
  return xRes;
}
●データを送る(Write)

Peripheralにデータを送るには文字列をArrayBufferにして、送る。

let xSendVal = "送信データ";

//文字列をArrayBufferに変換
let arrayBuffe = new TextEncoder().encode(xSendVal);
ble.write('UUID名',arrayBuffe);
●Node.js側でWriteされたデータを文字列に戻す
//xVal = writeされたデータ
let xVal = Buffer.from(Uint8Array.from(Buffer.from(data))).toString();

ターミナルに画像を表示する

ラズパイのカメラで撮影した画像を楽に確認する方法を探してたら、ターミナルに画像を表示するって素敵な方法がありました!MacでiTerm2を使ってる人限定だけど、コマンド2行書くだけで、導入も超簡単!
こりゃ便利だわー!

>> Mac の iTerm2 で画像をコンソールに表示する

ラズパイをBLEのPeripheralにするためにNode.js + bleno で環境作成

Peripheral(ペリフェラル)ってのは送信側の事だそうな。ちなみに、受信側はセントラル(Central)だって。

で、本題。
とりあえず、OS入れて初期設定だけ済ませたクリーンな環境で作業開始。(出たてで怖いので、あえてOSはStretchを利用。)

■環境
ハード:Raspberry Pi Zero WH
OS:Raspbian Stretch
■n のインストール
使い勝手が良いので、Node.jsのヴァージョン管理には n を使う事にする。

apt-getで node と npm入れる → npm で n 入れる → aptで入れた node と npm 消す。

…って方法が一般的っぽいけど、入れて消すってのが気持ち悪いのと、これだと色々面倒な事になるっぽいので、apt方式はやめて、n-install を使って、先に n をインストールする。

$curl -L https://git.io/n-install | bash

無事インストールできたら、インストーラの指示に従ってエイリアス設定を再読み込み。(これをしないと、n コマンドが通らない)

$source ~/.bashrc

n コマンドが通るのを確認したら、bleno 用にnode 8.xをインストール(今回は8.15.0を利用)

$n 8.15.0
■node を sudo で実行させる
実行できるなら、この項は無視してOK。
  1. nodeのパスを確認
    $which node
  2. シンボリックリンクを作成
    (上記1で調べたパスが「/home/pi/n」だった場合の例)
    $ sudo ln -s /home/pi/n/bin/node /usr/bin/node
    $ sudo ln -s /home/pi/n/lib/node /usr/lib/node
    $ sudo ln -s /home/pi/n/bin/npm /usr/bin/npm
    $ sudo ln -s /home/pi/n/bin/node-waf /usr/bin/node-waf *もしあったら
  3. とりあえず、ラズパイを再起動して、ちゃんとヴァージョン番号が表示されるのを確認できたら、作業完了!
    sudo node -v
    sudo npm -v

    (参考サイト:日々精進EC2でsudo nodeを実行するとcommand not found」)

■blenoのインストール
・Node.js ver8.x が動いてる。
・sudo node が実行できる。

この二つの条件が整ったら、いよいよblenoをインストール!

$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
$ npm install bleno

詳しいやり方等は、親切丁寧で分かりやすいページがありましたので、そちらをご覧ください。

極力ローコスト ロボット製作 ブログNode.jsとblenoでRaspberry PiとiPhoneをBLEでつなげてみる

Node.jsでラズパイのカメラモジュールを使う

Raspberry Pi Zeroとカメラモジュールを入手したので、Node.jsで制御させてみた。
コマンドラン叩く系とかは面倒くさいのので敬遠してたが、「pi-camera」ってモジュール入れたら、簡単にできた。

npm install pi-camera

モジュールを入れたらサイトにあるサンプルスクリプトを参考に、JavaScriptファイルを作成して書いて実行。

const PiCamera = require('pi-camera');

const myCamera = new PiCamera({
  mode: 'photo',
  output: `${ __dirname }/test.jpg`,
  width: 640,
  height: 480,
  nopreview: true,
});
 
myCamera.snap()
  .then((result) => {
    // Your picture was captured
  })
  .catch((error) => {
     // Handle your error
  });

撮影完了までに5秒くらいの待つけど、これは仕様らしいので、諦めるしか無いっぽい。
動画にも対応してる様なので、次は動画にチャレンジ。

参考サイト
Pi-Camera(npm)
pi-camera(GitHub)