Skip to content

イベント読み出しの問題

このガイドでは、kazunokoでイベント(検出データ)を読み込む際に発生する問題と解決方法を説明します。


イベント読み出しの流れ

1. デバイスにコマンドを送信 → "READ" コマンド
   ↓
2. デバイスがミューオンを検出 → 検出データが生成
   ↓
3. デバイスがイベントを返送 → JSON形式の応答
   ↓
4. kazunoko が受け取る → イベントとして処理

問題は このいずれかの段階で発生します。


EventTimeout(イベントタイムアウト)

症状

⏱ Event 23/1000: No event received within 5.0s timeout

意味: デバイスに READ コマンドを送ったが、指定時間内にイベントが返ってこなかった。

原因の分類

原因 詳細 対応
スレッショルド値が高い イベント検出が少ない スレッショルドを下げる
poll_count が少ない バッファをスキャンする回数が不足 poll_count を増やす
環境にミューオンが少ない 実験環境の問題 長くタイムアウトを設定
デバイス不調 ハードウェア故障 デバイスを再起動

対応方法

方法 1: スレッショルド値を下げる(推奨)

スレッショルド値が高いと、ノイズを除外する代わりにイベント検出が減ります。

# 現在のスレッショルドを確認
uv run kazunoko status | grep threshold

# スレッショルド値を下げる(例: CH1: 280 → 250)
uv run kazunoko measure "1:250;2:300;3:280" 100

# イベント読み込みを試す
uv run kazunoko read 10 --event-timeout 5.0

スレッショルド値の目安:

Ch1: 200-300
Ch2: 280-380
Ch3: 250-350

※ 値が小さい → より敏感に反応 → イベント数が多い

方法 2: poll_count を増やす

poll_count はデバイスのメモリバッファをスキャンする詳細さを表します。

# 推奨値 (50000)
uv run kazunoko read 100 --poll-count 50000

# 大きくする (100000)
uv run kazunoko read 100 --poll-count 100000

# 最大値 (65535)
uv run kazunoko read 100 --poll-count 65535

poll_count と処理時間の関係:

poll_count: 1000   → 高速 (取りこぼす可能性あり)
poll_count: 50000  → 大きめ (推奨)
poll_count: 65535  → 遅い (確実だが時間がかかる)

方法 3: タイムアウト時間を増やす

# デフォルト (5.0 秒)
uv run kazunoko read 100 --event-timeout 5.0

# 増やす (10.0 秒)
uv run kazunoko read 100 --event-timeout 10.0

# さらに増やす (30.0 秒)
uv run kazunoko read 100 --event-timeout 30.0

方法 4: デバイスを再起動

# デバイスの電源を切る
# → 10秒待つ
# → 再度電源を入れる

# 再度実行
uv run kazunoko read 10 --event-timeout 5.0

複合的な対応

複数の方法を組み合わせることで、より確実な読み込みが可能です。

# スレッショルドを下げて、poll_count を増やして、タイムアウトを長くする
uv run kazunoko measure "1:250;2:300;3:280" 100 \
  --poll-count 65535 \
  --event-timeout 10.0

ProtocolError / ResponseError

症状

⚠ Malformed event data, skipping: Invalid JSON: Expecting value

意味: デバイスから受け取ったデータが、期待される形式ではない。

原因

原因 詳細
ファームウェアが古い デバイスが古いバージョン
USB接続が不安定 データが破損して到着
データ形式が違う デバイスのプロトコルが変わった
デバイスメモリ破損 ハードウェア故障の可能性

対応方法

ステップ 1: ファームウェアバージョンを確認

uv run kazunoko version

出力例:

Device firmware:
  Version: v1.5.0
  ...
  • バージョンが v1.4.0 以下の場合はアップグレード推奨
  • 最新バージョンはデバイスメーカーに問い合わせ

ステップ 2: デバイスをリセット

# デバイスをリセット
uv run kazunoko reset

# リセット後、再度確認
uv run kazunoko status

ステップ 3: ケーブルを接続し直す

# USB ケーブルを抜く
# → 10秒待つ
# → 再度接続(別の USB ポートでも可)

# 再度実行
uv run kazunoko read 5 --event-timeout 5.0

ステップ 4: 詳細ログを確認

# ログファイルで詳細なエラーを確認
tail -50 ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.level.name == "ERROR" or .record.level.name == "WARNING")'

# または、デバッグレベルで実行
uv run kazunoko --level debug read 5 2> debug.log
cat debug.log | tail -30

ステップ 5: 別のケーブルで試す

USB ケーブルが破損している可能性があります。

# 別の USB ケーブルで接続
uv run kazunoko read 5 --event-timeout 5.0

イベントがスキップされている

症状

Event collection: 87/100 events received
Skipped: 13 events (87.0% success rate)

意味: 100 イベントを要求したが、87 個のみ成功し、13 個はスキップされた。

スキップの理由

kazunoko は以下の場合、イベントをスキップします。

エラー 原因 対応
EventTimeout イベント受信タイムアウト スレッショルド下げ、poll_count増加
ProtocolError データ形式エラー ファームウェアチェック、リセット
ResponseError レスポンスが無効 ケーブル確認、リセット

対応方法

成功率の確認

# 複数回実行して成功率を確認
for i in {1..5}; do
  uv run kazunoko read 100 --event-timeout 5.0
done

パラメータ最適化

# スレッショルドを下げてみる
uv run kazunoko measure "1:250;2:300;3:280" 100 \
  --poll-count 65535 \
  --event-timeout 10.0

ログから詳細を確認

# スキップされたイベントの理由を確認
tail ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.message | contains("skip")) | .record.message'

イベントが全く受け取れない

症状

Error: No event received within 5.0s timeout (attempted 100 times)

意味: 1 つもイベントが取得できない。

原因の特定フロー

1. デバイスが接続されているか?
   ↓ NO → シリアル通信の問題
   ↓ YES

2. デバイスの電源が入っているか?
   ↓ NO → 電源をオン
   ↓ YES

3. デバイスの状態は「ok」か?
   uv run kazunoko status
   ↓ NO → デバイスをリセット
   ↓ YES

4. スレッショルド値は適切か?
   ↓ 高い → スレッショルドを下げる
   ↓ YES

5. 環境にミューオンがあるか?
   ↓ NO → 場所を移動
   ↓ YES

6. デバイスハードウェアは正常か?
   ↓ 疑わしい → メーカーに問い合わせ

総合チェックリスト

# 1. デバイス接続確認
uv run kazunoko status

# 2. ファームウェア確認
uv run kazunoko version

# 3. スレッショルド確認と調整
uv run kazunoko measure "1:200;2:250;3:220" 10 \
  --poll-count 65535 \
  --event-timeout 10.0

# 4. ログで詳細確認
tail -100 ~/Library/Logs/kazunoko/kazunoko.json | jq .record.message

高速イベント読み込みのコツ

タイムアウトを短縮する場合

環境が良好でイベント検出が多い場合、タイムアウトを短縮できます。

# デフォルト (5.0 秒)
uv run kazunoko read 100 --event-timeout 5.0

# 短縮 (1.0 秒) - イベント検出が確実な場合のみ
uv run kazunoko read 100 --event-timeout 1.0

poll_count を調整する場合

# 大きめ (50000)
uv run kazunoko read 100 --poll-count 50000

# 高速 (1000) - 高速だが取りこぼすリスク
uv run kazunoko read 100 --poll-count 1000

# 確実 (65535) - 確実だが遅い
uv run kazunoko read 100 --poll-count 65535

パイプ経由でのイベント読み込み

ファイルに保存

# イベント 100 個をファイルに保存
uv run kazunoko read 100 > events.jsonl

# または、測定情報付きで保存
uv run kazunoko measure "1:300;2:320;3:310" 1000 > measurement.jsonl

リアルタイム監視

# イベントをリアルタイムで監視
uv run kazunoko read 1000 --use-sec | \
  jq '.event_count'

別のプロセスで処理

# イベントを数える
uv run kazunoko read 100 | wc -l

# 特定フィールドを抽出
uv run kazunoko read 100 | jq '.event_count'

# CSVに変換
uv run kazunoko read 100 --format csv > events.csv

Python API を使用した場合

ストリーミング読み込み

from kazunoko import connect, Reader

with connect() as device:
    reader = Reader(device)

    # カウントベース
    for event in reader.stream_by_count(100):
        print(f"Event: {event.event_count}")

    # または時間ベース
    for event in reader.stream_by_time(10.0):
        print(f"Event: {event.event_count}")

エラーハンドリング

from kazunoko import connect, Reader
from kazunoko.exceptions import (
    EventTimeout,
    ProtocolError,
    ResponseError,
)

with connect() as device:
    reader = Reader(device)
    collected = 0

    for event in reader.stream_by_count(100):
        try:
            print(f"Event {collected + 1}: {event.event_count}")
            collected += 1
        except EventTimeout as e:
            print(f"Timeout: {e}")
            continue
        except ProtocolError as e:
            print(f"Protocol error: {e}")
            continue
        except ResponseError as e:
            print(f"Response error: {e}")
            continue

    print(f"Successfully collected: {collected}/100")

ログで問題を診断

タイムアウトが多い場合

# タイムアウトイベント数をカウント
tail ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.message | contains("EventTimeout"))' | wc -l

# 診断
# → 数が多い: スレッショルド値が高い、poll_count が不足
# → 数が少ない: 環境が変わった可能性

プロトコルエラーが多い場合

# プロトコルエラー数をカウント
tail ~/Library/Logs/kazunoko/kazunoko.json | \
  jq 'select(.record.message | contains("ProtocolError"))' | wc -l

# 診断
# → 多い: ファームウェア問題、USB不安定
# → 少ない: 一時的な接続問題

次のステップ