スマフォ通話を黒電話でできるようにする!
いきなりだけど黒電話を購入した(ヤフオク)
幼い頃使っていたことから親しみがあり、以前から欲しいと思っていた。
とはいえ我が家には固定電話の回線は無いし、引く予定もないため使い道がなかったのだが
この記事を読んでスマフォで使えるようにしたら楽しい!ってことでやってみることにした。
上記の記事との環境の違い
基本的には上記の記事を読んで行ったのだが、上記の記事とは違う点がいくつかあった。
黒電話の型式
今回手に入れた黒電話は601-A2型であった。
601型はフックのスイッチの配線がケーブルとコネクタではんくプリント基板である。
とはいえ、今回基板とラズパイを接続するものはフックしかないため回路図的に基板上のB2とD3端子をH1、H2として接続した。
PulseAudioのビルドについて
apt-getで入手できるPulseAudioのバージョンが現在では記事より新しいため、簡単に導入できると思いきやここで大きな罠があった。
apt-getで入手したものだとラズパイゼロの場合、PulseAudioにハードコーディングされたMTUの値が合わない為音声がとてもノイジーになり使えません。
そのため値を変更してPulseAudioをビルドしないといけないのですがここでもいくつか問題が……
ビルドが上手く通らない……
ググって出てきたことを試してなんとかビルドできました。
作業
つづきは眠たいので後日……(今回は困ったことのメモ)
現在作っているものについて
謎のDiscord サーバー 「刺身たんぽぽ同好会」 Advent Calendar 5日目の記事です。
謎なので僕個人が最近作ってるものについて簡単に書こうと思います。
何を作っているの?
ラズベリーパイを使ったIP無線機を作ってます。
今は何をしているの?
プログラムを書いてます。
どんな環境で作るの?
ハードウェアは「Raspberry Pi Zero WH」状態表示に電子ペーパー。
アプリケーションはGo言語で作ってます。
どこまでできてるの?
- 作ったアプリケーションで電子ペーパーを動かすこと
- 作ったアプリケーションで受け取った音声をスピーカーから出力する
何か問題はあるの?
- アプリケーションから送ったマイクからの音声にノイズが載ってます……
今後について
問題の原因がどこにあるのか分かってない為、何とかしたい。
最終的に無線機の形にしたいのでハードウェア部分も考えないとです……
Bluetooth通信(RFCOMM)についてのメモ書き
Bluetoothを使いたい
今作っているアプリの通信をWIFIを使ったものからBluetoothを使ったものにしたいと思い、その際に調べたことのメモ。正しいかは分からない。
事前準備
通信する2台の端末のペアリングを済ませて置く
接続
2台の端末間で接続を確立するには、サーバー側とクライアント側の仕組みを実装する必要がある
Android
以下のドキュメントを参考にした。
ざっくりと説明すると
サーバー側ではサービス名とUUIDを登録して待ち受ける処理を行う。
クライアント側では接続先端末に対してサーバー側で指定したUUIDを指定して接続処理を行う。
という感じ。
Windows
以下のドキュメントを参考にした
Androidではサービス名とUUIDのみでSDP(service discovery protocol)部分を意識せずにサーバー側で待ち受けることができた。しかしWindowsではSDP部分を自分で触る必要がある。
UUID
ここに予約済みUUIDが分かる資料がある
16-bit UUIDsのAllocation type が「Service Classes and Profiles」のものがここで扱うUUIDのものっぽい。 上記値は省略されていて以下のように
0000XXXX-0000-1000-8000-00805F9B34FB
上記のXXXXの部分に当てはめるとよい
SDPについて
どんなサービスを提供するかの情報を表すデータ
データの形式が決まっており、サンプルのコードでは当然のように作成されていたのでこの部分についてメモを残す。
データについて
データ先頭ではデータ型を示す。
具体的には先頭5ビットを型、末尾3ビットを続くデータ長に関する情報が入る。
以下はサービス名をSDP情報として文字列で提供したい時の情報となる。
// 0x25 const byte SdpServiceNameAttributeType = (4 << 3) | 5;
ざっくり説明すると
文字列型を指す値としての4(0000 0100)の型を示したい場合、先頭5bitを型として扱うため3ビット左シフトする(0010 0000)。
次に文字列型の場合データ長は文字列長を示すがこの場合の数値も決まっており、8ビットの場合は5(0000 0101)となる。
上記の型とデータ長を論理和することで(0010 0101)となり8ビットの文字列データであることを表す値は0x25となる。
型やデータ長の値に関してはBLUETOOTH SPECIFICATION Version 2.1 + EDR [vol 3]のpage125 of 268の3 DATA REPRESENTATIONなどを読むとわかる。
データ型、データ長の次は実際のデータとなりますが特に変わったことはないので省略。
IDについて
SDPを追加する際に必要となるID、これはどうもPDU ID(PROTOCOL DATA UNIT ID)というものらしい?
ざっくりな理解だと、SDPの立ち振る舞いみたいな認識?
0x07までは決まっていてそこから0xFFまでが予約されているのでなにか任意のサービスときはそこに入れたらよい?
ガラホ(KYF37)向けアプリをUnityで作ってみる
ガラホとは
「ガラホ:ガラケーを作るにあたり、OSを含むスマホの技術・部品を転用したもの(ガラケーの機能・表示・操作感の再現などを目的に、スマホにある機能が一部削られている)」
とのこと。ちなみに「ガラホ」という単語はKDDIに商標登録されている。
KYF37とは
Android5.1.1をベースにした二つ折り携帯。
操作感などは従来のガラケーに近い感じでAndroidっぽさはほぼない。
ガラホ(KYF37)をコントローラーとして使おうとした時ここがすごい!
— ふたば(二葉) (@futanyaha) 2021年9月18日
・耐衝撃(MIL-STD-810G Method 516.7:Shock-Procedure IV)/ 防水(IPX5/IPX8)/防塵(IP5X)
・AndroidだからUnityで作ったアプリが動く!
・無線LAN(2.4Ghz)Bluetoothが使える
・800万画素のアウトカメラが使える
・当然画面もある
ツイートの通り、防水防塵耐衝撃でハードウェアキーのある扱いやすい端末なのだが、ほどほど市場に出回っているものの、そこまで需要があるものでもないため中古品が非常に安価(今回は2000円)に手に入るため今回開発してみることにした。
Unityでの開発
動かすまで
Android5.1.1ベースであるためUnityでAndroid向け開発を行うのと同様に開発ができる。
UnityでAndroid開発する際はモジュールを追加するだけで簡単に環境ができる。
KYF37の開発者向けオプションを出すには通常のAndroid端末と同様に端末情報のビルド番号を連打すると開発者向けオプションが有効になる。
ADB用USBドライバも以下に。
端末をパソコンにつなぎ
Unityで適当にオブジェクトやUIを配置
PlatformをAndroidにしていつものように「Build And Run」すると……
Unityアプリ動いてる
— ふたば(二葉) (@futanyaha) 2021年9月15日
大体のボタンの入力取れそう pic.twitter.com/TIewxK038t
このように普通に起動する。
ガラケーの見た目でUnityアプリが動いているのは面白いです。
UnityとKYF37(ガラホ)について
KYF37向けにUnityで開発していて気が付いたことを書いていきます。
タッチパネルがなく、ポインターもうまく動作しない
KYF37にはタッチパネルがありません。そのため画面上のボタンなどをタッチすることはできません。
タッチパネルのないKYF37ではポインターが用意されていますが、Unity上だとこのポインターはうまく動作しません。
ポインターが上に来た時、マウスオーバーの動作をするようですがクリックできません。
ハードウェアキー
KYF37のハードウェアキーのうち、「発信キー」と「終話キー」は認識しません。(なにかしら認識させる方法はあるかもしれない……)
下3つのカスタマイズキーは長押しした際にファンクションキーとして認識していた。 「センターキー」は一度押すと「JoystickButton0」と「Joystick1Button0」として認識されており面白かった。
テキスト入力
残念ながらKYF37ではUnity上でのテキスト入力は難しそう。
正確にはテキストの入力は可能なのですが文字を消せません。
問題として「クリアキー」を押した際の動作として「Backキー」の扱いとなっており、文字を消すのではなく入力を中断する扱いになるからの様?
変換機能を使わず、自前でキーパッドでの入力システムを実装すれば何とかなるかも?
最後に作ったもの
KYF37のキー入力をUDPでHoloLens 2やWindowsPCに送って操作するコントローラーアプリを作りました!
HoloLens 2をガラホ操作!
— ふたば(二葉) (@futanyaha) 2021年9月17日
だいぶ実用的になってきました! pic.twitter.com/3BQ5TIfpEL
テキスト入力の問題が発生したことや、Bluetoothを使った通信に変更するため今後の開発はAndroidStudioを使ってやってみようと思います。
HoloLens 2でInputInjectorクラスを使ってみる(キーボード編)
なにがしたいのか
HoloLens 2のプログラムからキー入力を送信したい。
どうやってする?
InputInjectorクラスを使うと実現できそう!
InputInjectorクラスではなにができる?
プログラムから生成されたキーボード、マウス、ゲームパッド、ペン、タッチデバイスの入力をプログラムから送信できる。
やってみる
他のアプリケーションにキー入力を送りたいため、今回はアウトプロセスバックグラウンドタスクから呼び出してみる。
(アウトプロセスバックグラウンドタスクやる意味は単に使えるようになったので使ってみたかったから)
動作
ボタンを押下するとバックグラウンドタスクが立ち上がり、4秒後にキー入力「hello」を送る。
HoloLens 2のバックグラウンドタスクからキー送信できることが分かった!
— ふたば(二葉) (@futanyaha) 2021年8月28日
ネットワーク部分作れば他のデバイスからいろいろできそう pic.twitter.com/RgUdByT8WH
参考にしたサイト
とても分かりやすくて助かりました。ありがとうございます!
今回の該当部分のコード
今回はとりあえず動くか確認したかったので参考にしたサイトの「Keyboard input」をそのまま使ってます。
バックグランド動作部分に関してはまた別で記事を作成するかも……?
// InputInjectorインスタンスを生成 InputInjector inputInjector = InputInjector.TryCreate(); // 一文字ずつ送信する処理 foreach (var letter in "hello") { // 送信するキー情報を作成する var info = new InjectedInputKeyboardInfo(); // VirtualKey Enumから一致する文字の値を設定する info.VirtualKey = (ushort)(VirtualKey)Enum.Parse(typeof(VirtualKey), letter.ToString(), true); // キー情報を配列で渡す。 inputInjector.InjectKeyboardInput(new[] { info }); // ここで待つことで同じ文字列が続いたときに認識されるようになるらしい?(未検証) await Task.Delay(100); }
今後やること
- キーボード以外のデバイスのHoloLens 2での動作を確認する。
- 通信部分を作って他のデバイスから動かしてみる。
- バックグラウンドタスクのトリガーをApplicationTriggerからSocketActivityTriggerにしてみる
などを予定しています。