Retire --idunn-rudp-health and the daemon-health publisher
The flag family (--idunn-rudp-health, --idunn-daemon, --idunn-health-contract), IdunnRudpHealthOptions, the health worker thread, idunn_health_payload, the RUDP health connection and the idunn.daemon_health document had no consumer since the previous Idunn generation. The raven-muninn recipe never passed them; liveness is the runtime-presence publisher. Removes the IdunnDaemonHealthRecord odin-core symbol (three remain). The daemon id is now derived from the host alone. The transport profile and command-boundary records no longer carry health_publication, and health_contract is null. The starfire, nightwing and raven health and restart scripts stop passing and checking the flags; muninn.md follows. Tests: the retired flags are unknown arguments; the boundary record carries the host-derived daemon id and no health_publication. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bd69598503
commit
e9580009ea
8 changed files with 42 additions and 426 deletions
|
|
@ -21,12 +21,12 @@ use cultnet_rs::{
|
|||
GAMECULT_MEDIA_STREAM_REQUEST_SCHEMA, GAMECULT_RUNTIME_PRESENCE_HEALTH_SCHEMA,
|
||||
GameCultMediaStreamAdvertisementRecord, GameCultMediaStreamRequestRecord,
|
||||
GameCultRuntimePresenceHealthRecord, decode_cultnet_message_from_slice,
|
||||
encode_cultnet_message_to_vec, media_stream_request_key, validate_media_stream_request,
|
||||
media_stream_request_key, validate_media_stream_request,
|
||||
};
|
||||
#[cfg(feature = "psmoveapi-tracker")]
|
||||
use odin_core::MuninnMoveTrackerHealthRecord;
|
||||
use odin_core::{
|
||||
EveProviderAdvertisementRecord, EveSurfaceStateRecord, IdunnDaemonHealthRecord,
|
||||
EveProviderAdvertisementRecord, EveSurfaceStateRecord,
|
||||
MUNINN_MOVE_HUE_PROGRAM_SCHEMA, MUNINN_OBS_STREAM_CATALOG_SCHEMA,
|
||||
MuninnCaptureStreamCommandRecord, MuninnCaptureStreamRecord, MuninnCommandBoundaryCompatRecord,
|
||||
MuninnHidControllerStateRecord, MuninnMoveControllerStateRecord,
|
||||
|
|
@ -70,7 +70,6 @@ use std::os::windows::ffi::OsStrExt;
|
|||
use windows_sys::Win32::UI::Input::XboxController::{XINPUT_GAMEPAD, XINPUT_STATE, XInputGetState};
|
||||
|
||||
const CULTNET_RUDP_PROTOCOL_ID: &str = "cultnet.transport.rudp.v0";
|
||||
const IDUNN_HEALTH_RUDP_CONNECTION_ID: u32 = 0x1d0d_0001;
|
||||
const MUNINN_MEDIA_RUDP_CONNECTION_ID: u32 = 0x6d75_0001;
|
||||
const MUNINN_HID_CONTROLLER_RUDP_CONNECTION_ID: u32 = 0x6d75_0005;
|
||||
const MUNINN_COMMAND_RUDP_CONNECTION_ID: u32 = 0x61e0_0001;
|
||||
|
|
@ -214,7 +213,6 @@ struct Options {
|
|||
quest_input_stream_id: Option<String>,
|
||||
quest_pose_stream_id: Option<String>,
|
||||
quest_video_input_stream_id: Option<String>,
|
||||
idunn_rudp_health: Option<IdunnRudpHealthOptions>,
|
||||
odin_cultmesh_uri: Option<String>,
|
||||
hid_controller_rudp_target: Option<SocketAddr>,
|
||||
hid_controller_rudp_bind: Option<SocketAddr>,
|
||||
|
|
@ -275,13 +273,6 @@ struct MoveStateSource {
|
|||
hidraw_path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct IdunnRudpHealthOptions {
|
||||
endpoint: SocketAddr,
|
||||
daemon_id: String,
|
||||
health_contract: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
struct MuxPlan {
|
||||
command_line: String,
|
||||
|
|
@ -406,7 +397,6 @@ fn serve(options: Options) -> Result<()> {
|
|||
let move_runtime_enabled = serve_should_manage_move_runtime(&options);
|
||||
let mut active_move_states =
|
||||
active_move_state_sources(serve_move_state_sources(&options, move_runtime_enabled));
|
||||
start_daemon_health_worker(&options);
|
||||
start_idunn_presence_worker(&options);
|
||||
let mut active_move_marker_cameras =
|
||||
active_move_marker_camera_sources(&options, Arc::clone(&move_hue_program));
|
||||
|
|
@ -613,21 +603,6 @@ fn start_idunn_presence_worker(options: &Options) {
|
|||
});
|
||||
}
|
||||
|
||||
fn start_daemon_health_worker(options: &Options) {
|
||||
if options.idunn_rudp_health.is_none() {
|
||||
return;
|
||||
}
|
||||
let options = options.clone();
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
if let Err(error) = run_daemon_health_publisher(&options) {
|
||||
eprintln!("Muninn Idunn health publish failed: {error:#}");
|
||||
}
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn move_hue_program_key(host_id: &str) -> String {
|
||||
format!("muninn:{host_id}:move-hue-program")
|
||||
}
|
||||
|
|
@ -2846,16 +2821,8 @@ fn publish_runtime_boundary_records(
|
|||
.as_ref()
|
||||
.map(|command| json!([command]))
|
||||
.unwrap_or_else(|| json!([]));
|
||||
let current_transport = if options.idunn_rudp_health.is_some() {
|
||||
"daemon-published-rudp-health + daemon-owned-cultcache-telemetry-store"
|
||||
} else {
|
||||
"daemon-owned-cultcache-telemetry-store + missing-rudp-health-publication"
|
||||
};
|
||||
let transport_state = if options.idunn_rudp_health.is_some() {
|
||||
"rudp-health-and-provider-store-live"
|
||||
} else {
|
||||
"cultcache-provider-store-only"
|
||||
};
|
||||
let current_transport = "daemon-owned-cultcache-telemetry-store";
|
||||
let transport_state = "cultcache-provider-store-only";
|
||||
let hid_controller_endpoint = options.hid_controller_rudp_bind.map(|bind| {
|
||||
options
|
||||
.hid_controller_rudp_advertise
|
||||
|
|
@ -2994,18 +2961,6 @@ fn publish_runtime_boundary_records(
|
|||
"state_store": store_path,
|
||||
"log_root": log_root,
|
||||
"lifecycle_authority": "idunn-supervisor-command",
|
||||
"health_publication": options.idunn_rudp_health.as_ref().map(|idunn| json!({
|
||||
"contract": idunn.health_contract,
|
||||
"transport": CULTNET_RUDP_PROTOCOL_ID,
|
||||
"publication_source": "daemon-published",
|
||||
"endpoint": idunn.endpoint.to_string(),
|
||||
"state_owner": "Muninn serve process"
|
||||
})).unwrap_or_else(|| json!({
|
||||
"contract": serde_json::Value::Null,
|
||||
"transport": "unconfigured",
|
||||
"publication_source": "missing-daemon-publication",
|
||||
"state_owner": "Muninn local store"
|
||||
})),
|
||||
"commands": [
|
||||
{
|
||||
"command": "muninn.capture_stream_command",
|
||||
|
|
@ -3053,7 +3008,7 @@ fn publish_runtime_boundary_records(
|
|||
"target_transport": CULTNET_RUDP_PROTOCOL_ID,
|
||||
"current_transport": current_transport,
|
||||
"state": transport_state,
|
||||
"health_contract": options.idunn_rudp_health.as_ref().map(|idunn| idunn.health_contract.clone()),
|
||||
"health_contract": serde_json::Value::Null,
|
||||
"provider_advertisement_schema": "gamecult.eve.provider_advertisement.v1",
|
||||
"command_boundary_schema": "muninn.command_boundary.v1",
|
||||
"telemetry_surface_schema": "muninn.telemetry_surface.v1",
|
||||
|
|
@ -3191,9 +3146,6 @@ fn muninn_provider_id(options: &Options) -> String {
|
|||
}
|
||||
|
||||
fn muninn_daemon_id(options: &Options) -> String {
|
||||
if let Some(idunn) = options.idunn_rudp_health.as_ref() {
|
||||
return idunn.daemon_id.clone();
|
||||
}
|
||||
match options.host_id.as_str() {
|
||||
"raven" => "muninn".to_string(),
|
||||
"starfire" => "starfire-muninn".to_string(),
|
||||
|
|
@ -8604,18 +8556,6 @@ fn health_check(options: &Options) -> Result<()> {
|
|||
Ok(detail) => ("active", detail.clone()),
|
||||
Err(error) => ("failed", error.to_string()),
|
||||
};
|
||||
if let Some(idunn) = options.idunn_rudp_health.as_ref() {
|
||||
let publish_result = publish_idunn_rudp_health(idunn, state, &detail, &observed_at);
|
||||
if let Err(publish_error) = publish_result {
|
||||
return match result {
|
||||
Ok(_) => Err(publish_error).context("publishing Muninn health to Idunn RUDP"),
|
||||
Err(health_error) => Err(anyhow!(
|
||||
"{health_error}; also failed to publish Muninn health to Idunn RUDP: {publish_error}"
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
match result {
|
||||
Ok(detail) => {
|
||||
println!("{detail}");
|
||||
|
|
@ -8674,22 +8614,6 @@ fn evaluate_health_from_node(
|
|||
))
|
||||
}
|
||||
|
||||
fn publish_idunn_rudp_health(
|
||||
options: &IdunnRudpHealthOptions,
|
||||
state: &str,
|
||||
detail: &str,
|
||||
observed_at: &str,
|
||||
) -> Result<()> {
|
||||
let mut transport = connect_idunn_rudp_health(options)?;
|
||||
transport
|
||||
.send(
|
||||
"schema",
|
||||
idunn_health_payload(options, state, detail, observed_at)?,
|
||||
)
|
||||
.with_context(|| format!("sending Idunn health to {}", options.endpoint))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn smootherstep(value: f64) -> f64 {
|
||||
let t = value.clamp(0.0, 1.0);
|
||||
t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
|
||||
|
|
@ -8700,104 +8624,6 @@ fn wrapped_hue_lerp(source: f64, target: f64, amount: f64) -> f64 {
|
|||
(source + delta * amount).rem_euclid(1.0)
|
||||
}
|
||||
|
||||
fn run_daemon_health_publisher(options: &Options) -> Result<()> {
|
||||
let idunn = options
|
||||
.idunn_rudp_health
|
||||
.as_ref()
|
||||
.context("Muninn daemon health publisher requires Idunn RUDP options")?;
|
||||
let mut transport = connect_idunn_rudp_health(idunn)?;
|
||||
let cadence = Duration::from_secs(options.interval_seconds.unwrap_or(15).max(1));
|
||||
let mut next_publish_at = Instant::now();
|
||||
loop {
|
||||
if Instant::now() >= next_publish_at {
|
||||
let observed_at = idunn_timestamp()?;
|
||||
let (state, detail) = match evaluate_health(options) {
|
||||
Ok(detail) => ("active", detail),
|
||||
Err(error) => ("failed", error.to_string()),
|
||||
};
|
||||
transport
|
||||
.send(
|
||||
"schema",
|
||||
idunn_health_payload(idunn, state, &detail, &observed_at)?,
|
||||
)
|
||||
.with_context(|| format!("sending Idunn health to {}", idunn.endpoint))?;
|
||||
next_publish_at = Instant::now() + cadence;
|
||||
}
|
||||
let _ = transport.receive_once()?;
|
||||
transport.poll_resends()?;
|
||||
}
|
||||
}
|
||||
|
||||
fn idunn_health_payload(
|
||||
options: &IdunnRudpHealthOptions,
|
||||
state: &str,
|
||||
detail: &str,
|
||||
observed_at: &str,
|
||||
) -> Result<Vec<u8>> {
|
||||
let health = IdunnDaemonHealthRecord {
|
||||
daemon_id: options.daemon_id.clone(),
|
||||
state: state.to_string(),
|
||||
detail: detail.to_string(),
|
||||
observed_at: observed_at.to_string(),
|
||||
health_contract: options.health_contract.clone(),
|
||||
publication_source: "daemon-published".to_string(),
|
||||
transport: CULTNET_RUDP_PROTOCOL_ID.to_string(),
|
||||
};
|
||||
let message = CultNetMessage::DocumentPutRaw {
|
||||
message_id: format!(
|
||||
"muninn-health:{}:{}",
|
||||
options.daemon_id,
|
||||
observed_at.replace(':', "-")
|
||||
),
|
||||
document: CultNetRawDocumentRecord {
|
||||
schema_id: "idunn.daemon_health".to_string(),
|
||||
record_key: options.daemon_id.clone(),
|
||||
stored_at: observed_at.to_string(),
|
||||
payload_encoding: CultNetRawPayloadEncoding::Messagepack,
|
||||
payload: rmp_serde::to_vec(&health).context("encoding Idunn daemon health")?,
|
||||
source_runtime_id: Some("muninn-daemon".to_string()),
|
||||
source_agent_id: None,
|
||||
source_role: Some("daemon-health-publisher".to_string()),
|
||||
tags: Some(vec![CULTNET_RUDP_PROTOCOL_ID.to_string()]),
|
||||
},
|
||||
};
|
||||
encode_cultnet_message_to_vec(&message, CultNetWireContract::CultNetSchemaV0)
|
||||
.context("encoding Idunn health CultNet message")
|
||||
}
|
||||
|
||||
fn connect_idunn_rudp_health(
|
||||
options: &IdunnRudpHealthOptions,
|
||||
) -> Result<CultNetRudpSocketTransportConnection> {
|
||||
let bind_address = if options.endpoint.is_ipv4() {
|
||||
"0.0.0.0:0"
|
||||
} else {
|
||||
"[::]:0"
|
||||
};
|
||||
let socket = UdpSocket::bind(bind_address)
|
||||
.with_context(|| format!("binding Muninn RUDP sender at {bind_address}"))?;
|
||||
socket.set_read_timeout(Some(Duration::from_secs(1)))?;
|
||||
let mut transport =
|
||||
CultNetRudpSocketTransportConnection::new(CultNetRudpSocketTransportOptions::client(
|
||||
"muninn-daemon",
|
||||
socket,
|
||||
options.endpoint,
|
||||
IDUNN_HEALTH_RUDP_CONNECTION_ID,
|
||||
))?;
|
||||
transport.connect(Vec::new())?;
|
||||
let deadline = Instant::now() + Duration::from_secs(2);
|
||||
while !transport.connected() {
|
||||
let _ = transport.receive_once()?;
|
||||
transport.poll_resends()?;
|
||||
if Instant::now() >= deadline {
|
||||
return Err(anyhow!(
|
||||
"timed out connecting Muninn RUDP sender to {}",
|
||||
options.endpoint
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
fn verify_move_sources_fresh(options: &Options, node: &cultmesh_rs::CultMeshNode) -> Result<()> {
|
||||
let move_state_sources =
|
||||
serve_move_state_sources(options, serve_should_manage_move_runtime(options));
|
||||
|
|
@ -9837,7 +9663,6 @@ impl Options {
|
|||
quest_input_stream_id: None,
|
||||
quest_pose_stream_id: None,
|
||||
quest_video_input_stream_id: None,
|
||||
idunn_rudp_health: None,
|
||||
odin_cultmesh_uri: Some("cultmesh://odin/rendezvous/provider-catalog".to_string()),
|
||||
hid_controller_rudp_target: None,
|
||||
hid_controller_rudp_bind: None,
|
||||
|
|
@ -9848,9 +9673,6 @@ impl Options {
|
|||
};
|
||||
|
||||
let mut args = args.peekable();
|
||||
let mut idunn_rudp_health_endpoint = None;
|
||||
let mut idunn_daemon_id = None;
|
||||
let mut idunn_health_contract = None;
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"serve" => options.mode = Mode::Serve,
|
||||
|
|
@ -10087,19 +9909,6 @@ impl Options {
|
|||
options.quest_video_input_stream_id =
|
||||
Some(take_value(&mut args, "--quest-video-input-stream")?)
|
||||
}
|
||||
"--idunn-rudp-health" => {
|
||||
idunn_rudp_health_endpoint = Some(
|
||||
take_value(&mut args, "--idunn-rudp-health")?
|
||||
.parse()
|
||||
.context("--idunn-rudp-health must be a socket address")?,
|
||||
)
|
||||
}
|
||||
"--idunn-daemon" => {
|
||||
idunn_daemon_id = Some(take_value(&mut args, "--idunn-daemon")?)
|
||||
}
|
||||
"--idunn-health-contract" => {
|
||||
idunn_health_contract = Some(take_value(&mut args, "--idunn-health-contract")?)
|
||||
}
|
||||
"--odin-cultmesh-rudp" => {
|
||||
let _ = take_value(&mut args, "--odin-cultmesh-rudp")?;
|
||||
return Err(anyhow!(
|
||||
|
|
@ -10287,32 +10096,11 @@ impl Options {
|
|||
options.quest_video_input_stream_id.as_ref(),
|
||||
),
|
||||
("--move-host", options.move_host_address.as_ref()),
|
||||
("--idunn-daemon", idunn_daemon_id.as_ref()),
|
||||
("--idunn-health-contract", idunn_health_contract.as_ref()),
|
||||
] {
|
||||
if value.is_some_and(|value| value.trim().is_empty()) {
|
||||
return Err(anyhow!("{name} must be non-empty"));
|
||||
}
|
||||
}
|
||||
options.idunn_rudp_health = match (
|
||||
idunn_rudp_health_endpoint,
|
||||
idunn_daemon_id,
|
||||
idunn_health_contract,
|
||||
) {
|
||||
(None, None, None) => None,
|
||||
(Some(endpoint), Some(daemon_id), Some(health_contract)) => {
|
||||
Some(IdunnRudpHealthOptions {
|
||||
endpoint,
|
||||
daemon_id,
|
||||
health_contract,
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
"--idunn-rudp-health, --idunn-daemon, and --idunn-health-contract must be provided together"
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
|
@ -10330,14 +10118,6 @@ fn timestamp() -> Result<String> {
|
|||
Ok(format!("unix-{seconds}"))
|
||||
}
|
||||
|
||||
fn idunn_timestamp() -> Result<String> {
|
||||
let seconds = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.context("system clock is before Unix epoch")?
|
||||
.as_secs();
|
||||
Ok(format!("unix:{seconds}"))
|
||||
}
|
||||
|
||||
fn timestamp_ns() -> Result<i64> {
|
||||
let nanos = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
|
@ -10406,7 +10186,7 @@ fn parse_move_marker_camera_source(value: &str) -> Result<MoveMarkerCameraSource
|
|||
}
|
||||
|
||||
fn help_text() -> &'static str {
|
||||
"Usage: muninn [serve|activate|request-stream|capture-stream-status|obs-catalog-status|request-move-light|move-light-status|move-identity-status|move-source-status|move-state-status|claim-move-host|quest-access-status] [--store <path>] [--activate-store <path>] [--stream-action <start|stop>] [--target-host <cultmesh-uri>] [--media-transport <rudp>] [--media-rudp-bind <addr>] [--media-rudp-advertise <host:port>] [--media-packet-bytes <bytes>] [--rudp-video-bitrate-kbps <kbps>] [--rudp-latency-budget-ms <ms>] [--video-source <source-id=label>] [--audio-source <source-id=label>] [--audio-source-id <source-id>] [--no-video] [--no-audio] [--loopback-script <path>] [--ffmpeg <path>] [--odin-cultmesh-uri <cultmesh-uri>] [--move-state <move-id>=<hidraw-path>] [--move-marker-camera <camera-id>=<device-path>] [--move-psmoveapi-tracker] [--move-tracker-exposure-milli <0..1000>] [--move-marker-width <px>] [--move-marker-height <px>] [--move-marker-fps <fps>] [--move-host <bt-addr>] [--move-evidence-stream <stream-id>] [--move-evidence-verse <verse-id>] [--move-evidence-ring-slots <slots>] [--move-evidence-slot-bytes <bytes>] [--move-evidence-snapshot <path>] [--quest-adb] [--quest-serial <serial>] [--quest-input-stream <stream-id>] [--quest-pose-stream <stream-id>] [--quest-video-input-stream <stream-id>] [--idunn-rudp-health <addr>] [--idunn-daemon <id>] [--idunn-health-contract <contract>] [--dry-run] [--health]\n\nMuninn is Odin's portable telemetry Verse assembler. serve publishes cheap typed telemetry affordances, optional Quest USB access surfaces, and the explicitly configured Move runtime; when serve receives --move-state, --move-marker-camera, --move-host, or --move-evidence-stream it may publish source-local Move controller state, source-local optical marker candidates, typed Move identity records, a CultMesh Move evidence stream, optionally write a latest one-copy Move proof evidence snapshot for Mimir field capture/replay, and keep USB-attached PS Moves claimed to that explicit Bluetooth host; --move-psmoveapi-tracker delegates camera exposure and optical extraction to the reference PSMoveAPI backend while Muninn retains stable-ID light actuation; serve consumes typed capture stream commands from its provider-owned activation store and owns the local ffmpeg/loopback activation child lifecycle, listens for media receivers on --media-rudp-bind and advertises that endpoint (--media-rudp-advertise when the bind address is not reachable as-is), and publishes its discovery advertisement through --odin-cultmesh-uri; activate starts an explicitly requested local CultNet RUDP stream as a daemon child that serves every receiver dialling --media-rudp-bind; request-stream discovers the provider through Odin and sends its typed command to that provider; obs-catalog-status pulls Odin-owned muninn.obs_stream_catalog discovery into the local compatibility store for OBS; capture-stream-status reads typed capture stream command receipts; use --no-video or --no-audio to request one leg over the CultNet RUDP media lane; request-move-light publishes a typed Move light command for Muninn serve to execute; move-light-status reads typed command receipts; move-identity-status reads typed Move identity records; move-source-status prints live Move source discovery; move-state-status reads typed controller-state records; claim-move-host assigns USB-attached PS Moves to a Bluetooth host; quest-access-status reads typed Quest access state. In --health mode, the Idunn RUDP flags publish the same typed daemon health document to Idunn for explicit diagnostics."
|
||||
"Usage: muninn [serve|activate|request-stream|capture-stream-status|obs-catalog-status|request-move-light|move-light-status|move-identity-status|move-source-status|move-state-status|claim-move-host|quest-access-status] [--store <path>] [--activate-store <path>] [--stream-action <start|stop>] [--target-host <cultmesh-uri>] [--media-transport <rudp>] [--media-rudp-bind <addr>] [--media-rudp-advertise <host:port>] [--media-packet-bytes <bytes>] [--rudp-video-bitrate-kbps <kbps>] [--rudp-latency-budget-ms <ms>] [--video-source <source-id=label>] [--audio-source <source-id=label>] [--audio-source-id <source-id>] [--no-video] [--no-audio] [--loopback-script <path>] [--ffmpeg <path>] [--odin-cultmesh-uri <cultmesh-uri>] [--move-state <move-id>=<hidraw-path>] [--move-marker-camera <camera-id>=<device-path>] [--move-psmoveapi-tracker] [--move-tracker-exposure-milli <0..1000>] [--move-marker-width <px>] [--move-marker-height <px>] [--move-marker-fps <fps>] [--move-host <bt-addr>] [--move-evidence-stream <stream-id>] [--move-evidence-verse <verse-id>] [--move-evidence-ring-slots <slots>] [--move-evidence-slot-bytes <bytes>] [--move-evidence-snapshot <path>] [--quest-adb] [--quest-serial <serial>] [--quest-input-stream <stream-id>] [--quest-pose-stream <stream-id>] [--quest-video-input-stream <stream-id>] [--dry-run] [--health]\n\nMuninn is Odin's portable telemetry Verse assembler. serve publishes cheap typed telemetry affordances, optional Quest USB access surfaces, and the explicitly configured Move runtime; when serve receives --move-state, --move-marker-camera, --move-host, or --move-evidence-stream it may publish source-local Move controller state, source-local optical marker candidates, typed Move identity records, a CultMesh Move evidence stream, optionally write a latest one-copy Move proof evidence snapshot for Mimir field capture/replay, and keep USB-attached PS Moves claimed to that explicit Bluetooth host; --move-psmoveapi-tracker delegates camera exposure and optical extraction to the reference PSMoveAPI backend while Muninn retains stable-ID light actuation; serve consumes typed capture stream commands from its provider-owned activation store and owns the local ffmpeg/loopback activation child lifecycle, listens for media receivers on --media-rudp-bind and advertises that endpoint (--media-rudp-advertise when the bind address is not reachable as-is), and publishes its discovery advertisement through --odin-cultmesh-uri; activate starts an explicitly requested local CultNet RUDP stream as a daemon child that serves every receiver dialling --media-rudp-bind; request-stream discovers the provider through Odin and sends its typed command to that provider; obs-catalog-status pulls Odin-owned muninn.obs_stream_catalog discovery into the local compatibility store for OBS; capture-stream-status reads typed capture stream command receipts; use --no-video or --no-audio to request one leg over the CultNet RUDP media lane; request-move-light publishes a typed Move light command for Muninn serve to execute; move-light-status reads typed command receipts; move-identity-status reads typed Move identity records; move-source-status prints live Move source discovery; move-state-status reads typed controller-state records; claim-move-host assigns USB-attached PS Moves to a Bluetooth host; quest-access-status reads typed Quest access state. In --health mode, the Idunn RUDP flags publish the same typed daemon health document to Idunn for explicit diagnostics."
|
||||
}
|
||||
|
||||
fn parse_move_state_source(value: &str) -> Result<MoveStateSource> {
|
||||
|
|
@ -10430,6 +10210,7 @@ fn parse_move_state_source(value: &str) -> Result<MoveStateSource> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::media_send::{MediaKind, QueuedMediaGroup};
|
||||
use cultnet_rs::encode_cultnet_message_to_vec;
|
||||
|
||||
fn media_stream_request() -> GameCultMediaStreamRequestRecord {
|
||||
GameCultMediaStreamRequestRecord {
|
||||
|
|
@ -10875,39 +10656,20 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn health_idunn_rudp_options_are_explicit_bundle() {
|
||||
let options = Options::parse(
|
||||
[
|
||||
"--health",
|
||||
"--idunn-rudp-health",
|
||||
"127.0.0.1:17870",
|
||||
"--idunn-daemon",
|
||||
"starfire-muninn",
|
||||
"--idunn-health-contract",
|
||||
"muninn.cultnet-rudp-local-telemetry-and-quest-access",
|
||||
]
|
||||
.into_iter()
|
||||
.map(String::from),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let idunn = options.idunn_rudp_health.unwrap();
|
||||
assert_eq!(options.mode, Mode::Health);
|
||||
assert_eq!(idunn.endpoint, "127.0.0.1:17870".parse().unwrap());
|
||||
assert_eq!(idunn.daemon_id, "starfire-muninn");
|
||||
assert_eq!(
|
||||
idunn.health_contract,
|
||||
"muninn.cultnet-rudp-local-telemetry-and-quest-access"
|
||||
);
|
||||
|
||||
let error = Options::parse(
|
||||
["--health", "--idunn-rudp-health", "127.0.0.1:17870"]
|
||||
.into_iter()
|
||||
.map(String::from),
|
||||
)
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
assert!(error.contains("must be provided together"));
|
||||
fn retired_idunn_rudp_health_flags_are_unknown_arguments() {
|
||||
for flag in [
|
||||
"--idunn-rudp-health",
|
||||
"--idunn-daemon",
|
||||
"--idunn-health-contract",
|
||||
] {
|
||||
let error = Options::parse(["--health", flag, "127.0.0.1:17870"].into_iter().map(String::from))
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
assert!(
|
||||
error.contains(&format!("unknown Muninn argument: {flag}")),
|
||||
"{flag} must be rejected, got: {error}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -10995,67 +10757,6 @@ mod tests {
|
|||
assert!(error.contains("request-stream requires --odin-cultmesh-uri"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idunn_rudp_health_publisher_sends_raw_daemon_health_document() {
|
||||
let receiver = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||
receiver
|
||||
.set_read_timeout(Some(Duration::from_secs(1)))
|
||||
.unwrap();
|
||||
let receiver_addr = receiver.local_addr().unwrap();
|
||||
let handle = thread::spawn(move || {
|
||||
let mut transport = CultNetRudpSocketTransportConnection::new(
|
||||
CultNetRudpSocketTransportOptions::server(
|
||||
"idunn-test",
|
||||
receiver,
|
||||
IDUNN_HEALTH_RUDP_CONNECTION_ID,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let deadline = Instant::now() + Duration::from_secs(2);
|
||||
loop {
|
||||
if let Some(frame) = transport.receive_once().unwrap() {
|
||||
return cultnet_rs::decode_cultnet_message_from_slice(
|
||||
&frame.payload,
|
||||
CultNetWireContract::CultNetSchemaV0,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
transport.poll_resends().unwrap();
|
||||
if Instant::now() >= deadline {
|
||||
panic!("timed out waiting for Muninn RUDP health frame");
|
||||
}
|
||||
}
|
||||
});
|
||||
let options = IdunnRudpHealthOptions {
|
||||
endpoint: receiver_addr,
|
||||
daemon_id: "starfire-muninn".to_string(),
|
||||
health_contract: "muninn.cultnet-rudp-local-telemetry-and-quest-access".to_string(),
|
||||
};
|
||||
|
||||
publish_idunn_rudp_health(&options, "active", "Muninn healthy", "unix:100").unwrap();
|
||||
|
||||
let message = handle.join().unwrap();
|
||||
let CultNetMessage::DocumentPutRaw { document, .. } = message else {
|
||||
panic!("expected raw document put");
|
||||
};
|
||||
assert_eq!(document.schema_id, "idunn.daemon_health");
|
||||
assert_eq!(document.record_key, "starfire-muninn");
|
||||
assert_eq!(
|
||||
document.payload_encoding,
|
||||
CultNetRawPayloadEncoding::Messagepack
|
||||
);
|
||||
let health: IdunnDaemonHealthRecord = rmp_serde::from_slice(&document.payload).unwrap();
|
||||
assert_eq!(health.daemon_id, "starfire-muninn");
|
||||
assert_eq!(health.state, "active");
|
||||
assert_eq!(
|
||||
health.health_contract,
|
||||
"muninn.cultnet-rudp-local-telemetry-and-quest-access"
|
||||
);
|
||||
assert_eq!(health.publication_source, "daemon-published");
|
||||
assert_eq!(health.transport, CULTNET_RUDP_PROTOCOL_ID);
|
||||
assert_eq!(health.observed_at, "unix:100");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_capture_stream_start_is_equivalent_when_media_shape_matches() {
|
||||
let options = Options::parse(
|
||||
|
|
@ -12985,12 +12686,6 @@ Device 00:07:04:A8:00:D0 (public)
|
|||
"C:/Meta/Odin/state/muninn.activate.cc",
|
||||
"--target-host",
|
||||
"cultmesh://odin/media/muninn-raven-av",
|
||||
"--idunn-rudp-health",
|
||||
"198.51.100.10:17870",
|
||||
"--idunn-daemon",
|
||||
"muninn",
|
||||
"--idunn-health-contract",
|
||||
"muninn.cultnet-rudp-remote-telemetry-health",
|
||||
]
|
||||
.into_iter()
|
||||
.map(String::from),
|
||||
|
|
@ -13023,6 +12718,13 @@ Device 00:07:04:A8:00:D0 (public)
|
|||
assert!(invocation.contains("request-stream"));
|
||||
assert!(invocation.contains("--target-host cultmesh://odin/media/muninn-raven-av"));
|
||||
|
||||
assert_eq!(
|
||||
boundary.value.get("daemon_id").and_then(|value| value.as_str()),
|
||||
Some("muninn")
|
||||
);
|
||||
assert!(boundary.value.get("health_publication").is_none());
|
||||
assert!(transport.value.get("health_contract").is_some_and(|value| value.is_null()));
|
||||
|
||||
let command_lowerings = transport
|
||||
.value
|
||||
.get("command_lowerings")
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ microphones, cameras, and future sensors.
|
|||
|
||||
```powershell
|
||||
cargo build -p muninn-daemon
|
||||
muninn serve --store C:\Meta\Odin\state\muninn.telemetry.cc --interval-seconds 15 --idunn-rudp-health $env:IDUNN_RUDP_HEALTH --idunn-daemon starfire-muninn --idunn-health-contract muninn.cultnet-rudp-local-telemetry-and-quest-access
|
||||
muninn serve --store C:\Meta\Odin\state\muninn.telemetry.cc --interval-seconds 15
|
||||
muninn --health --store C:\Meta\Odin\state\muninn.telemetry.cc
|
||||
```
|
||||
|
||||
|
|
@ -97,10 +97,7 @@ E:\Projects\Odin\scripts\restart-starfire-muninn.cmd
|
|||
E:\Projects\Odin\scripts\health-starfire-muninn.cmd
|
||||
```
|
||||
|
||||
The restart script launches Muninn hidden with `--host starfire --quest-adb`,
|
||||
`--idunn-rudp-health` from explicit `-IdunnRudpHealth` or
|
||||
`IDUNN_RUDP_HEALTH`, `--idunn-daemon starfire-muninn`, and
|
||||
`--idunn-health-contract muninn.cultnet-rudp-local-telemetry-and-quest-access`.
|
||||
The restart script launches Muninn hidden with `--host starfire --quest-adb`.
|
||||
If the CultCache store at `C:\Meta\Odin\state\starfire.muninn.telemetry.cc`
|
||||
fails MessagePack decode on boot, the restart path archives the corrupt file,
|
||||
clears the stale `.lock`, and relaunches the daemon instead of leaving the lane
|
||||
|
|
@ -192,11 +189,7 @@ muninn move-light-status \
|
|||
Idunn keeps the Muninn daemon alive. Idunn does not learn a Move-specific
|
||||
watcher, and Mimir does not write HID directly except through temporary smoke
|
||||
scripts used to prove hardware behavior before a Muninn daemon is available.
|
||||
When `serve` is launched with `--idunn-rudp-health`, `--idunn-daemon`, and
|
||||
`--idunn-health-contract`, the long-running Muninn body publishes
|
||||
`idunn.daemon_health` directly to Idunn over `cultnet.transport.rudp.v0` on its
|
||||
normal cadence. `--health` keeps the same publication path for manual proof and
|
||||
compatibility probes, but the live owner is the daemon's `serve` process.
|
||||
`--health` reads the telemetry store and reports; it publishes nothing.
|
||||
Quest ADB probing is a telemetry input, not daemon liveness. If `adb` is
|
||||
missing or the Quest is unavailable, Muninn publishes `muninn.quest_access` as
|
||||
`unavailable` and keeps serving the local telemetry surface.
|
||||
|
|
@ -235,10 +228,6 @@ actuators only, not lifecycle owners. The binary is installed at
|
|||
`/home/metacrat/.local/state/gamecult/muninn/muninn.telemetry.cc`, and the
|
||||
restart actuator launches `serve --host nightwing --interval-seconds 15` with
|
||||
`--move-state move-usb=/dev/input/by-id/usb-Sony_Computer_Entertainment_Motion_Controller-joystick`,
|
||||
`--idunn-rudp-health` supplied by explicit `-IdunnRudpHealth` or
|
||||
`IDUNN_RUDP_HEALTH`,
|
||||
`--idunn-daemon nightwing-muninn`,
|
||||
`--idunn-health-contract muninn.cultnet-rudp-remote-telemetry-and-move-hid`,
|
||||
PID, and logs under
|
||||
`/home/metacrat/.local/state/gamecult/muninn`.
|
||||
With that Move state source attached, `serve` also publishes the
|
||||
|
|
@ -248,10 +237,7 @@ Nightwing source discovery must emit one Move source per controller id. The USB
|
|||
pairing collection and Bluetooth joystick can expose the same controller as
|
||||
separate `/dev/input/js*` paths; `nightwing-move-state-sources.sh` prefers the
|
||||
Bluetooth `HID_ID=0005:0000054C:000003D5` path so Idunn health does not demand
|
||||
fresh records from two faces of the same controller. The Nightwing health
|
||||
actuator requires the same configured Idunn RUDP endpoint, but that command is
|
||||
fallback proof only; the live keepalive contract is now published by the
|
||||
long-running Nightwing `serve` process.
|
||||
fresh records from two faces of the same controller.
|
||||
|
||||
Each private PSMoveAPI Eye worker owns optical observation admission before the
|
||||
parent aggregates evidence. Positions older than 50 ms, blobs below 2 px,
|
||||
|
|
|
|||
|
|
@ -701,8 +701,7 @@ by continuity in under 10 s. The catalog on Odin named the new endpoint the
|
|||
first time the restarted `serve` advertised.
|
||||
|
||||
Still Raven-specific and unmanaged: the two activation scripts and
|
||||
`health-muninn.ps1`, which still passes the retired `--idunn-rudp-health`
|
||||
flags. That flag family (`IdunnRudpHealthOptions`, `run_daemon_health_publisher`,
|
||||
`idunn.daemon_health` documents) has no consumer since the previous Idunn
|
||||
generation was retired and is the next cut; nightwing and starfire's restart
|
||||
scripts still require it, so it goes with them.
|
||||
`health-muninn.ps1`. The retired `--idunn-rudp-health` flag family
|
||||
(`IdunnRudpHealthOptions`, `run_daemon_health_publisher`, `idunn.daemon_health`
|
||||
documents) had no consumer since the previous Idunn generation was retired; it
|
||||
was deleted from `muninn`, its five host scripts and `muninn.md` in named cut 3.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ param(
|
|||
[string] $ActivateStorePath = "C:\Meta\Odin\state\muninn.activate.cc",
|
||||
[string] $LogRoot = "C:\Meta\Odin\logs\muninn",
|
||||
[int] $MaxStoreAgeSeconds = 180,
|
||||
[string] $IdunnRudpHealth = $env:IDUNN_RUDP_HEALTH,
|
||||
[int] $ConnectTimeoutSeconds = 10,
|
||||
[string] $SshUser = "madman's lullaby",
|
||||
[string] $IdentityFile = ""
|
||||
|
|
@ -13,10 +12,6 @@ param(
|
|||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($IdunnRudpHealth)) {
|
||||
throw "Idunn RUDP health endpoint must be supplied by -IdunnRudpHealth or IDUNN_RUDP_HEALTH; no Starfire LAN default is allowed."
|
||||
}
|
||||
|
||||
function Set-AsciiFile {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)] [string] $Path,
|
||||
|
|
@ -177,10 +172,7 @@ if (`$null -eq `$process) {
|
|||
}
|
||||
foreach (`$pattern in @(
|
||||
"--host raven",
|
||||
"--activate-store $ActivateStorePath",
|
||||
"--idunn-rudp-health $IdunnRudpHealth",
|
||||
"--idunn-daemon muninn",
|
||||
"--idunn-health-contract muninn.cultnet-rudp-remote-telemetry-health"
|
||||
"--activate-store $ActivateStorePath"
|
||||
)) {
|
||||
if (`$process.CommandLine -notlike "*`$pattern*") {
|
||||
throw "Muninn serve process is missing expected command-line segment `${pattern}: `$(`$process.CommandLine)"
|
||||
|
|
|
|||
|
|
@ -5,16 +5,11 @@ param(
|
|||
[string] $PidPath = "/home/metacrat/.local/state/gamecult/muninn/muninn.pid",
|
||||
[string[]] $MoveState = @(),
|
||||
[int] $IntervalSeconds = 15,
|
||||
[int] $MaxStoreAgeSeconds = 180,
|
||||
[string] $IdunnRudpHealth = $env:IDUNN_RUDP_HEALTH
|
||||
[int] $MaxStoreAgeSeconds = 180
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($IdunnRudpHealth)) {
|
||||
throw "Idunn RUDP health endpoint must be supplied by -IdunnRudpHealth or IDUNN_RUDP_HEALTH; no WireGuard endpoint default is allowed."
|
||||
}
|
||||
|
||||
function Set-AsciiFile {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)] [string] $Path,
|
||||
|
|
@ -76,16 +71,6 @@ if [ -z "`$process_line" ]; then
|
|||
echo 'Nightwing Muninn serve command line is unavailable' >&2
|
||||
exit 1
|
||||
fi
|
||||
for pattern in \
|
||||
'--idunn-rudp-health $IdunnRudpHealth' \
|
||||
'--idunn-daemon nightwing-muninn' \
|
||||
'--idunn-health-contract muninn.cultnet-rudp-remote-telemetry-and-move-hid'
|
||||
do
|
||||
if ! printf '%s\n' "`$process_line" | grep -F -- "`$pattern" >/dev/null 2>&1; then
|
||||
echo "Nightwing Muninn serve command line is missing `$pattern" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [ ! -f '$StorePath' ]; then
|
||||
echo 'Muninn telemetry store is missing on Nightwing' >&2
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -3,16 +3,11 @@ param(
|
|||
[string] $StorePath = "C:\Meta\Odin\state\starfire.muninn.telemetry.cc",
|
||||
[string] $LogRoot = "C:\Meta\Odin\logs\starfire-muninn",
|
||||
[string[]] $MoveState = @(),
|
||||
[int] $MaxStoreAgeSeconds = 180,
|
||||
[string] $IdunnRudpHealth = $env:IDUNN_RUDP_HEALTH
|
||||
[int] $MaxStoreAgeSeconds = 180
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($IdunnRudpHealth)) {
|
||||
throw "Idunn RUDP health endpoint must be supplied by -IdunnRudpHealth or IDUNN_RUDP_HEALTH; no Starfire LAN default is allowed."
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $MuninnExe)) {
|
||||
throw "Muninn executable not found at $MuninnExe"
|
||||
}
|
||||
|
|
@ -28,15 +23,6 @@ $process = Get-CimInstance Win32_Process |
|
|||
if ($null -eq $process) {
|
||||
throw "Starfire Muninn serve process is not running with Quest access enabled"
|
||||
}
|
||||
foreach ($pattern in @(
|
||||
"--idunn-rudp-health $IdunnRudpHealth",
|
||||
"--idunn-daemon starfire-muninn",
|
||||
"--idunn-health-contract muninn.cultnet-rudp-local-telemetry-and-quest-access"
|
||||
)) {
|
||||
if ($process.CommandLine -notlike "*$pattern*") {
|
||||
throw "Starfire Muninn serve process is missing expected command-line segment ${pattern}: $($process.CommandLine)"
|
||||
}
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $StorePath)) {
|
||||
throw "Starfire Muninn telemetry store is missing at $StorePath"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ param(
|
|||
"nightwing-eye-1" = 100
|
||||
},
|
||||
[int] $IntervalSeconds = 15,
|
||||
[string] $IdunnRudpHealth = $env:IDUNN_RUDP_HEALTH,
|
||||
[string] $IdunnDaemon = "nightwing-muninn",
|
||||
[string] $IdunnHealthContract = "muninn.cultnet-rudp-remote-telemetry-and-move-hid",
|
||||
[string] $OdinCultMeshUri = $(if ($env:ODIN_CULTMESH_URI) { $env:ODIN_CULTMESH_URI } else { "cultmesh://odin/rendezvous/provider-catalog" }),
|
||||
[string] $OdinCultMeshRudpEndpoint = $(if ($env:CULTMESH_URI_ODIN_RUDP) { $env:CULTMESH_URI_ODIN_RUDP } else { "10.77.0.2:17871" }),
|
||||
[string] $HidControllerRudpBind = "0.0.0.0:17888",
|
||||
|
|
@ -34,12 +31,6 @@ if ($env:IDUNN_ACTUATOR -ne "1" -or $env:IDUNN_COMMAND_AUTHORITY -ne "idunn-daem
|
|||
throw "restart-nightwing-muninn.ps1 is an Idunn actuator body. Redeploy by poking Idunn; direct service restart is not an owned path."
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($IdunnRudpHealth)) {
|
||||
throw "Idunn RUDP health endpoint must be supplied by -IdunnRudpHealth or IDUNN_RUDP_HEALTH; no Starfire LAN default is allowed."
|
||||
}
|
||||
if ($IdunnRudpHealth -match '^(127\.0\.0\.1|localhost):(\d+)$') {
|
||||
$IdunnRudpHealth = "10.77.0.2:$($Matches[2])"
|
||||
}
|
||||
if (-not [string]::IsNullOrWhiteSpace($HidControllerRudpBind) -and [string]::IsNullOrWhiteSpace($HidControllerRudpAdvertise)) {
|
||||
throw "HID controller RUDP advertise endpoint must be supplied by -HidControllerRudpAdvertise or MUNINN_HID_CONTROLLER_RUDP_ADVERTISE when HID RUDP bind is enabled; no Nightwing LAN default is allowed."
|
||||
}
|
||||
|
|
@ -162,10 +153,7 @@ set -- serve \
|
|||
--host nightwing
|
||||
$moveRuntimeSetBlock
|
||||
set -- "`$@" \
|
||||
--interval-seconds '$IntervalSeconds' \
|
||||
--idunn-rudp-health '$IdunnRudpHealth' \
|
||||
--idunn-daemon '$IdunnDaemon' \
|
||||
--idunn-health-contract '$IdunnHealthContract'
|
||||
--interval-seconds '$IntervalSeconds'
|
||||
$odinCultMeshUriSetBlock
|
||||
$hidControllerRudpSetBlock
|
||||
$commandRudpSetBlock
|
||||
|
|
@ -179,10 +167,9 @@ muninn_pid="`$(cat '$LogRoot/muninn.pid')"
|
|||
kill -0 "`$muninn_pid" 2>/dev/null
|
||||
muninn_cmdline="`$(tr '\0' ' ' < "/proc/`$muninn_pid/cmdline")"
|
||||
if ! printf '%s\n' "`$muninn_cmdline" | grep -F -- '--host nightwing' >/dev/null 2>&1 ||
|
||||
! printf '%s\n' "`$muninn_cmdline" | grep -F -- '--idunn-rudp-health $IdunnRudpHealth' >/dev/null 2>&1 ||
|
||||
! printf '%s\n' "`$muninn_cmdline" | grep -F -- '--move-marker-camera nightwing-eye-0=/dev/video2' >/dev/null 2>&1 ||
|
||||
! printf '%s\n' "`$muninn_cmdline" | grep -F -- '--move-marker-camera nightwing-eye-1=/dev/video3' >/dev/null 2>&1; then
|
||||
echo 'Nightwing Muninn serve command line is missing Idunn health or dual-camera arguments' >&2
|
||||
echo 'Nightwing Muninn serve command line is missing dual-camera arguments' >&2
|
||||
exit 1
|
||||
fi
|
||||
"@
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ param(
|
|||
[string] $MoveBluetoothHost = "",
|
||||
[string[]] $MoveState = @(),
|
||||
[switch] $EnableUsbMoveState,
|
||||
[string] $IdunnRudpHealth = $env:IDUNN_RUDP_HEALTH,
|
||||
[string] $IdunnDaemon = "starfire-muninn",
|
||||
[string] $IdunnHealthContract = "muninn.cultnet-rudp-local-telemetry-and-quest-access",
|
||||
[string] $OdinCultMeshUri = $(if ($env:ODIN_CULTMESH_URI) { $env:ODIN_CULTMESH_URI } else { "cultmesh://odin/rendezvous/provider-catalog" }),
|
||||
[string] $OdinCultMeshRudpEndpoint = $(if ($env:CULTMESH_URI_ODIN_RUDP) { $env:CULTMESH_URI_ODIN_RUDP } else { "127.0.0.1:17871" }),
|
||||
[string] $HidControllerRudpBind = "",
|
||||
|
|
@ -29,9 +26,6 @@ if ($env:IDUNN_ACTUATOR -ne "1" -or $env:IDUNN_COMMAND_AUTHORITY -ne "idunn-daem
|
|||
if (-not (Test-Path -LiteralPath $MuninnExe)) {
|
||||
throw "Muninn executable not found at $MuninnExe"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($IdunnRudpHealth)) {
|
||||
throw "Idunn RUDP health endpoint must be supplied by -IdunnRudpHealth or IDUNN_RUDP_HEALTH; no Starfire LAN default is allowed."
|
||||
}
|
||||
if (-not [string]::IsNullOrWhiteSpace($HidControllerRudpBind) -and [string]::IsNullOrWhiteSpace($HidControllerRudpAdvertise)) {
|
||||
throw "HID controller RUDP advertise endpoint must be supplied by -HidControllerRudpAdvertise or MUNINN_HID_CONTROLLER_RUDP_ADVERTISE when HID RUDP bind is enabled; no Starfire LAN default is allowed."
|
||||
}
|
||||
|
|
@ -63,10 +57,7 @@ $arguments = @(
|
|||
"--host", "starfire",
|
||||
"--interval-seconds", "15",
|
||||
"--quest-adb",
|
||||
"--quest-serial", $QuestSerial,
|
||||
"--idunn-rudp-health", $IdunnRudpHealth,
|
||||
"--idunn-daemon", $IdunnDaemon,
|
||||
"--idunn-health-contract", $IdunnHealthContract
|
||||
"--quest-serial", $QuestSerial
|
||||
)
|
||||
if (-not [string]::IsNullOrWhiteSpace($OdinCultMeshUri)) {
|
||||
$arguments += @("--odin-cultmesh-uri", $OdinCultMeshUri)
|
||||
|
|
@ -160,15 +151,3 @@ if ($null -eq $processCheck) {
|
|||
if ($null -eq $processCheck) {
|
||||
throw "Starfire Muninn serve process is not running after restart"
|
||||
}
|
||||
foreach ($pattern in @(
|
||||
"--idunn-rudp-health",
|
||||
$IdunnRudpHealth,
|
||||
"--idunn-daemon",
|
||||
$IdunnDaemon,
|
||||
"--idunn-health-contract",
|
||||
$IdunnHealthContract
|
||||
)) {
|
||||
if ($processCheck.CommandLine -notlike "*$pattern*") {
|
||||
throw "Starfire Muninn serve command line is missing ${pattern}: $($processCheck.CommandLine)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue