168 lines
6.0 KiB
Diff
168 lines
6.0 KiB
Diff
|
From b545460c66b8de1e94ae3ebd8614fe1d3b18b22c Mon Sep 17 00:00:00 2001
|
||
|
From: Benjamin Bouvier <public@benj.me>
|
||
|
Date: Thu, 8 Aug 2019 10:05:25 +0200
|
||
|
Subject: [PATCH] Fixes #387: Display WiFi signal strength in the net block.
|
||
|
|
||
|
---
|
||
|
blocks.md | 2 ++
|
||
|
src/blocks/net.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++-
|
||
|
2 files changed, 81 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/blocks.md b/blocks.md
|
||
|
index 94e6cde..5584e66 100644
|
||
|
--- a/blocks.md
|
||
|
+++ b/blocks.md
|
||
|
@@ -485,6 +485,7 @@ Creates a block which displays the upload and download throughput for a network
|
||
|
block = "net"
|
||
|
device = "wlp2s0"
|
||
|
ssid = true
|
||
|
+signal_strength = true
|
||
|
ip = true
|
||
|
speed_up = false
|
||
|
graph_up = true
|
||
|
@@ -497,6 +498,7 @@ Key | Values | Required | Default
|
||
|
----|--------|----------|--------
|
||
|
`device` | Network interface to moniter (name from /sys/class/net) | Yes | `lo` (loopback interface)
|
||
|
`ssid` | Display network SSID (wireless only). | No | `false`
|
||
|
+`signal_strength` | Display WiFi signal strength (wireless only). | No | `false`
|
||
|
`bitrate` | Display connection bitrate. | No | `false`
|
||
|
`ip` | Display connection IP address. | No | `false`
|
||
|
`speed_up` | Display upload speed. | No | `true`
|
||
|
diff --git a/src/blocks/net.rs b/src/blocks/net.rs
|
||
|
index 87b1332..328e587 100644
|
||
|
--- a/src/blocks/net.rs
|
||
|
+++ b/src/blocks/net.rs
|
||
|
@@ -130,6 +130,62 @@ impl NetworkDevice {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ fn absolute_signal_strength(&self) -> Result<Option<i32>> {
|
||
|
+ let up = self.is_up()?;
|
||
|
+ if !self.wireless || !up {
|
||
|
+ return Err(BlockError(
|
||
|
+ "net".to_string(),
|
||
|
+ "Signal strength is only available for connected wireless devices."
|
||
|
+ .to_string(),
|
||
|
+ ));
|
||
|
+ }
|
||
|
+ let mut iw_output = Command::new("sh")
|
||
|
+ .args(&[
|
||
|
+ "-c",
|
||
|
+ &format!(
|
||
|
+ "iw dev {} link | sed -n 's/^\\s\\+signal: \\(.*\\) dBm/\\1/p'",
|
||
|
+ self.device
|
||
|
+ ),
|
||
|
+ ])
|
||
|
+ .output()
|
||
|
+ .block_error("net", "Failed to execute signal strength query.")?
|
||
|
+ .stdout;
|
||
|
+ if iw_output.is_empty() {
|
||
|
+ Ok(None)
|
||
|
+ } else {
|
||
|
+ iw_output.pop(); // Remove trailing newline.
|
||
|
+ String::from_utf8(iw_output)
|
||
|
+ .block_error("net", "Non-UTF8 signal strength.")
|
||
|
+ .and_then(|as_str| as_str.parse::<i32>()
|
||
|
+ .block_error("net", "Non numerical signal strength."))
|
||
|
+ .map(Some)
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ fn relative_signal_strength(&self) -> Result<Option<u32>> {
|
||
|
+ let xbm = if let Some(xbm) = self.absolute_signal_strength()? {
|
||
|
+ xbm as f64
|
||
|
+ } else {
|
||
|
+ return Ok(None);
|
||
|
+ };
|
||
|
+
|
||
|
+ // Code inspired by https://github.com/NetworkManager/NetworkManager/blob/master/src/platform/wifi/nm-wifi-utils-nl80211.c
|
||
|
+ const NOISE_FLOOR_DBM: f64 = -90.;
|
||
|
+ const SIGNAL_MAX_DBM: f64 = -20.;
|
||
|
+
|
||
|
+ let xbm = if xbm < NOISE_FLOOR_DBM {
|
||
|
+ NOISE_FLOOR_DBM
|
||
|
+ } else if xbm > SIGNAL_MAX_DBM {
|
||
|
+ SIGNAL_MAX_DBM
|
||
|
+ } else {
|
||
|
+ xbm
|
||
|
+ };
|
||
|
+
|
||
|
+ let result = 100. - 70. * ((SIGNAL_MAX_DBM - xbm) / (SIGNAL_MAX_DBM - NOISE_FLOOR_DBM));
|
||
|
+ let result = result as u32;
|
||
|
+ Ok(Some(result))
|
||
|
+ }
|
||
|
+
|
||
|
/// Queries the inet IP of this device (using `ip`).
|
||
|
pub fn ip_addr(&self) -> Result<Option<String>> {
|
||
|
if !self.is_up()? {
|
||
|
@@ -196,6 +252,7 @@ pub struct Net {
|
||
|
network: ButtonWidget,
|
||
|
ssid: Option<ButtonWidget>,
|
||
|
max_ssid_width: usize,
|
||
|
+ signal_strength: Option<ButtonWidget>,
|
||
|
ip_addr: Option<ButtonWidget>,
|
||
|
bitrate: Option<ButtonWidget>,
|
||
|
output_tx: Option<ButtonWidget>,
|
||
|
@@ -235,6 +292,10 @@ pub struct NetConfig {
|
||
|
#[serde(default = "NetConfig::default_max_ssid_width")]
|
||
|
pub max_ssid_width: usize,
|
||
|
|
||
|
+ /// Whether to show the signal strength of active wireless networks.
|
||
|
+ #[serde(default = "NetConfig::default_signal_strength")]
|
||
|
+ pub signal_strength: bool,
|
||
|
+
|
||
|
/// Whether to show the bitrate of active wireless networks.
|
||
|
#[serde(default = "NetConfig::default_bitrate")]
|
||
|
pub bitrate: bool,
|
||
|
@@ -296,6 +357,10 @@ impl NetConfig {
|
||
|
false
|
||
|
}
|
||
|
|
||
|
+ fn default_signal_strength() -> bool {
|
||
|
+ false
|
||
|
+ }
|
||
|
+
|
||
|
fn default_bitrate() -> bool {
|
||
|
false
|
||
|
}
|
||
|
@@ -350,6 +415,10 @@ impl ConfigBlock for Net {
|
||
|
None
|
||
|
},
|
||
|
max_ssid_width: block_config.max_ssid_width,
|
||
|
+ signal_strength: if block_config.signal_strength && wireless {
|
||
|
+ Some(ButtonWidget::new(config.clone(), &id)) } else {
|
||
|
+ None
|
||
|
+ },
|
||
|
bitrate: if block_config.bitrate {
|
||
|
Some(ButtonWidget::new(config.clone(), &id)) } else {
|
||
|
None
|
||
|
@@ -460,6 +529,12 @@ impl Block for Net {
|
||
|
ssid_widget.set_text(truncated);
|
||
|
}
|
||
|
}
|
||
|
+ if let Some(ref mut signal_strength_widget) = self.signal_strength {
|
||
|
+ let value = self.device.relative_signal_strength()?;
|
||
|
+ if value.is_some() {
|
||
|
+ signal_strength_widget.set_text(format!("{}%", value.unwrap()));
|
||
|
+ }
|
||
|
+ }
|
||
|
if let Some(ref mut ip_addr_widget) = self.ip_addr {
|
||
|
let ip_addr = self.device.ip_addr()?;
|
||
|
if ip_addr.is_some() {
|
||
|
@@ -510,11 +585,14 @@ impl Block for Net {
|
||
|
|
||
|
fn view(&self) -> Vec<&I3BarWidget> {
|
||
|
if self.active {
|
||
|
- let mut widgets: Vec<&I3BarWidget> = Vec::with_capacity(7);
|
||
|
+ let mut widgets: Vec<&I3BarWidget> = Vec::with_capacity(8);
|
||
|
widgets.push(&self.network);
|
||
|
if let Some(ref ssid_widget) = self.ssid {
|
||
|
widgets.push(ssid_widget);
|
||
|
};
|
||
|
+ if let Some(ref signal_strength_widget) = self.signal_strength {
|
||
|
+ widgets.push(signal_strength_widget);
|
||
|
+ };
|
||
|
if let Some(ref bitrate_widget) = self.bitrate {
|
||
|
widgets.push(bitrate_widget);
|
||
|
}
|