#show tech >>log

Raspberry Pi 3B で自宅のテレビをどこでも見る ── 改修編② 壊れても映り続ける

>> はじめに - 321回の再起動

改修編① で「不調の理由を画面に出す」ところまで作った.そのきっかけになった事故から始める.

夕方,外出先からテレビを見ようとして見られなかった.帰宅してログを見るとこうだった.

error - failed on B_CAS_CARD::init() : code=-4
Scheduled restart job, restart counter is at 321

B-CAS カードリーダーが応答しなくなっていた.フルセグの復号にはカードが要るので,配信は立ち上がれない.Restart=always が律儀に拾い,立てんものを321回起こし続けていた.

カードを物理的に挿し直したら直った.つまりソフトの問題ではない.

だがここで思った.前日に入れたワンセグは B-CAS を使わない.カードが死んでもテレビは映り続けられるはずだ.

>> 自動でワンセグへ逃げる

60秒もたずに終わった回を «失敗» と数える
    ↓ 3回続けて失敗し,今がフルセグなら
★ワンセグへ落ちる(B-CAS を使わん段)
    ↓
赤帯に «落ちていること» を出し続ける
    ↓ 画質を選び直したら
数え札と表示を消してやり直す

ここで二の足を踏んだ.実は数日前,別の場面で「自動で逃げる」仕組みを外したばかりだったからだ.

当初の画面には AUTO / LIVE / DEMO という選択があり,AUTO は放送が取れんと黙って試験映像へ逃げていた.これは故障を隠す.チューナーが載った時点で外していた.

では今回の逃げは何が違うか.

DEMO への逃げ   «黙って» 逃げ,故障が分からん
ワンセグへの逃げ ★«逃げたことを言う».映っても赤帯は消えん

逃げること自体は悪くない.悪いのは黙って逃げることだった.テレビが映り続けるほうが実用に適う——ただし故障は必ず目に入る形で.

>>> 短気すぎた閾値

最初は「3回失敗したら逃げる」にした.だが RestartSec=2 なので6秒で届いてしまう.

ワンセグからフルセグへ戻る際,mirakc がチューナーを離す間に2~3回躓くことはありうる.そこで落とされると「フルセグにできん」ように見える.

実際,検証中にそれが起きたと思った.だが真相は違った——カードを本当に抜いて検証していただけで,仕組みは正しく働いていた.

「回数」だけでは「速く3回死ぬ」と「長く直らん」を区別できん——時間の条件を足すべきだった,というのが残った孿題だ.

>> カードを «電気的に» 挿し直す

「ボタンで直せないか」と問われた.USB にはその手がある.

echo 1-1.5 > /sys/bus/usb/drivers/usb/unbind
sleep 2
echo 1-1.5 > /sys/bus/usb/drivers/usb/bind

カーネルに「抜いて挿す」のと同じことをさせる.幸いなことに構成が良かった.

ハブ 1-11-1.1  LAN(smsc95xx)   ← ★触ってはならん
 ├ 1-1.4  チューナー
 └ 1-1.5  カードリーダ      ← 独立したポート

カードリーダだけを狙える.チューナーも LAN も巻き込まない.

>>> 型番で決め打ちにせん

ここで大事なのは探し方だ.

# ✕ 型番(04e6:5116)で決め打ち → リーダを換えたら壊れる
# ✅ USB のインターフェースクラス 0x0B(スマートカード)で探す
for itf in Path("/sys/bus/usb/devices").glob("*:*"):
    if (itf / "bInterfaceClass").read_text().strip().lower() == "0b":
        return itf.name.split(":")[0]      # → "1-1.5"

取り違えればネットワークごと落ちる.検証では「0x0B として見つかったのがカードリーダだけか」を実際に確かめてから進めた.

>>> 自動ではやらん

「3回失敗したら自動で一度だけ入れ直す」という案も出たが,人が押す形に留めた.

ハードの故障に対して機械が繰り返し reset をかけるのは筋が悪い.ボタンはカードのエラーが出ている時だけ赤帯の中に現れる.関係ない時に押せる場所へ置くと,いつか誤って押される.

✅ カードを認識しました(low)
🔴 入れ直しましたが認識されません(物理的に挿し直してください)
🔴 入れ直しましたが配信が立ちません

結果は正直に返す.直らない時に「直しました」と言うのがいちばん悪い.

>> 監視が «自分で作った関所» に締め出された

別の日,端末の登録制(→ 改修編③)を入れた.その2分後から,監視が鳴り始めた.

07:51  関所を入れた(合鍵が無ければ 40307:53  tv-health が «自分で» 弾かれ始める
         curl 8080/403
         curl 8080/state  → 403
以降   5分ごとに «異常2件» を検知し続ける

監視が自分で作った関所に締め出されていた.一時的な不調ではなく,放っておけば永遠に鳴る種類の壊れ方だった.

# ✕ curl 8080/       → 合鍵が無いゆえ 403
# ✅ curl 8080/enroll/ → 自宅からは通る。nginx が配れておるか判る

# ✕ curl 8080/state  → 関所に弾かれる
# ✅ curl 8081/state  → tv-switch を直に叩く(nginx を経由せん)

監視は «守りの内側» から確かめる.守りに弾かれては,何を測っているのか分からない.

新しい守りを入れる時は «既に通っている者» を数える.
ブラウザのことしか考えておらず,同じ入口を使う監視を忘れていた.
しかも通知は届いていたのに,自分では確かめていなかった.

>> 8日間気づかなかった穴

もう一つ,この日見つかったものがある.

再起動の後,番組表が 0件になっていた.前日も同じことが起きていて,その時は「そういうもの」と思って収集し直していた.

二度目でさすがにおかしいと思って調べた.

ExecStart  -v mirakc-epg:/var/lib/mirakc/epg   ← ★保存先は繋いである
config.yml epg の記述 0件                     ← ★書く設定が無い

入れ物だけ用意して,中身を入れていなかった.ボリュームは8日前から繋いであったのに,mirakc に「そこへ書け」と言っていなかった.

epg:
  cache-dir: /var/lib/mirakc/epg

この3行が抜けていただけだった.

入れて収集し直し,わざと再起動して確かめた.

再起動 前: 6655 件
再起動 後: 6655 件   ✅ 生き残った
schedules.json  5.2MB

これが無ければ,停電や不意の再起動のたびに最大21時間番組名が出ないことになる.

一度 «消えた» のを見ておるのに «仕様» で済ませたのが落ち度だ.
動いているように見えて,半分しか出来ていなかった.

>> まとめ

  • 逃げること自体は悪くない.悪いのは黙って逃げること
  • 回数だけでは「速く死ぬ」と「長く直らん」を区別できん.時間の条件を足す
  • 型番で決め打ちにせずクラスで探す.取り違えればネットワークごと落ちる
  • ハードの故障に機械が繰り返し reset をかけない.人が押す
  • 新しい守りを入れる時は «既に通っている者» を数える
  • 監視は守りの内側から確かめる
  • 一度「消えた」を見たら,「仕様」で済ませない

次は改修編③ 外へ出す.端末の登録制と,「入口を分けねばならん」と気づいた実データの話だ.