use super::RpcHandler; use crate::{identity, mesh}; use anyhow::Result; use tracing::info; impl RpcHandler { /// mesh.status — Get mesh radio status and detected devices. pub(super) async fn handle_mesh_status(&self) -> Result { let config = mesh::load_config(&self.config.data_dir).await?; let devices = mesh::detect_meshtastic_devices().await; Ok(serde_json::json!({ "enabled": config.enabled, "device_path": config.device_path, "channel_name": config.channel_name, "broadcast_identity": config.broadcast_identity, "detected_devices": devices, })) } /// mesh.discover — Discover nodes via mesh radio. pub(super) async fn handle_mesh_discover( &self, params: Option, ) -> Result { let device_path = params .as_ref() .and_then(|p| p.get("device_path")) .and_then(|v| v.as_str()); let config = mesh::load_config(&self.config.data_dir).await?; let effective_device = device_path.or(config.device_path.as_deref()); let nodes = mesh::discover_nodes(effective_device).await?; Ok(serde_json::json!({ "nodes": nodes, "count": nodes.len(), })) } /// mesh.broadcast — Broadcast our node identity over mesh. pub(super) async fn handle_mesh_broadcast(&self) -> Result { let config = mesh::load_config(&self.config.data_dir).await?; if !config.enabled { anyhow::bail!("Mesh networking is not enabled. Configure it first."); } let (data, _) = self.state_manager.get_snapshot().await; let did = identity::did_key_from_pubkey_hex(&data.server_info.pubkey)?; let pubkey = &data.server_info.pubkey; mesh::broadcast_identity(&did, pubkey, config.device_path.as_deref()).await?; info!("Broadcast identity over mesh"); Ok(serde_json::json!({ "broadcast": true })) } /// mesh.configure — Enable/disable mesh and set device path. pub(super) async fn handle_mesh_configure( &self, params: Option, ) -> Result { let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?; let mut config = mesh::load_config(&self.config.data_dir).await?; if let Some(enabled) = params.get("enabled").and_then(|v| v.as_bool()) { config.enabled = enabled; } if let Some(device) = params.get("device_path").and_then(|v| v.as_str()) { config.device_path = Some(device.to_string()); } if let Some(channel) = params.get("channel_name").and_then(|v| v.as_str()) { config.channel_name = Some(channel.to_string()); } if let Some(broadcast) = params.get("broadcast_identity").and_then(|v| v.as_bool()) { config.broadcast_identity = broadcast; } mesh::save_config(&self.config.data_dir, &config).await?; info!("Mesh config updated"); Ok(serde_json::json!({ "configured": true, "enabled": config.enabled, "device_path": config.device_path, })) } }