梶研 [お料理やってない, BLE微妙..., NFC最高!]
2024年3月12日

お料理やってない, BLE微妙..., NFC最高!
出席率
- 3年セミナー:??%
スケジュール
短期的な予定
- mocopi と お料理センシング
- シーンとランドマークを決める(~2月上旬)
- SVM で動作判別する
- 機械学習を深める
- 機械学習の手法を知る
- 使う手法を決める
- データセットを探す
- 機械学習(LSTM)する
- 精度を上げる
- ?
- お料理センシング
- お料理でどんな動作があるかを知る
- ?
- 論文書く
- 発表
- BLEビーコンのuuidを書き換えたい
- 通信内容を読み解く
- shellコマンドで通信してみる
- 実装してみる
- BookWorm
- Pasori と デスクトップアプリを接続する(技術検証)
- nfc読み込み機能 & 画面を作る
- API と連携させる
- 管理者画面を作る
長期的な予定
- ~?月 シーン検知?をする
- ~?月 論文を書く
- ~?月 論文発表したい
進捗報告
お料理でどんな動作があるかを知る
前回) 精度は置いといて、機械学習は一旦できたぽい
お料理についてどんな動作があるか fuma さんと話す
→ 気づいたら金曜日にだったので今週やる
- コンロや冷蔵庫, 電子レンジ, まな板前 など動き回る料理がいい
- 卵焼き→コンロ程度?
- 料理力が壊滅的
- 初心者でも(慣れれば)出来るような物がいい
- 現状
- 卵焼き 🙆
- 目玉焼き 🙅♀️
- 今後たくさん作る必要がある
- 好きな食べ物がいい
- オムライスとか?
- 好きな食べ物がいい
BLEビーコンのuuidを書き換えたい
Python で GATT プロトコルを扱いたい
どうやら Python で GATT 通信できるものがあるらしい
https://pypi.org/project/BLE-GATT/
https://micropython-docs-ja.readthedocs.io/ja/latest/library/bluetooth.html
HTTP ではなく、より低レイヤーの TCP を扱うイメージ
なんやかんや調べた結果、一旦ペアリングする必要があるとか?
Android端末 と ビーコンはそんなことしていないので違うはず?
よく分からないので一旦手を動かしてみる
シェルコマンドで BLE(GATT)通信してみる
BLEデバイスをスキャンする
$ sudo hcitool lescan
![]()
選択
$ gatttool -I -b [address]
![]()
接続
[address][LE] > connect
エラー: Attempting to connect

gatttool 使用法(日本語)
使用法:
ガットツール [オプション?]
ヘルプオプション:
-h, --help ヘルプ オプションを表示します
--help-all すべてのヘルプ オプションを表示します
--help-gatt すべての GATT コマンドを表示します
--help-params すべてのプライマリ サービス/特性引数を表示します
--help-char-read-write すべての特性を表示 値/記述子 読み取り/書き込み引数
GATTコマンド
--primary プライマリ サービスの検出
--characteristics 特性の発見
--char-read 特性値/記述子の読み取り
--char-write 特性値 応答なしの書き込み (書き込みコマンド)
--char-write-req 特性値書き込み (書き込み要求)
--char-desc 特性記述子の検出
--listen 通知と指示をリッスンします
主なサービス/特性の引数
-s, --start=0x0001 開始ハンドル(オプション)
-e, --end=0xffff 終了ハンドル(オプション)
-u、--uuid=0x1801 UUID16 または UUID128 (オプション)
特性 値/記述子 読み取り/書き込み引数
-a, --handle=0x0001 ハンドルによる読み取り/書き込み特性 (必須)
-n, --value=0x0001 書き込み特性値 (書き込み操作に必要)
アプリケーションオプション:
-i, --adapter=hciX ローカルアダプターインターフェースを指定します
-b, --device=MAC リモート Bluetooth アドレスを指定します
-t、--addr-type=[パブリック | [ランダム] LE アドレスの種類を設定します。 デフォルト: パブリック
-m, --mtu=MTU MTU サイズを指定します
-p, --psm=PSM BR/EDR 上の GATT/ATT の PSM を指定します
-l, --sec-level=[低 | 中 | 高] セキュリティレベルを設定します。 デフォルト: 低
-I, --interactive 対話モードを使用する
bluetoothctl というコマンドもあるらしい.
デバイス一覧を出す
$ bluetoothctl
[bluetooth]# devices![]()
でてこない.
スキャンしたものの中から接続可能なものが出てくるらしい
[bluetooth]# scan on
デバイス一覧が取れた

gatt というコマンドもあるのでそれを使えばできる?
[bluetooth]# menu gatt
![]()
ねむい.つかれた.また今度やる
BookWorm デスクトップアプリ側 で Pasori を扱う
疲れたので楽なBookWromをやった
Pasori を使う方法として
- Tauri のバックエンド(Rust)で読み取る
- 一番美しい ※個人の思想
- 本来あるべき姿
- Rust という面で引き継ぎづらい?
- パッケージがあれば書く量は少なく引き継ぎやすい?
- 一番美しい ※個人の思想
- Tauri のバックエンドから shell などから他の言語(Pythonなど)で読み取る
- 現在の方法
- 美しくない
- 環境依存になる
- 正攻法ではない
- Python などを使えるという面では引き継ぎやすい?
- Tauriのフロントエンド(ブラウザ/JavaScript)で読み取る
- 美しいとは言えない
- 正攻法ではある
- Pasori や MFCタグ の低レイヤーを知る必要がある
- 参考: https://sakura-system.com/?p=3120
- JavaScript という面では引き継ぎやすい?
- 低レイヤーを知る必要があるため引き継ぎづらい
- 美しいとは言えない
技術検証
Rust で Pasori を扱う
→ 良いパッケージがなかった
- nfc
- libnfcを使って自分で実装
- 実装辛い
- 環境依存
- https://github.com/segfo/smartcard
重いので Rust は諦める.
WebUSB を使って JavaScript から Pasori を扱う
- 参考元
- ライセンス: the unlicense
- ライセンスに則った上で改変しまくりました
- https://github.com/saturday06/webusb-felica/blob/gh-pages/demo.html
- ライセンス: the unlicense
- Pasori 仕様書
USBデバイス全てに対応するAPIなのでとても低レイヤーを触っています
コード一部抜粋
1 await send(device, [0x00, 0x00, 0xff, 0x00, 0xff, 0x00]); 2 await send(device, [0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfd, 0xd6, 0x2a, 0x01, 0xff, 0x00]); 3 await receive(device, 6); 4 await receive(device, 13); 5 6 await send(device, [0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfd, 0xd6, 0x06, 0x00, 0x24, 0x00]); 7 await receive(device, 6); 8 await receive(device, 13); 9 10 await send(device, [0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0xfd, 0xd6, 0x06, 0x00, 0x24, 0x00]); 11 await receive(device, 6); 12 await receive(device, 13);
カスタムイベントというやつを使ってみた
イベント: ウェブページ上で発生するあらゆるアクションの総称 SAMURAI ENGINEER
idm を読み取ったら発火するイベントを作成した
1// イベントを定義 2const readIdmEvent = new CustomEvent('readIdm', { detail: { idm } }); 3// イベントを発火 4window.dispatchEvent(readIdmEvent); 5 6// イベントリスナーを登録 (idm が呼ばれる度にonReadIdmが実行される) 7window.addEventListener('readIdm', onReadIdm);
カスタムフックにして扱いやすくなった
1const LendingPage = (props: LendingPageProps): ReactElement => { 2 const subscribeIdm = useCallback(handleReadIdm, []); // カスタムフック 3 const { start, stop } = usePasoriEvent(subscribeIdm); 4 5 function handleReadIdm(idm: string) { 6 console.log({ idm }); 7 handleNext(); 8 } 9 10 ... 11}
mizutani 先輩とのReactドキュメント輪読会が役に立ちました
イベントリスナーを削除するには同じ関数を与える必要がある
→ useCallback でいい感じに
もう少しいい感じにしたい (strictモードでは webUSBの動作が不安定)
せっかく JS だけで出来たので仮デプロイしました
https://bookworm-nfc.satooru.dev/
ほとんど完成してしまったのでAPIができ次第、続きをやります
進路関係
余談
neovim 始めました
windows の VScode があまりにも触りづらかったので vim に慣れようと思います.
ぼくのかんがえたさいきょうのIDEを構築しています

広見城に訪れた
八草駅から5分程度の位置にある城
雨上がりで危なそうだったので攻城は諦めた
牧野先輩の家に帰った @豊橋
行き
帰り道に竹島に寄るのが恒例と聞いたので寄った
楽しくなって浜名湖にも寄った
帰り
吉田城に行った
続日本百名城の一つで気になってた
のんほいパークに行った
メモ
DC:0D:30:0D:FF:CC
https://www.mikan-tech.net/entry/ble-gatt-study
https://www.mikan-tech.net/entry/raspi-sensortag-gatttool
https://jitaku.work/it/category/bluetooth/gatttool/