リファクタリング方針: MQTT ネイティブ移行

進捗状況

Phase

状態

内容

Phase 1

✅ 完了

TCP→MQTT ブリッジ + InfluxDB + NiceGUI

Phase 1.5

✅ 完了

フロントエンド刷新 (FastAPI + Vite/React/TypeScript)

Phase 2

未着手

衛星ファームウェア MQTT ネイティブ化

現在のアーキテクチャ (Phase 1.5: FastAPI + React)

flowchart LR
    subgraph Satellite["衛星 (Pico W)"]
        sat_tcp[TCP Server<br/>:80 CMD / :81 TLM]
    end
    subgraph Ground["地上局"]
        bridge[bridge.py<br/>TCP→MQTT]
        server[server.py<br/>FastAPI]
        ui[React UI<br/>Vite dev server]
    end
    subgraph Infra["インフラ"]
        mqtt_broker[(Mosquitto)]
        influxdb[(InfluxDB)]
    end

    sat_tcp -- TCP:81 TLM/IMG --> bridge
    bridge -- publish --> mqtt_broker
    mqtt_broker -- subscribe --> server
    server -- write --> influxdb
    server -- WebSocket --> ui
    server -- query --> influxdb
    ui -- REST API --> server
    server -- publish CMD --> mqtt_broker
    mqtt_broker -- subscribe CMD --> bridge
    bridge -- TCP:80 --> sat_tcp

目標アーキテクチャ (Phase 2: MQTT ネイティブ)

flowchart LR
    subgraph Satellite["衛星 (Pico W)"]
        sat_mqtt[MQTT Client<br/>lwIP MQTT]
    end
    subgraph Ground["地上局 (Python)"]
        server[server.py<br/>FastAPI]
    end
    subgraph Infra["インフラ"]
        mqtt_broker[(Mosquitto)]
        influxdb[(InfluxDB)]
    end

    sat_mqtt -- publish TLM/IMG --> mqtt_broker
    mqtt_broker -- subscribe CMD --> sat_mqtt
    mqtt_broker -- subscribe --> server
    server -- write --> influxdb
    server -- query --> influxdb
    server -- publish CMD --> mqtt_broker

Phase 2 で削除されるもの: bridge.py のみ。 server.py は変更不要。


Phase 2 実装手順

Step 1: 衛星ファームウェアの MQTT 対応

  1. lwIP MQTT を有効化lwipopts.h に以下を追加:

    #define LWIP_TCP 1
    #define MQTT_REQ_MAX_IN_FLIGHT 5
    

    CMakeLists.txtpico_lwip_mqtt をリンク:

    target_link_libraries(satelite pico_lwip_mqtt)
    
  2. hal/mqtt.h / hal/mqtt.cpp を新規作成 — 以下の API:

    int mqtt_init(const char *broker_ip, uint16_t port);
    int mqtt_publish(const char *topic, const uint8_t *data, uint16_t len);
    int mqtt_subscribe(const char *topic, mqtt_callback_t cb);
    
  3. テレメトリ送信を置き換えmain.cpp:

    • wifi_write(telemetry)mqtt_publish("sat/telemetry", json_payload)

    • テレメトリフォーマットを JSON に変更(bridge.py のパース互換)

    • 画像: mqtt_publish("sat/image", ...) ※ QoS 0, 分割送信は MQTT レイヤーが処理

  4. コマンド受信を置き換え:

    • wifi_read() ループ → mqtt_subscribe("sat/command", cmd_callback)

Step 2: 通信テスト

  • Mosquitto のログで衛星からの publish を確認

  • server.py が変更なしで動作することを確認

Step 3: bridge.py を削除

  • bridge.py を削除

  • config.py から SAT_HOST, SAT_CMD_PORT, SAT_TLM_PORT を削除


MQTT トピック設計 (Phase 1 / 2 共通)

トピック

方向

ペイロード

QoS

sat/telemetry

衛星→地上

JSON

0

sat/image

衛星→地上

バイナリ (メタ長+JSON+画像)

0

sat/command

地上→衛星

テキスト COMMAND,VALUE

1


注意事項

  • Pico W の MQTT ペイロード上限: lwIP の MQTT 実装はデフォルトでペイロードサイズに制限がある。320×240 = 76,800 バイトの画像は分割 publish が必要になる可能性あり。

  • ブローカーの QoS: テレメトリは QoS 0 (欠損許容)、コマンドは QoS 1 (到達保証) を推奨。

  • WiFi 再接続: MQTT のクリーンセッション / Will メッセージで接続断を検知可能。

  • JSON フォーマット統一: Phase 2 では衛星が直接 JSON を生成するため、cJSON ライブラリ (Pico SDK 同梱) の使用を推奨。