Progress Log: マルチボード対応設計 - 接続形式別アーキテクチャ検討¶
Task Description¶
kurikintonsのマルチボード対応について、以下の3つの接続形式に対応可能な統一アーキテクチャについて検討しました。
- 1:1接続 - 1台のPC ← → 1台のOSECHI(現在の基本形態)
- USB接続、単一のシリアルポート
- N:N接続 - N台のPC ← → N台のOSECHI(複数台のパソコン/OSECHIのセット同時計測)
- 各PCが独立して単一ボードを管理
- 1:1をスケールしたシンプルな構成
- 1:N接続 - 1台のPC ← → N台のOSECHI(1台で複数ボードを同時管理/計測)
- USBハブ+複数シリアルポート接続
- 複数ボードのデータを統合、時刻同期、相関分析
現状分析¶
既存実装の確認(v1.9.5時点)¶
- ✅ シリアル通信: SSV/TSV/CSV/JSONLのフォーマット対応(v1.7.0以降)
- ✅ タイムスタンプ: RTC機能(
unix_timestamp)実装済み(v1.9.4) - ✅ WiFi機能: AP/STAモード基盤整備済み(v1.8.0)
- ✅ コマンド処理: テキスト/バイナリプロトコル対応(v1.8.6)
- ⏳ マルチスレッド化: デュアルコア分離予定(v2.0.0前半)
REFACTORING_ROADMAP での計画¶
- Phase 1(v2.0.0中盤): USB接続ベースの複数台管理
- ボード識別システム(デバイスID、シリアル番号)
- データ統合フォーマット
- タイムスタンプ同期(相対時刻)
- PC側: Python + PySerial での統合スクリプト
- Phase 2/3(v2.0.0後半以降): WiFi経由の同期通信
- WiFi安定化検証が前提
- ネットワーク同期機構(NTP等)
- 中央サーバーへの集約
検討項目(決定が必要な設計ポイント)¶
1. デバイス識別方式¶
複数ボードを区別するための識別子の設計を検討した
案A: MAC アドレス(自動取得)¶
- 利点:ESP32の固有番号、手動設定不要、業界標準
- 欠点:英数字(e.g.,
A4:CF:12:AB:CD:EF)、人間が覚えにくい - 実装:
WiFi.macAddress()で自動取得可能- ファイル名などに使用する場合、コロンなしのlowercaseにする
案B: シリアルナンバー(手動割り当て)¶
- 利点:短くて覚えやすい(e.g.,
OSECHI-001,OSECHI-002) - 欠点:手動設定が必要、初期化フロー設計が必要
- 実装:
SET_DEVICE_ID/GET_DEVICE_IDコマンドで操作- LittleFS(v2.0.0計画)または
EEPROMに保存予定
案C: 両方実装(オプション)¶
- MAC + シリアル名の併用
- ユーザーが選択可能
2. タイムスタンプ同期戦略¶
複数ボードの検出イベント時刻の同期の設定を検討した
案A: 各ボードが独立RTC使用¶
- 相対時刻での同期(PC側で時刻合わせ)
- 利点:シンプル、ボード独立、PC側で調整可能
- 欠点:長期運用時にドリフト発生可能
- 用途:短期実験、開発テスト向け
案B: NTP(Network Time Protocol)連携¶
- WiFi経由で外部タイムサーバーと同期
- 利点:全ボード共通の絶対時刻保証
- 欠点:WiFi環境が必須、外部依存
- 用途:長期測定、本格運用向け
案C: PC側基準クロック(SET_TIME コマンド)¶
- PCから各ボードに
unix_timestampをSET_TIMEで配信 - 利点:PC側で一元管理、簡単
- 欠点:PC ⇔ ボード間通信遅延の影響
- 用途:1:N接続で有効
3. 実装ロードマップの優先度¶
推奨案(USBケーブル接続ベース):
- v2.0.0前半: マルチスレッド化(デュアルコア分離)✅ 既計画
- v2.0.0中盤 - Phase 1(USB/シリアル基盤)優先実装:
- N:N接続対応(1:1をスケール)
- 1:N接続対応(単一PCで複数ボード管理)
- ボード識別システム(MACアドレス + device_id)
- PC側統合スクリプト(Python + PySerial)
- v2.0.0後半:
- LittleFS導入(device_id永続化)
- WiFi安定化検証(Phase 2へ向けた準備)
- v2.1.0以降 - Phase 2(WiFi対応):
- WiFi経由での複数ボード管理
- NTP連携またはGNSSモジュール対応
- 中央サーバーへの集約
設計方針¶
以下の方針で設計を進めます。
1. デバイス識別方式 → 案C(両方実装)¶
- MACアドレス:自動取得、デバイス追跡用
- シリアルナンバー:ユーザー設定可能、人間にわかりやすい識別
- 実装:LittleFS(v2.0.0導入予定)またはEEPROMに保存
- 出力形式:JSONレスポンスに両者を含める
{"device_id":"OSECHI-001", "mac_address":"A4:CF:12:AB:CD:EF", ...}
2. タイムスタンプ同期戦略 → 案A(相対時刻)+ 案B(GNSS将来対応)¶
-
基本実装(Phase 1):各ボードが独立RTC使用
- 相対時刻での同期(PC側で時刻合わせ)
- v1.9.4で既実装の
unix_timestampを活用 - 短期実験、開発テスト向け
-
将来対応(v2.1.0以降):GNSSモジュール(GPS等)追加検討
- 絶対時刻取得が可能に
- 外部依存性低減(WiFi不要)
- 長期測定、本格運用向け
3. 実装スコープ → Phase 1(物理ケーブル/USB接続)優先¶
- WiFi対応は「様子見」、基本は物理ケーブル(シリアル通信)
-
Phase 1(v2.0.0中盤):USB/シリアル基盤
- ボード識別システム(MACアドレス + シリアルナンバー)
- PC側統合スクリプト(Python + PySerial)
- データ統合フォーマット(JSONL活用)
-
Phase 2/3(v2.1.0以降、WiFi安定化後):WiFi対応検討
- NTP連携またはGNSSモジュール連携
- ネットワーク同期機構
- 中央サーバーへの集約
4. WiFi安定化 → 現在は様子見、後続フェーズで判断¶
- v1.8.0での基盤実装は継続維持
- 長期運用テストはPhase 1完了後に実施
- Phase 3実装前に24時間以上の安定性テスト
責任分界の検討¶
kurikintonsと外部DAQツール(haniwers)Python DAQツール間での責任分界を検討した。
kurikintonsの責任¶
各OSECHIボード個別の機能
- ✅ 宇宙線検出:物理的な検出、信号処理
- ✅ センサー読み込み:BME280、ADC、GNSS(将来)など
- ✅ デバイス識別:MACアドレス自動取得、シリアルナンバー管理
- ✅ タイムスタンプ記録:RTC(unix_timestamp)、検出タイミング
- ✅ シリアル出力:JSONL形式での検出イベント送信
- ✅ コマンド処理:テキスト/バイナリプロトコル
- ✅ LED制御、検出イベント管理
- 検討中: ボード間の同期信号(将来、マスター/スレーブ方式の検討)
haniwersの責任¶
複数ボード統合・管理・解析
- 複数シリアルポート監視(USBハブ経由)
- 各ポートからのJSONL受信・パース
- タイムスタンプ同期(各ボードの
unix_timestamp比較・補正) - データロギング(CSV、JSON、HDF5等)
- リアルタイム可視化(
matplotlib、plotlyなど) - マルチボード統計(検出率、相関分析等)
- ファイル管理(出力ディレクトリ構成)
- 設定管理(ボード初期化、パラメーター一括設定)
具体的な作業分担例¶
1:1接続(PC ← → OSECHI)¶
graph TB
subgraph OSECHI["OSECHI"]
direction LR
detect["検出"]
sensor["センサー読込"]
output["JSONL送信"]
detect --> sensor --> output
end
subgraph PC["PC-DAQ"]
direction LR
recv["受信"]
log["ログ出力"]
viz["可視化"]
recv --> log --> viz
end
output -->|serial| recv
style OSECHI fill:#e1f5ff
style PC fill:#f3e5f5
N:N接続(PC ← → OSECHI ×N)¶
graph LR
subgraph Setup1["セットアップ1"]
direction LR
OSECHI1["OSECHI-1"]
OSECHI1 -->|serial| PCA["PC1-DAQ"]
end
subgraph Setup2["セットアップ2"]
direction LR
OSECHI2["OSECHI-2"]
OSECHI2 -->|serial| PCB["PC2-DAQ"]
end
subgraph Setup3["セットアップ3"]
direction LR
OSECHI3["OSECHI-3"]
OSECHI3 -->|serial| PCC["PC3-DAQ"]
end
style OSECHI1 fill:#e1f5ff
style OSECHI2 fill:#e1f5ff
style OSECHI3 fill:#e1f5ff
style PCA fill:#f3e5f5
style PCB fill:#f3e5f5
style PCC fill:#f3e5f5
1:N接続(PC ← → OSECHI×N)¶
graph LR
OSECHI1["OSECHI-1"]
OSECHI2["OSECHI-2"]
OSECHI3["OSECHI-3"]
OSECHI1 -->|COM1| HUB["USB Hub"]
OSECHI2 -->|COM2| HUB
OSECHI3 -->|COM3| HUB
HUB -->|serial| PC["PC-DAQ"]
subgraph PC_Functions["PC"]
monitor["複数ポート同時監視"]
sync["タイムスタンプ同期"]
stats["マルチボード統計"]
agg["統合ログ"]
monitor -.-> sync -.-> stats -.-> agg
end
style OSECHI1 fill:#e1f5ff
style OSECHI2 fill:#e1f5ff
style OSECHI3 fill:#e1f5ff
style PC fill:#f3e5f5
style PC_Functions fill:#f3e5f5
各ボードはまったく独立:
- 各ボード内部の検出・計測は独立
- PC側で時刻合わせ、相関分析を実施
- ボード間通信なし(物理ケーブル接続のみ)
デバイス識別システム¶
MACアドレス取得方式の検討¶
案1(ファームウェア側)¶
kurikintonsからGET_MAC_ADDRESSコマンドでMACアドレスを返す
- 利点:ファームウェアですでに取得可能、クエリで即座に確認可能
- 欠点:毎回シリアル通信が必要、若干の遅延
- 実装:
WiFi.macAddress()をコマンドハンドラーに追加
案2(DAQ側)¶
esptoolで直接ファームウェアイメージから読み取り
- 利点:ファームウェア変更不要、ボード識別が初期化フロー完全に外部で管理可能
- 欠点:esptoolの追加依存、USB接続時のみ動作(シリアル接続時は不可)
- 実装:Python DAQツールにesptool統合
推奨案:案1 + 案2の併用¶
- 初期化フロー(セットアップ時):DAQ側で
esptoolで一括取得、ボードマッピング表作成 - ランタイム確認:
kurikintonsからGET_MAC_ADDRESSコマンドで確認 - 利点:柔軟性が高い、メンテナンス容易
詳細設計¶
ファームウェア¶
GET_MAC_ADDRESSコマンド追加(テキストプロトコル)- JSONL出力にはシリアルナンバー(device_id)のみ含める
- MACアドレスはオンデマンド取得(コマンド経由)
DAQ側¶
- 初期化時に
esptoolで各ボードのMACアドレスを取得 - ボードマッピングテーブル作成(COM1 → MAC → OSECHI-001)
- 出力ファイルにボード情報(MAC、device_id、COMポート等)を記録
- ランタイムで必要なら
GET_MAC_ADDRESSでクロスチェック
タイムスタンプ同期¶
- ファームウェア:各ボード独立RTC、
unix_timestamp出力 - DAQ側:受信時刻との比較で同期確認、補正(1:N接続での時刻オフセット計算)
将来(GNSS対応時)¶
- ファームウェア:GPS/NTP連携(v2.1.0以降、オプション)
- DAQ側:外部タイムソース検証(GNSS信号確認時のみ使用)
シリアルナンバー管理の実装方針¶
- ファームウェア:コマンドを追加
GET_DEVICE_ID- 現在のシリアルナンバーを返すSET_DEVICE_ID <name>- シリアルナンバーを設定(例:SET_DEVICE_ID OSECHI-001)- 出力フォーマット:
STATUSコマンドのレスポンスにdevice_idを追加する - メモリ管理:
- 現在:セッション中メモリに保持(電源切ると初期化)
- 将来:LittleFS/EEPROMに永続保存(v2.0.0以降の検討事項)
- DAQ側
- 設定ファイル(TOML)からボード設定を読み込む
- セットアップ時
esptoolで各ボードのMACアドレスを自動取得(セットアップ時)- 各ボードに
SET_DEVICE_IDコマンドを送信して初期化 - ランタイム:
- セッション開始時に
STATUSコマンドで確認 - 保存先のファイルを変える時はセッションを変更
利点¶
- ファームウェアシンプル:RAMのみ使用、複雑な永続化ロジック不要
- Python側で管理:設定ファイル一元管理、複数ボード一括初期化可能
- デバイス交換対応:esptool + SET_DEVICE_IDで新ボードを素早く識別・設定可能
- 将来拡張性:LittleFS導入時に永続化を追加可能
ファイル保存の仕様(Python DAQ側)¶
ディレクトリ構造¶
current_workspace/
└── 20251129_a4cf12abcdef/ # yyyymmdd_mac_address(小文字)
├── cosmic_2025-11-29_10h30m45s_a4cf12abcdef.jsonl
├── cosmic_2025-11-29_10h45m12s_a4cf12abcdef.jsonl
└── metadata_device_a4cf12abcdef.jsonl
└── 20251129_b5d023bcdef0/ # 別ボードの例
├── cosmic_2025-11-29_11h00m00s_b5d023bcdef0.jsonl
└── metadata_device_b5d023bcdef0.jsonl
ファイル命名規則¶
データファイル¶
cosmic_yyyy-mm-dd_HHhMMmSSs_{mac_address}.jsonl
- 例:
cosmic_2025-11-29_10h30m45s_a4cf12abcdef.jsonl - タイムスタンプを先に配置(時系列でソート)
- MACアドレス(小文字、コロン除去)をファイル名に含める(一意性が高い)
- 1セッション(コマンド実行~終了)ごとに新規ファイル作成
- JSONL形式(各行が検出イベント)
メタデータファイル¶
metadata_session_{mac_address}.jsonlmetadata_device_{mac_address}.jsonlmetadata_environment_{mac_address}.jsonl- 各メタデータファイルにもMACアドレス(小文字)を含める
- 複数ボードのメタデータを一括処理する際に識別容易
ボード識別(boardid)¶
採用方式: MACアドレス(小文字、コロン除去)
- 形式:
a4cf12abcdef(小文字12文字、コロン除去) - ディレクトリ:
20251129_a4cf12abcdef/ - ファイル名:
cosmic_2025-11-29_10h30m45s_a4cf12abcdef.jsonl - メタデータ:
metadata_device_a4cf12abcdef.jsonl
選定理由:
- 一意性: ESP32の固有番号で重複なし
- 自動取得: esptoolで自動取得可能、手動設定不要
- ファイル名に含める: ボードを人間が確実に識別可能
- 小文字統一: ファイルシステムの互換性向上
セッション管理¶
- コマンド実行時にcurrent workspaceを基準に起動
- ボード設定ファイルから各MACアドレスを取得
- 各MACアドレスについてサブディレクトリを作成(
yyyymmdd_mac_address形式) - データファイルを時系列+MACアドレス付きで該当ディレクトリに保存(
cosmic_yyyy-mm-dd_HHhMMmSSs_mac_address.jsonl) - セッション終了時にメタデータを記録(MACアドレス付きファイル名)
複数ボード同時記録例(1:N接続)¶
current_workspace/
├── config.json
├── 20251129_a4cf12abcdef/
│ ├── cosmic_2025-11-29_10h30m45s_a4cf12abcdef.jsonl (Board-A data)
│ ├── cosmic_2025-11-29_10h31m02s_a4cf12abcdef.jsonl (Board-A data)
│ ├── metadata_device_a4cf12abcdef.jsonl
│ └── metadata_session_a4cf12abcdef.jsonl
├── 20251129_b5d023bcdef0/
│ ├── cosmic_2025-11-29_10h30m45s_b5d023bcdef0.jsonl (Board-B data)
│ ├── cosmic_2025-11-29_10h31m15s_b5d023bcdef0.jsonl (Board-B data)
│ ├── metadata_device_b5d023bcdef0.jsonl
│ └── metadata_session_b5d023bcdef0.jsonl
└── 20251129_c6e134cdef01/
├── cosmic_2025-11-29_10h30m50s_c6e134cdef01.jsonl (Board-C data)
├── cosmic_2025-11-29_10h31m20s_c6e134cdef01.jsonl (Board-C data)
├── metadata_device_c6e134cdef01.jsonl
└── metadata_session_c6e134cdef01.jsonl
メタデータ記録戦略¶
記録タイミング:
- セッション開始時:
STATUSコマンド実行直後にメタデータを記録 - セッション終了時: メタデータは保存不可(呼び出し時点で終了)、開始時点の情報のみ
ファイル分割方式(推奨):
各メタデータ種類ごとに別ファイルを作成して、JSONL行の形式を統一。解析時にpandas/polarsで一括読み込み可能:
yyyymmdd_mac_address/
├── cosmic_yyyy-mm-dd_HHhMMmSSs_mac_address.jsonl # 検出イベント(複数セッション、時系列ソート)
├── metadata_session_mac_address.jsonl # セッション開始情報
├── metadata_device_mac_address.jsonl # ボード情報
└── metadata_environment_mac_address.jsonl # 環境情報
各メタデータファイルの仕様:
- metadata_session_{mac_address}.jsonl(セッション開始時に記録):
{"record_type":"session_start", "timestamp":"2025-11-29T10:30:45.123Z", "data_file":"cosmic_2025-11-29_10h30m45s_a4cf12abcdef.jsonl"}
- 各行の形式統一:全て
record_typeとtimestamp、data_fileを含む -
MACアドレスを含めてファイル識別容易
-
metadata_device_{mac_address}.jsonl(STATUSコマンド結果から):
{"record_type":"device_status", "device_id":"OSECHI-001", "mac_address":"a4:cf:12:ab:cd:ef", "com_port":"COM3"}
-
デバイス識別情報を統一形式で記録
-
metadata_environment_{mac_address}.jsonl(ツール側の環境情報):
{"record_type":"environment", "python_version":"3.11.0", "tool_version":"1.0.0", "stream_format":"JSONL"}
- ツール環境を統一形式で記録
利点:
- 形式統一: 各ファイル内で行の形式が一定(pandas/polarsで直接読み込み可能)
- スケーラビリティ: 複数セッション、複数ボードのデータを追記形式で保存
- 解析容易性: ファイルごとにDataFrameに変換して処理可能
df_cosmic = pd.read_json('cosmic_2025-11-29_10h30m45s.jsonl', lines=True)
df_device = pd.read_json('metadata_device.jsonl', lines=True)
df_session = pd.read_json('metadata_session.jsonl', lines=True)
- record_type保持: ファイル分割後もrecord_typeフィールドで追加情報を記録
- 統合解析容易: sessionファイルでdata_fileを取得 → 対応する検出データを読み込み → deviceファイルで補足情報を参照
デメリット回避:
- ファイル数が増えてもメタデータファイルは小さい(セッション開始時のみ追記)
- cosmos_*.jsonlは検出データのみで行の形式が統一
次のステップ¶
-
ファームウェア実装仕様の詳細化(v2.0.0中盤向け)
GET_DEVICE_ID、SET_DEVICE_IDコマンド実装STATUSレスポンスにdevice_id追加- JSONL出力にdevice_idフィールド追加
- メモリ管理:静的バッファーまたは動的割り当て
-
Python DAQツール仕様の策定
- 設定ファイルスキーマ定義(JSON)
- esptool統合方法
- 複数シリアルポート同時管理
- タイムスタンプ同期アルゴリズム
- データ保存形式
-
Phase 1実装順序
- ファームウェア優先(デバイスID、JSONL拡張)
- Python側の整備
- 統合テスト(1:1 → 1:N)
-
将来的な検討事項
- LittleFS導入(v2.0.0後半)
- device_idの永続化
- GNSS対応(v2.1.0向け)
リソース¶
- REFACTORING_ROADMAP.md セクション 2「マルチボード対応」
- 既実装: RTC(v1.9.4)、WiFi基盤(v1.8.0)、シリアルフォーマット統一(v1.7.0)