1use std::path::PathBuf;
9use std::time::Duration;
10
11pub const RUN_DIR_DEFAULT: &str = "/run/ados";
13
14pub const RUN_DIR_ENV: &str = "ADOS_RUN_DIR";
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct SidecarPath {
20 pub id: &'static str,
21 pub path: &'static str,
23 pub max_age_ms: Option<u64>,
25 pub writer: &'static str,
27}
28
29impl SidecarPath {
30 pub const fn max_age(&self) -> Option<Duration> {
32 match self.max_age_ms {
33 Some(ms) => Some(Duration::from_millis(ms)),
34 None => None,
35 }
36 }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub struct SocketPath {
42 pub id: &'static str,
43 pub path: &'static str,
45 pub owner: &'static str,
47}
48
49pub const CLOUD_LINK_JSON: &str = "cloud-link.json";
51pub const OFFLOAD_LINK_JSON: &str = "offload-link.json";
52pub const WFB_STATS_JSON: &str = "wfb-stats.json";
53pub const WFB_STATS_MAX_AGE_MS: u64 = 10000;
54pub const HOP_SUPERVISOR_JSON: &str = "hop-supervisor.json";
55pub const HOP_SUPERVISOR_MAX_AGE_MS: u64 = 10000;
56pub const PEER_PRESENCE_JSON: &str = "peer-presence.json";
57pub const PEER_PRESENCE_MAX_AGE_MS: u64 = 10000;
58pub const MGMT_LINK_JSON: &str = "mgmt-link.json";
59pub const MGMT_LINK_MAX_AGE_MS: u64 = 90000;
60pub const MGMT_FAILOVER_JSON: &str = "mgmt-failover.json";
61pub const MGMT_FAILOVER_MAX_AGE_MS: u64 = 90000;
62pub const USB_REHOME_JSON: &str = "usb-rehome.json";
63pub const USB_REHOME_MAX_AGE_MS: u64 = 600000;
64pub const WIFI_POWERSAVE_JSON: &str = "wifi-powersave.json";
65pub const WIFI_POWERSAVE_MAX_AGE_MS: u64 = 120000;
66pub const WFB_FAILOVER_JSON: &str = "wfb_failover.json";
67pub const WFB_FAILOVER_MAX_AGE_MS: u64 = 10000;
68pub const WFB_PAIR_PROOF_JSON: &str = "wfb-pair-proof.json";
69pub const BIND_STATE_JSON: &str = "bind-state.json";
70pub const CRSF_STATS_JSON: &str = "crsf-stats.json";
71pub const CRSF_STATS_MAX_AGE_MS: u64 = 10000;
72pub const LORA_JSON: &str = "lora.json";
73pub const LORA_MAX_AGE_MS: u64 = 10000;
74pub const LORA_BEACONS_JSON: &str = "lora-beacons.json";
75pub const LORA_BEACONS_MAX_AGE_MS: u64 = 10000;
76pub const TUNNEL_CONFIG_JSON: &str = "tunnel-config.json";
77pub const TUNNEL_CONFIG_MAX_AGE_MS: u64 = 30000;
78pub const RELAYED_STATUS_JSON: &str = "relayed-status.json";
79pub const RELAYED_STATUS_MAX_AGE_MS: u64 = 20000;
80pub const LINKED_PEERS_JSON: &str = "linked-peers.json";
81pub const MESH_STATE_JSON: &str = "mesh-state.json";
82pub const MESH_STATE_MAX_AGE_MS: u64 = 10000;
83pub const WFB_RELAY_JSON: &str = "wfb-relay.json";
84pub const WFB_RELAY_MAX_AGE_MS: u64 = 10000;
85pub const WFB_RECEIVER_JSON: &str = "wfb-receiver.json";
86pub const WFB_RECEIVER_MAX_AGE_MS: u64 = 10000;
87pub const FLEET_HERO_JSON: &str = "fleet-hero.json";
88pub const CAMERA_STATE_JSON: &str = "camera-state.json";
89pub const CAMERA_STATE_MAX_AGE_MS: u64 = 300000;
90pub const CAMERAS_DISCOVERED_JSON: &str = "cameras-discovered.json";
91pub const VIDEO_STREAMS_JSON: &str = "video-streams.json";
92pub const VIDEO_STREAMS_MAX_AGE_MS: u64 = 20000;
93pub const VIDEO_PROFILE_JSON: &str = "video-profile.json";
94pub const CAMERA_USB_RECOVERY_JSON: &str = "camera-usb-recovery.json";
95pub const CAMERA_USB_RECOVERY_MAX_AGE_MS: u64 = 60000;
96pub const JANITOR_JSON: &str = "janitor.json";
97pub const PIC_STATE_JSON: &str = "pic-state.json";
98pub const GROUND_STATION_INPUT_JSON: &str = "ground-station-input.json";
99pub const GPIO_OUTPUT_JSON: &str = "gpio-output.json";
100pub const BOARD_JSON: &str = "board.json";
101pub const FC_IDENTITY_JSON: &str = "fc-identity.json";
102pub const MAVLINK_ROUTER_JSON: &str = "mavlink-router.json";
103pub const MAVLINK_ROUTER_MAX_AGE_MS: u64 = 15000;
104pub const LINK_FEEDBACK_JSON: &str = "link-feedback.json";
105pub const PLUGIN_LOOPBACK_GUARD_JSON: &str = "plugin-loopback-guard.json";
106pub const PLUGIN_STATE_MAX_AGE_MS: u64 = 10000;
107pub const AP_GUARD_JSON: &str = "ap-guard.json";
108pub const LOGD_PUSH_REQUEST_JSON: &str = "logd-push-request.json";
109pub const LOGD_PUSH_RESULT_JSON: &str = "logd-push-result.json";
110pub const LCD_LATENCY_JSON: &str = "lcd-latency.json";
111pub const LCD_LATENCY_MAX_AGE_MS: u64 = 10000;
112pub const LCD_FB_STATS_JSON: &str = "lcd-fb-stats.json";
113pub const LCD_FB_STATS_MAX_AGE_MS: u64 = 10000;
114pub const LCD_STATE_JSON: &str = "lcd-state.json";
115pub const LCD_PAGE_REQUEST_JSON: &str = "lcd-page-request.json";
116pub const LCD_PLUGIN_PAGE_JSON: &str = "lcd-plugin-page.json";
117pub const LCD_PLUGIN_TAP_JSON: &str = "lcd-plugin-tap.json";
118pub const CLOCK_JSON: &str = "clock.json";
119pub const CLOCK_MAX_AGE_MS: u64 = 5000;
120pub const SENSORS_JSON: &str = "sensors.json";
121pub const SENSORS_MAX_AGE_MS: u64 = 5000;
122pub const SENSORHUB_JSON: &str = "sensorhub.json";
123pub const SENSORHUB_MAX_AGE_MS: u64 = 5000;
124pub const GNSS_JSON: &str = "gnss.json";
125pub const GNSS_MAX_AGE_MS: u64 = 5000;
126pub const CAPTURE_STORAGE_JSON: &str = "capture-storage.json";
127pub const CAPTURE_STORAGE_MAX_AGE_MS: u64 = 30000;
128
129pub const API_INTERNAL_SOCK: &str = "api-internal.sock";
131pub const AUX_CMD_SOCK: &str = "aux-cmd.sock";
132pub const AUX_RPC_RESPONSES_SOCK: &str = "aux-rpc-responses.sock";
133pub const BUTTONS_SOCK: &str = "buttons.sock";
134pub const CLOUD_PUBLISH_SOCK: &str = "cloud-publish.sock";
135pub const CRSF_CMD_SOCK: &str = "crsf-cmd.sock";
136pub const GPIO_CMD_SOCK: &str = "gpio-cmd.sock";
137pub const GROUNDLINK_CMD_SOCK: &str = "groundlink-cmd.sock";
138pub const HID_CMD_SOCK: &str = "hid-cmd.sock";
139pub const LOGD_SOCK: &str = "logd.sock";
140pub const LOGD_QUERY_SOCK: &str = "logd-query.sock";
141pub const MAVLINK_SOCK: &str = "mavlink.sock";
142pub const MAVLINK_INGEST_SOCK: &str = "mavlink-ingest.sock";
143pub const MSP_SOCK: &str = "msp.sock";
144pub const GNSS_CMD_SOCK: &str = "gnss-cmd.sock";
145pub const PAIRING_SOCK: &str = "pairing.sock";
146pub const PIC_SOCK: &str = "pic.sock";
147pub const RADIO_AUX_SOCK: &str = "radio-aux.sock";
148pub const RADIO_CMD_SOCK: &str = "radio-cmd.sock";
149pub const STATE_SOCK: &str = "state.sock";
150pub const SUPERVISOR_SOCK: &str = "supervisor.sock";
151pub const SWARM_SOCK: &str = "swarm.sock";
152pub const TUNNEL_CONFIG_CMD_SOCK: &str = "tunnel-config-cmd.sock";
153pub const VIDEO_CMD_SOCK: &str = "video-cmd.sock";
154pub const VIDEO_ENCODER_SOCK: &str = "video-encoder.sock";
155pub const SENSOR_BUS_SOCK: &str = "sensors.sock";
156pub const VISION_SOCK: &str = "vision.sock";
157pub const WFB_CMD_SOCK: &str = "wfb-cmd.sock";
158pub const WIFI_CMD_SOCK: &str = "wifi-cmd.sock";
159
160#[rustfmt::skip]
162pub const SIDECARS: &[SidecarPath] = &[
163 SidecarPath { id: "cloud-link", path: "/run/ados/cloud-link.json", max_age_ms: None, writer: "ados-cloud" },
164 SidecarPath { id: "offload-link", path: "/run/ados/offload-link.json", max_age_ms: None, writer: "ados-plugin-host" },
165 SidecarPath { id: "wfb-stats", path: "/run/ados/wfb-stats.json", max_age_ms: Some(10000), writer: "ados-radio, ados-groundlink" },
166 SidecarPath { id: "hop-supervisor", path: "/run/ados/hop-supervisor.json", max_age_ms: Some(10000), writer: "ados-radio" },
167 SidecarPath { id: "peer-presence", path: "/run/ados/peer-presence.json", max_age_ms: Some(10000), writer: "ados-radio" },
168 SidecarPath { id: "mgmt-link", path: "/run/ados/mgmt-link.json", max_age_ms: Some(90000), writer: "ados-supervisor" },
169 SidecarPath { id: "mgmt-failover", path: "/run/ados/mgmt-failover.json", max_age_ms: Some(90000), writer: "ados-supervisor" },
170 SidecarPath { id: "usb-rehome", path: "/run/ados/usb-rehome.json", max_age_ms: Some(600000), writer: "ados-supervisor" },
171 SidecarPath { id: "wifi-powersave", path: "/run/ados/wifi-powersave.json", max_age_ms: Some(120000), writer: "ados-supervisor" },
172 SidecarPath { id: "wfb_failover", path: "/run/ados/wfb_failover.json", max_age_ms: Some(10000), writer: "ados-supervisor" },
173 SidecarPath { id: "wfb-pair-proof", path: "/var/lib/ados/wfb-pair-proof.json", max_age_ms: None, writer: "ados-radio, ados-groundlink" },
174 SidecarPath { id: "bind-state", path: "/run/ados/bind-state.json", max_age_ms: None, writer: "ados-radio" },
175 SidecarPath { id: "crsf-stats", path: "/run/ados/crsf-stats.json", max_age_ms: Some(10000), writer: "ados-crsf" },
176 SidecarPath { id: "lora", path: "/run/ados/lora.json", max_age_ms: Some(10000), writer: "ados-lora" },
177 SidecarPath { id: "lora-beacons", path: "/run/ados/lora-beacons.json", max_age_ms: Some(10000), writer: "ados-lora" },
178 SidecarPath { id: "tunnel-config", path: "/run/ados/tunnel-config.json", max_age_ms: Some(30000), writer: "ados-config-tunnel" },
179 SidecarPath { id: "relayed-status", path: "/run/ados/relayed-status.json", max_age_ms: Some(20000), writer: "ados-groundlink" },
180 SidecarPath { id: "linked-peers", path: "/run/ados/linked-peers.json", max_age_ms: None, writer: "ados-groundlink" },
181 SidecarPath { id: "mesh-state", path: "/run/ados/mesh-state.json", max_age_ms: Some(10000), writer: "ados-groundlink" },
182 SidecarPath { id: "wfb-relay", path: "/run/ados/wfb-relay.json", max_age_ms: Some(10000), writer: "ados-groundlink" },
183 SidecarPath { id: "wfb-receiver", path: "/run/ados/wfb-receiver.json", max_age_ms: Some(10000), writer: "ados-groundlink" },
184 SidecarPath { id: "fleet-hero", path: "/run/ados/fleet-hero.json", max_age_ms: None, writer: "ados-control" },
185 SidecarPath { id: "camera-state", path: "/run/ados/camera-state.json", max_age_ms: Some(300000), writer: "ados-video" },
186 SidecarPath { id: "cameras-discovered", path: "/run/ados/cameras-discovered.json", max_age_ms: None, writer: "ados.hal.camera" },
187 SidecarPath { id: "video-streams", path: "/run/ados/video-streams.json", max_age_ms: Some(20000), writer: "ados-video" },
188 SidecarPath { id: "video-profile", path: "/run/ados/video-profile.json", max_age_ms: None, writer: "ados-video" },
189 SidecarPath { id: "camera-usb-recovery", path: "/run/ados/camera-usb-recovery.json", max_age_ms: Some(60000), writer: "ados-supervisor" },
190 SidecarPath { id: "janitor", path: "/run/ados/janitor.json", max_age_ms: None, writer: "ados-supervisor" },
191 SidecarPath { id: "pic-state", path: "/run/ados/pic-state.json", max_age_ms: None, writer: "ados-hid" },
192 SidecarPath { id: "ground-station-input", path: "/etc/ados/ground-station-input.json", max_age_ms: None, writer: "ados-hid" },
193 SidecarPath { id: "gpio-output", path: "/run/ados/gpio-output.json", max_age_ms: None, writer: "ados-gpio" },
194 SidecarPath { id: "board", path: "/run/ados/board.json", max_age_ms: None, writer: "ados-hal-probe" },
195 SidecarPath { id: "config-status", path: "/run/ados/config-status-<service>.json", max_age_ms: None, writer: "ados-config" },
196 SidecarPath { id: "fc-identity", path: "/run/ados/fc-identity.json", max_age_ms: None, writer: "ados-control" },
197 SidecarPath { id: "mavlink-router", path: "/run/ados/mavlink-router.json", max_age_ms: Some(15000), writer: "ados-mavlink-router" },
198 SidecarPath { id: "link-feedback", path: "/run/ados/link-feedback.json", max_age_ms: None, writer: "ados-mavlink-router" },
199 SidecarPath { id: "plugin-loopback-guard", path: "/run/ados/plugin-loopback-guard.json", max_age_ms: None, writer: "ados-plugin-host" },
200 SidecarPath { id: "plugin-state", path: "/run/ados/plugins/<plugin_id>-state.json", max_age_ms: Some(10000), writer: "ados-plugin-host" },
201 SidecarPath { id: "ap-guard", path: "/run/ados/ap-guard.json", max_age_ms: None, writer: "ados-net" },
202 SidecarPath { id: "logd-push-request", path: "/run/ados/logd-push-request.json", max_age_ms: None, writer: "ados-control" },
203 SidecarPath { id: "logd-push-result", path: "/run/ados/logd-push-result.json", max_age_ms: None, writer: "ados-cloud" },
204 SidecarPath { id: "lcd-latency", path: "/run/ados/lcd-latency.json", max_age_ms: Some(10000), writer: "ados-video" },
205 SidecarPath { id: "lcd-fb-stats", path: "/run/ados/lcd-fb-stats.json", max_age_ms: Some(10000), writer: "ados-display" },
206 SidecarPath { id: "lcd-state", path: "/run/ados/lcd-state.json", max_age_ms: None, writer: "ados-display" },
207 SidecarPath { id: "lcd-page-request", path: "/run/ados/lcd-page-request.json", max_age_ms: None, writer: "ados-api" },
208 SidecarPath { id: "lcd-plugin-page", path: "/run/ados/lcd-plugin-page.json", max_age_ms: None, writer: "ados-plugin-host" },
209 SidecarPath { id: "lcd-plugin-tap", path: "/run/ados/lcd-plugin-tap.json", max_age_ms: None, writer: "ados-display" },
210 SidecarPath { id: "clock", path: "/run/ados/sensing/clock.json", max_age_ms: Some(5000), writer: "ados-clock" },
211 SidecarPath { id: "sensors", path: "/run/ados/sensors.json", max_age_ms: Some(5000), writer: "ados-clock" },
212 SidecarPath { id: "sensorhub", path: "/run/ados/sensorhub.json", max_age_ms: Some(5000), writer: "ados-sensorhub" },
213 SidecarPath { id: "gnss", path: "/run/ados/gnss.json", max_age_ms: Some(5000), writer: "ados-gnss" },
214 SidecarPath { id: "capture-storage", path: "/run/ados/capture-storage/capture-storage.json", max_age_ms: Some(30000), writer: "ados-supervisor" },
215];
216
217#[rustfmt::skip]
219pub const SOCKETS: &[SocketPath] = &[
220 SocketPath { id: "api-internal", path: "/run/ados/api-internal.sock", owner: "ados-api" },
221 SocketPath { id: "aux-cmd", path: "/run/ados/aux-cmd.sock", owner: "ados-radio" },
222 SocketPath { id: "aux-rpc-responses", path: "/run/ados/aux-rpc-responses.sock", owner: "ados-control" },
223 SocketPath { id: "buttons", path: "/run/ados/buttons.sock", owner: "ados-hid" },
224 SocketPath { id: "cloud-publish", path: "/run/ados/cloud-publish.sock", owner: "ados-cloud" },
225 SocketPath { id: "crsf-cmd", path: "/run/ados/crsf-cmd.sock", owner: "ados-crsf" },
226 SocketPath { id: "gpio-cmd", path: "/run/ados/gpio-cmd.sock", owner: "ados-gpio" },
227 SocketPath { id: "groundlink-cmd", path: "/run/ados/groundlink-cmd.sock", owner: "ados-groundlink" },
228 SocketPath { id: "hid-cmd", path: "/run/ados/hid-cmd.sock", owner: "ados-hid" },
229 SocketPath { id: "logd", path: "/run/ados/logd.sock", owner: "ados-logd" },
230 SocketPath { id: "logd-query", path: "/run/ados/logd-query.sock", owner: "ados-logd" },
231 SocketPath { id: "mavlink", path: "/run/ados/mavlink.sock", owner: "ados-mavlink-router" },
232 SocketPath { id: "mavlink-ingest", path: "/run/ados/mavlink-ingest.sock", owner: "ados-mavlink-router" },
233 SocketPath { id: "msp", path: "/run/ados/msp.sock", owner: "ados-mavlink-router" },
234 SocketPath { id: "gnss-cmd", path: "/run/ados/gnss-cmd.sock", owner: "ados-gnss" },
235 SocketPath { id: "pairing", path: "/run/ados/pairing.sock", owner: "ados-groundlink" },
236 SocketPath { id: "pic", path: "/run/ados/pic.sock", owner: "ados-hid" },
237 SocketPath { id: "radio-aux", path: "/run/ados/radio-aux.sock", owner: "ados-radio" },
238 SocketPath { id: "radio-cmd", path: "/run/ados/radio-cmd.sock", owner: "ados-radio" },
239 SocketPath { id: "state", path: "/run/ados/state.sock", owner: "ados-mavlink-router" },
240 SocketPath { id: "supervisor", path: "/run/ados/supervisor.sock", owner: "ados-supervisor" },
241 SocketPath { id: "swarm", path: "/run/ados/swarm.sock", owner: "ados-swarmbus" },
242 SocketPath { id: "tunnel-config-cmd", path: "/run/ados/tunnel-config-cmd.sock", owner: "ados-config-tunnel" },
243 SocketPath { id: "video-cmd", path: "/run/ados/video-cmd.sock", owner: "ados-supervisor" },
244 SocketPath { id: "video-encoder", path: "/run/ados/video-encoder.sock", owner: "ados-video" },
245 SocketPath { id: "sensor-bus", path: "/run/ados/sensing/sensors.sock", owner: "ados-clock" },
246 SocketPath { id: "vision", path: "/run/ados/vision.sock", owner: "ados-vision" },
247 SocketPath { id: "wfb-cmd", path: "/run/ados/wfb-cmd.sock", owner: "ados-radio" },
248 SocketPath { id: "wifi-cmd", path: "/run/ados/wifi-cmd.sock", owner: "ados-net" },
249];
250
251pub fn run_dir() -> PathBuf {
254 std::env::var_os(RUN_DIR_ENV)
255 .filter(|v| !v.is_empty())
256 .map(PathBuf::from)
257 .unwrap_or_else(|| PathBuf::from(RUN_DIR_DEFAULT))
258}
259
260pub fn sidecar(id: &str) -> Option<&'static SidecarPath> {
262 SIDECARS.iter().find(|s| s.id == id)
263}
264
265pub fn socket(id: &str) -> Option<&'static SocketPath> {
267 SOCKETS.iter().find(|s| s.id == id)
268}
269
270pub fn resolve(path: &str) -> PathBuf {
273 match path
274 .strip_prefix(RUN_DIR_DEFAULT)
275 .and_then(|r| r.strip_prefix('/'))
276 {
277 Some(rest) => run_dir().join(rest),
278 None => PathBuf::from(path),
279 }
280}
281
282pub fn run_path(id: &str) -> PathBuf {
287 match sidecar(id)
288 .map(|s| s.path)
289 .or_else(|| socket(id).map(|s| s.path))
290 {
291 Some(path) => resolve(path),
292 None => run_dir().join(id),
293 }
294}
295
296pub fn max_age(id: &str) -> Option<Duration> {
299 sidecar(id).and_then(SidecarPath::max_age)
300}