State Monitoring
Looking at the return value of read_state of the Client lets you monitor whether the communication with the devices is working correctly. read_state sends a liveness check to every device and gathers the replies, and its Response carries device_status.
Obtaining the State
Section titled “Obtaining the State”device_status of a Response returns an array of the state DeviceStatus of each device at the time of the replies.
DeviceStatus holds the following.
state: the state of the device (DeviceState).ptp_locked: whether its PTP is locked.failsafe_active: whether it stopped its output by the failsafe and has not been released yet
Aggregates such as whether every device is Ready are built from the returned values (see the example below).
ptp_locked and failsafe_active are taken from those replies.
The meaning of each DeviceState is as follows.
| State | Meaning |
|---|---|
Ready |
The device replies and its time is synchronized |
Syncing |
The device replies, but its time is still being synchronized |
The following is an example that sends a liveness check at fixed intervals, looks at device_status, and outputs only when the state changes.
let mut last: Vec<DeviceStatus> = Vec::new();loop { let Ok(response) = tokio::time::timeout(CHECK_INTERVAL, client.read_state()).await else { println!("not every device replied within {CHECK_INTERVAL:?}"); continue; }; let status = response?.device_status(); if last != status { for (i, s) in status.iter().enumerate() { println!("device[{i}]: {}", s.state); } println!( "all ready: {}", status.iter().all(|s| s.state == DeviceState::Ready) ); last = status; } tokio::time::sleep(CHECK_INTERVAL).await;}last = Nonewhile True: try: response = await asyncio.wait_for(client.read_state(), timeout=CHECK_INTERVAL) except TimeoutError: print(f"not every device replied within {CHECK_INTERVAL} s") continue status = response.device_status() if status != last: for i, s in enumerate(status): print(f"device[{i}]: {s.state}") all_ready = all(s.state == DeviceState.Ready for s in status) print(f"all ready: {all_ready}") last = status await asyncio.sleep(CHECK_INTERVAL)DeviceStatus[] last = Array.Empty<DeviceStatus>();while (true){ using var timeout = new CancellationTokenSource(CheckInterval); DeviceStatus[] status; try { status = (await client.ReadStateAsync(timeout.Token)).DeviceStatus(); } catch (OperationCanceledException) { Console.WriteLine($"not every device replied within {CheckInterval}"); continue; } if (!status.SequenceEqual(last)) { for (var i = 0; i < status.Length; i++) { Console.WriteLine($"device[{i}]: {status[i].State}"); } var allReady = status.All(s => s.State == DeviceState.Ready); Console.WriteLine($"all ready: {allReady}"); last = status; } await Task.Delay(CheckInterval);}