Device Management
nmrs provides methods to list, inspect, and control network devices managed by NetworkManager.
Listing All Devices
use nmrs::NetworkManager; #[tokio::main] async fn main() -> nmrs::Result<()> { let nm = NetworkManager::new().await?; let devices = nm.list_devices().await?; for device in &devices { println!("{}", device); // "wlan0 (Wi-Fi) [Activated]" } Ok(()) }
The Device Struct
Each device provides the following information:
| Field | Type | Description |
|---|---|---|
path | String | D-Bus object path |
interface | String | Interface name (e.g., wlan0, eth0) |
identity | DeviceIdentity | MAC addresses (permanent and current) |
device_type | DeviceType | Type of device |
state | DeviceState | Current operational state |
managed | Option<bool> | Whether NetworkManager manages this device |
driver | Option<String> | Kernel driver name |
ip4_address | Option<String> | IPv4 address with CIDR (when connected) |
ip6_address | Option<String> | IPv6 address with CIDR (when connected) |
Device Types
#![allow(unused)] fn main() { use nmrs::DeviceType; }
| Variant | Description |
|---|---|
DeviceType::Wifi | Wi-Fi (802.11) wireless adapter |
DeviceType::Ethernet | Wired Ethernet interface |
DeviceType::Bluetooth | Bluetooth network device |
DeviceType::WifiP2P | Wi-Fi Direct (peer-to-peer) |
DeviceType::Loopback | Loopback interface (localhost) |
DeviceType::Other(u32) | Unknown type with raw code |
Type Helper Methods
#![allow(unused)] fn main() { let device = &devices[0]; if device.is_wireless() { println!("{} is a Wi-Fi adapter", device.interface); } if device.is_wired() { println!("{} is an Ethernet interface", device.interface); } if device.is_bluetooth() { println!("{} is a Bluetooth device", device.interface); } }
DeviceType also provides capability queries:
#![allow(unused)] fn main() { let dt = &device.device_type; dt.supports_scanning(); // true for Wifi, WifiP2P dt.requires_specific_object(); // true for Wifi, WifiP2P dt.has_global_enabled_state(); // true for Wifi dt.connection_type_str(); // "802-11-wireless", "802-3-ethernet", etc. dt.to_code(); // raw NM type code (2 for Wifi, 1 for Ethernet) }
Device States
#![allow(unused)] fn main() { use nmrs::DeviceState; }
| State | Description |
|---|---|
Unmanaged | Not managed by NetworkManager |
Unavailable | Managed but not ready (e.g., Wi-Fi disabled) |
Disconnected | Available but not connected |
Prepare | Preparing to connect |
Config | Being configured |
NeedAuth | Waiting for credentials |
IpConfig | Requesting IP configuration |
IpCheck | Verifying IP connectivity |
Secondaries | Waiting for secondary connections |
Activated | Fully connected and operational |
Deactivating | Disconnecting |
Failed | Connection failed |
Other(u32) | Unknown state with raw code |
Transitional States
Use is_transitional() to check if a device is in a connecting or disconnecting state:
#![allow(unused)] fn main() { if device.state.is_transitional() { println!("{} is in a transitional state: {}", device.interface, device.state); } }
Transitional states include: Prepare, Config, NeedAuth, IpConfig, IpCheck, Secondaries, and Deactivating.
Filtered Device Lists
#![allow(unused)] fn main() { let nm = NetworkManager::new().await?; // Only wireless devices let wireless = nm.list_wireless_devices().await?; // Only wired devices let wired = nm.list_wired_devices().await?; // Only Bluetooth devices (returns BluetoothDevice, not Device) let bluetooth = nm.list_bluetooth_devices().await?; }
Wi-Fi Radio Control
Enable or disable the Wi-Fi radio globally:
#![allow(unused)] fn main() { let nm = NetworkManager::new().await?; // Check current state let enabled = nm.wifi_enabled().await?; println!("Wi-Fi enabled: {}", enabled); // Check hardware switch (rfkill) let hw_enabled = nm.wifi_hardware_enabled().await?; println!("Wi-Fi hardware enabled: {}", hw_enabled); // Toggle Wi-Fi nm.set_wifi_enabled(false).await?; // Disable nm.set_wifi_enabled(true).await?; // Enable }
Note:
wifi_hardware_enabled()reflects the rfkill state. If the hardware switch is off, enabling Wi-Fi via software will have no effect.
Waiting for Wi-Fi Ready
After enabling Wi-Fi, the device may take a moment to become ready:
#![allow(unused)] fn main() { let nm = NetworkManager::new().await?; nm.set_wifi_enabled(true).await?; nm.wait_for_wifi_ready().await?; // Now safe to scan and connect nm.scan_networks().await?; }
Finding a Device by Interface Name
#![allow(unused)] fn main() { let nm = NetworkManager::new().await?; let device_path = nm.get_device_by_interface("wlan0").await?; println!("D-Bus path: {}", device_path.as_str()); }
Device Identity
Each device has both a permanent (factory) and current MAC address:
#![allow(unused)] fn main() { for device in nm.list_devices().await? { println!("{}: permanent={}, current={}", device.interface, device.identity.permanent_mac, device.identity.current_mac, ); } }
If MAC randomization is enabled, the current MAC will differ from the permanent one.
Checking Connection Progress
Before starting a new connection, check if any device is currently connecting:
#![allow(unused)] fn main() { if nm.is_connecting().await? { println!("A connection operation is in progress"); } }
Next Steps
- WiFi Management – Wi-Fi-specific operations
- Bluetooth – Bluetooth device management
- Ethernet Management – wired connections
- Real-Time Monitoring – subscribe to device state changes