フェイルセーフ
ホストとの通信が途絶えたときや PTP のロックを失ったときに, 自分で出力を止めるフェイルセーフ機能がある. どちらも既定では無効で, SetCpuConfig で有効化できる.
通信途絶の failsafe と生存確認
Section titled “通信途絶の failsafe と生存確認”failsafe_timeout を指定すると, ホストからの通信がその時間途絶えたデバイスは出力を止める.
既定は None (無効) で, ホストのクラッシュやケーブル断で通信が途絶えてもデバイスは超音波を止めない.
Client は既定では, 送るものが無い間, 自分からはデバイスへ何も送らない.
そのため failsafe_timeout を指定した場合は, TransportOption の heartbeat_interval を指定して, 生存確認を定期的に送り続けさせる必要がある.
間隔は failsafe_timeout より十分短くする (半分未満を目安にする).
以下は, failsafe_timeout を 100 ms にして, 10 ms ごとに生存確認を送る例.
let option = TransportOption { heartbeat_interval: Some(Duration::from_millis(10)), ..Default::default()};let mut client = Client::open(&geometry, &option).await?;
client .send(SetCpuConfig::new(CpuConfig { failsafe_timeout: Some(Duration::from_millis(100)), ..Default::default() })) .await?;client = await Client.open(geometry, TransportOption(heartbeat_interval=Duration.from_millis(10)))
await client.send(SetCpuConfig(CpuConfig(failsafe_timeout=Duration.from_millis(100))))var client = await Client.OpenAsync(geometry, new TransportOption { HeartbeatInterval = TimeSpan.FromMilliseconds(10) });
await client.SendAsync(new SetCpuConfig(new CpuConfig { FailsafeTimeout = TimeSpan.FromMilliseconds(100) }));failsafe で止まった出力は, 自動では戻らない.
止まっているかどうかは返信 (Response) の device_status() が返す DeviceStatus の failsafe_active で確認でき, ReleaseFailsafe を送ると再開する (Clearでも良いが, その場合, すべての状態が初期化される).
PTP failsafe の検出と解除
Section titled “PTP failsafe の検出と解除”SetCpuConfig で ptp_unlock_failsafe_timeout を指定すると, PTP のロックを失ったまま指定の時間が経ったデバイスは出力を止める.
以下は, failsafe_active が立っていて再ロックした (ptp_locked が立っている) デバイスへ ReleaseFailsafe を送る例.
let status = client.read_state().await?.device_status();let releasable = |s: &DeviceStatus| s.failsafe_active && s.ptp_locked;if status.iter().any(releasable) { client .send(each(|device| { releasable(&status[device.idx()]).then_some(ReleaseFailsafe) })) .await?;}status = (await client.read_state()).device_status()
def releasable(s: DeviceStatus) -> bool: return s.failsafe_active and s.ptp_locked
if any(releasable(s) for s in status): await client.send(each(lambda device: ReleaseFailsafe() if releasable(status[device.idx()]) else None))var status = (await client.ReadStateAsync()).DeviceStatus();static bool Releasable(DeviceStatus s) => s.FailsafeActive && s.PtpLocked;if (status.Any(Releasable)){ await client.SendAsync(Command.Each(device => Releasable(status[device.Idx]) ? new ReleaseFailsafe() : null));}ロックを失ったままのデバイスへ ReleaseFailsafe を送ってもエラーになり, 出力は止まったままになる.