[!NOTE]
2026-09-23 現行GitHub同期メモ現在の
google_sync_worker.pyはsummary / L0 / L1 / L2 / L3_INDEX / L4_INDEX / SYNCを扱います。#17執筆時に将来用だった L3/L4 INDEX も現行実装では同期対象です。Google障害時に観測を止めない「ローカルファースト」の方針は現在も変わっていません。
RON-V 連載リンク
← 前の記事:#16 — Google Sheets・Looker Studioの準備
→ 次の記事:#18 — LTEのL3/L4とGoogle Drive転送
L0〜L4の定義追記(2026-10-25)
本文中のコード・試験結果は執筆当時の記録として残しています。画像AI・音声を関連付ける現在の定義は次のとおりです。
| レベル | 残す内容 |
|---|---|
| L0 | Meshtastic向けの23バイト短報。画像AIの候補通知は任意設定 |
| L1 | 個別の観測・撮影/録音/認識の状態と、詳細への参照 |
| L2 | 一定時間の観測件数・分類別候補などの集計 |
| L3 | 画像AIの詳細、録音情報、文字起こし全文 |
| L4 | 元画像JPEG、元音声WAV、LTEのraw logなど |
L0の警報欄は1バイト=8ビットです。新しいversion=2の定義は、倒木 0x01、冠水 0x02、煙 0x04、道路上の障害物 0x08、路面の穴 0x10。残り3ビットは未割り当てです。0x03は倒木と冠水の組み合わせで、煙の番号ではありません。0x00はL0上では未判定で、安全を示しません。 候補ありでは元イベントの時刻・位置を使い、現在地と混同しません。
発信元はnode_uid、根拠は画像・音声などです。「処理成功」「災害の候補」「人の確認済み」を分けます。初期の確認状態はunreviewed。画像AIの検出0件を「危険なし」とせず、音声の否定も全文へ残します。人が補足・訂正する画面と、音声からの災害自動分類は今後の実装です。
10月25日にL1の関連付け・L2の集計・音声L3/L4の転送処理をコードへ追加しました。新連携の実機確認はこれからです。音声転送とL0候補通知は初期設定では無効で、個別に有効化します。従来のL0 version=1へ、この分類の意味を遡って付けません。
Looker Studioで使用中のSheets summaryはRF測定から直接出力する既存の10列で、L2とは別です。今回の追加で列名・順序・値の意味、既存Grafanaの参照項目は変えません。L1のMesh送信、写真・音声のMesh転送、自動公開は実装していません。
詳細と設定手順:データレベルの定義(リポジトリの閲覧権限が必要です)。
はじめに
RON-Vの観測結果は、最初にRaspberry Pi 5内のSQLiteへ保存します。
Google Sheetsは便利ですが一次保存先ではありません。
設計上の中心は、
Googleへ接続できなくても観測を止めない
ことです。
現在のデータフローは、
RF / LTE / Vehicle / GNSS / Mesh
↓
SQLite
↓
Google Sync Worker
↓
Google Sheets
です。
1. 同期対象
現行 google_sync_worker.py は次の7系統を扱います。
summary
L0
L1
L2
L3_INDEX
L4_INDEX
SYNC
#17初期実装時にはL3/L4は未実装でしたが、現在は #18 のEvidence生成・rclone配送と連携し、INDEXも同期対象です。
2. Google同期Worker
実装は、
app/integration/google_sync_worker.py
です。
基本動作は、
SQLite
↓
未同期データを取得
↓
Google Sheetsへappend
↓
成功
↓
cursor / export状態を更新
です。
Google APIで例外が発生した場合、測定側のSQLite保存とは独立しているため、RF/LTE/Vehicle測定には影響しません。
3. 設定
実環境では、
[google]
enabled = true
spreadsheet_id = "<SPREADSHEET_ID>"
credentials_file = "/home/ronv/.config/ronv/secrets/google-service-account.json"
を設定します。
認証JSONやSpreadsheet IDはGitHubへ登録しません。
4. cursorによる差分同期
Google同期では sync_cursors を利用します。
現行の主なcursorは、
google_summary_rf
google_l0
google_l1
google_l2
google_l3
google_l4
です。
たとえばL0では、最後に送った l0_beacons.id を保持し、次回はそれより新しい行だけを取得します。
L1 / L2 / INDEXでは、複数のデータ種別を1本の順序で扱えるよう、sync_objects.rowid をcursorとして利用する箇所があります。
5. summary
summary はLooker Studio向けの平坦な表です。
現行では rf_measurements のうち status='ok' のデータを対象にし、
band
timestamp
lat_lon
peak_count
burst_count
max_power
field_activity_index
などを書き出します。
CAN系の列もWorksheet側に用意していますが、未取得項目は空欄として扱います。
6. L0
L0では、
object_uid
packet_hex
created_at_jst
をGoogleへ出します。
Google側の重複確認キーは object_uid です。
7. L1
L1は sync_objects の、
level = 1
を対象にします。
現在は代表的に、
Vehicle Fact
LTE Fact
RF Fact
を扱います。
Googleへは、
object_uid
event_time_jst
data_type
source_table
source_id
priority
payload_json
created_at_jst
を出します。
8. L2
L2は level = 2 のCycle Summaryです。
現在のL2には、
Vehicle
LTE
RF
Mesh
latest L0
service state
などの時間窓情報が含まれます。
Google Sheetsの change_summary 列には構造化payloadを保存し、AI文章要約はまだ別機能として実装していません。
9. L3_INDEX / L4_INDEX
L3/L4のファイル本体はGoogle Sheetsには入れません。
L3 JSON
L4 raw log / JPEG
はローカルEvidenceとして生成し、rcloneでGoogle Driveへ配送します。
Google Sheetsには、
object_uid
level
event_time_jst
data_type
source_table
source_id
file_path
mime_type
bytes
sha256
upload_transport
upload_state
remote_id
などのINDEXだけを出します。
これにより、
Sheets = 検索・索引
Drive = Evidence本体
という役割分担になります。
10. SYNC
SYNC は配送状態をGoogle側から確認するためのシートです。
元データは主に sync_deliveries です。
pending
retry
inflight
sent
acked
held
failed
cancelled
などの配送状態を扱えます。
Meshtasticでは、
packet_id
ack_type
ack_from
ack_error
も保持します。
rclone配送では、
remote_id
bytes
sha256
latency
status
などを追跡できます。
11. 重複防止
Google APIでは、
append成功
↓
Pi電源断
↓
cursor更新前
というケースを考慮する必要があります。
そのため現行workerでは、単にcursorだけに依存せず、Google側の最近のキーを確認して同一キーを再appendしない処理があります。
また、INDEX / SYNCの送信済み管理には、
google_sync_exports
を利用します。
概念的には、
(stream, source_id)
を主キーにし、同じ対象を二重にexportしない構造です。
12. dry-run
送信前にはdry-runできます。
cd /home/ronv/ronv
/home/ronv/.venvs/ronv/bin/python \
-m app.integration.google_sync_worker \
--batch-size 20 \
--dry-run
SQLiteから何件取得されるかを確認してから、実送信へ進められます。
13. systemd化
Google同期は観測serviceから直接呼びません。
現行serviceは、
[Unit]
Description=RON-V Google Sheets Sync
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=ronv
Group=ronv
WorkingDirectory=/home/ronv/ronv
Environment=PYTHONUNBUFFERED=1
Environment=RONV_CONFIG=/home/ronv/ronv/config/ronv.toml
ExecStart=/home/ronv/.venvs/ronv/bin/python -m app.integration.google_sync_worker --batch-size 200
TimeoutStartSec=90
Nice=10
timerは、
[Timer]
OnBootSec=2min
OnUnitInactiveSec=5min
AccuracySec=5s
Unit=ronv-google-sync.service
です。
5分ごとに独立して同期します。
14. 通信障害時
Googleが使えない場合でも、
Google NG
↓
Google Sync失敗
↓
SQLiteは保持
↓
RF / LTE / Vehicle観測継続
となります。
通信復旧後にworkerが再度起動すると、残っている対象を順番に処理します。
これはRON-Vの重要な設計条件です。
15. 現在の動作確認
状態確認は、
systemctl status \
ronv-google-sync.timer \
--no-pager
journalctl \
-u ronv-google-sync.service \
-n 100 \
--no-pager
で行います。
Google側の構造確認は、
/home/ronv/.venvs/ronv/bin/python \
-m app.integration.google_sheet_check
を使用します。
まとめ
RON-VのGoogle同期は、
測定
↓
SQLite
↓
非同期Worker
↓
Google Sheets
です。
Googleは一次保存先ではありません。
現在は、
summary
L0
L1
L2
L3_INDEX
L4_INDEX
SYNC
まで同期対象となっています。
次の #18 では、L3/L4 Evidence本体を作り、rcloneでGoogle Driveへ非同期配送する仕組みを扱います。