other: aarch64 support (#217)

Adds theoretical aarch64 support.
This commit is contained in:
Clement Tsang 2020-09-02 02:59:51 -04:00 committed by GitHub
parent 663ae6c5c2
commit 22278d7d75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 513 additions and 192 deletions

View File

@ -4,4 +4,4 @@ echo "Executing: cargo +nightly clippy -- -D clippy::all"
cargo +nightly clippy -- -D clippy::all
echo "Executing: cargo test"
cargo test
cargo test

View File

@ -1,4 +1,8 @@
[target.x86_64-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static"]
[target.i686-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static"]
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"

View File

@ -1,16 +1,75 @@
language: rust
rust:
- stable
- beta
os:
- linux
- osx
- windows
jobs:
cache: cargo
notifications:
email:
on_success: never
matrix:
include:
# Standard x86-64 stuff, stable and beta
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
arch: amd64
rust: stable
- os: linux
env: TARGET=x86_64-unknown-linux-gnu
arch: amd64
rust: beta
- os: osx
env: TARGET=x86_64-apple-darwin
arch: amd64
rust: stable
- os: osx
env: TARGET=x86_64-apple-darwin
arch: amd64
rust: beta
- os: windows
env: TARGET=x86_64-pc-windows-msvc
arch: amd64
rust: stable
- os: windows
env: TARGET=x86_64-pc-windows-msvc
arch: amd64
rust: beta
# musl
- os: linux
env: TARGET=x86_64-unknown-linux-musl
arch: amd64
rust: stable
- os: linux
env: TARGET=x86_64-unknown-linux-musl
arch: amd64
rust: beta
# ARM stuff (skip beta for now, see https://github.com/rust-lang/rust/issues/62896)
- os: linux
env: TARGET=aarch64-unknown-linux-gnu
arch: arm64
rust: stable
- os: linux
env: TARGET=armv7-unknown-linux-gnueabihf
arch: amd64
rust: stable
addons:
apt:
packages: &armhf
- gcc-arm-linux-gnueabihf
- libc6-armhf-cross
- libc6-dev-armhf-cross
fast_finish: true
exclude:
- if: tag IS present
rust: beta
- if: tag IS present
arch: arm64
- if: tag IS present
env: TARGET=armv7-unknown-linux-gnueabihf
allow_failures:
- arch: arm64 # ARM will be run, but support is still gonna be limited for now... may change.
- env: TARGET=armv7-unknown-linux-gnueabihf
branches:
only:
- master
@ -19,10 +78,7 @@ branches:
before_install:
- export RUST_BACKTRACE=1
- |
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
export TARGET=x86_64-unknown-linux-gnu;
elif [[ $TRAVIS_OS_NAME == "windows" ]]; then
export TARGET=x86_64-pc-windows-msvc;
if [[ $TRAVIS_OS_NAME == "windows" ]]; then
if [[ -n $TRAVIS_TAG ]]; then
powershell Install-WindowsFeature Net-Framework-Core;
choco install -y wixtoolset;
@ -30,21 +86,29 @@ before_install:
choco install zip;
rustup target add i686-pc-windows-msvc;
fi
elif [[ $TRAVIS_OS_NAME == "osx" ]]; then
export TARGET=x86_64-apple-darwin;
fi
before_script:
- rustup target add $TARGET
- rustup component add clippy
- rustup update
- |
# Only check clippy if stable...
if [[ $TRAVIS_RUST_VERSION == "stable" ]]; then
rustup component add clippy
fi
script:
- cargo clippy -- -D clippy::all
- cargo test --verbose --target $TARGET
cache: cargo
notifications:
email:
on_success: never
- |
# Only check clippy if stable...
if [[ $TRAVIS_RUST_VERSION == "stable" ]]; then
cargo clippy -- -D clippy::all
fi
- |
if [[ $TARGET = "armv7-unknown-linux-gnueabihf" ]]; then
cargo build --verbose --target $TARGET
else
cargo test --verbose --target $TARGET
fi
before_deploy:
- |
@ -98,11 +162,10 @@ before_deploy:
strip btm;
local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname)
cp -r $target_dir completions
echo "Tar-ing macOS/Linux binary and completions..."
tar -czvf bottom_$TARGET.tar.gz btm completions;
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
echo "Tar-ing Linux binary and completions..."
tar -czvf bottom_x86_64-unknown-linux-gnu.tar.gz btm completions;
echo "Generating AUR template...";
python "./deployment/packager.py" $TRAVIS_TAG "./deployment/linux/arch/PKGBUILD_BIN.template" "./PKGBUILD_BIN" "SHA512" "./bottom_x86_64-unknown-linux-gnu.tar.gz";
curl -LO "https://github.com/ClementTsang/bottom/archive/$TRAVIS_TAG.tar.gz";
@ -120,9 +183,6 @@ before_deploy:
cargo deb;
cp ./target/debian/bottom_*.deb .;
elif [[ $TRAVIS_OS_NAME == "osx" ]]; then
echo "Tar-ing macOS binary and completions..."
tar -czvf bottom_x86_64-apple-darwin.tar.gz btm completions;
# The bottom.rb file must be generated AFTER, since it relies on the Linux binary file.
fi

View File

@ -19,6 +19,7 @@
"Mousebindings",
"Nonexhaustive",
"PKGBUILD",
"PKGBUILDs",
"Polishchuk",
"Qudsi",
"SIGTERM",
@ -30,6 +31,7 @@
"WASD",
"Wojnarowski",
"andys",
"armv",
"atim",
"choco",
"cmdline",
@ -39,6 +41,7 @@
"czvf",
"fpath",
"fract",
"gnueabihf",
"gotop",
"gtop",
"haase",
@ -48,6 +51,7 @@
"markdownlint",
"memb",
"minwindef",
"musl",
"n'th",
"noheader",
"ntdef",
@ -81,6 +85,7 @@
"winget",
"winnt",
"wixtoolset",
"xargs",
"xzvf",
"ytop"
]

View File

@ -32,7 +32,6 @@ ctrlc = {version = "3.1", features = ["termination"]}
clap = "2.33"
dirs = "3.0.1"
futures = "0.3.5"
heim = "0.0.10"
itertools = "0.9.0"
libc = "0.2"
regex = "1.3"
@ -51,6 +50,9 @@ tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
fern = "0.6.0"
log = "0.4.11"
[target.'cfg(not(any(target_arch = "arm", target_arch = "aarch64")))'.dependencies]
heim = "0.0.10"
[target.'cfg(windows)'.dependencies]
winapi = "0.3.9"

View File

@ -62,7 +62,9 @@ Note that bottom is:
- Officially tested and released for only `x86_64` (and `i686` for Windows)
- Developed mainly for macOS, Windows, and Linux
As such, support beyond that is not guaranteed.
As such, support beyond that is not guaranteed. There is now _technically_ support for AArch64 builds,
and I do run them in Travis, but I am currently not guaranteeing their stability. In theory, they should
work fine, but I've had some troubles with building on ARM in some situations.
### Manually

View File

@ -15,8 +15,9 @@ use lazy_static::lazy_static;
/// more points as this is used!
use std::{time::Instant, vec::Vec};
use crate::data_harvester::{
battery_harvester, cpu, disks, mem, network, processes, temperature, Data,
use crate::{
data_harvester::{battery_harvester, cpu, disks, mem, network, processes, temperature, Data},
utils::gen_util::get_simple_byte_values,
};
use regex::Regex;
@ -54,6 +55,7 @@ pub struct DataCollection {
pub disk_harvest: Vec<disks::DiskHarvest>,
pub io_harvest: disks::IOHarvest,
pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>,
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
pub battery_harvest: Vec<battery_harvester::BatteryHarvest>,
}
@ -72,6 +74,7 @@ impl Default for DataCollection {
disk_harvest: Vec::default(),
io_harvest: disks::IOHarvest::default(),
io_labels_and_prev: Vec::default(),
io_labels: Vec::default(),
temp_harvest: Vec::default(),
battery_harvest: Vec::default(),
}
@ -232,7 +235,6 @@ impl DataCollection {
if let Some(trim) = device.name.split('/').last() {
let io_device = if cfg!(target_os = "macos") {
// Must trim one level further!
lazy_static! {
static ref DISK_REGEX: Regex = Regex::new(r"disk\d+").unwrap();
}
@ -244,24 +246,50 @@ impl DataCollection {
} else {
io.get(trim)
};
let (io_r_pt, io_w_pt) = if let Some(io) = io_device {
(io.read_bytes, io.write_bytes)
if let Some(io_device) = io_device {
let (io_r_pt, io_w_pt) = if let Some(io) = io_device {
(io.read_bytes, io.write_bytes)
} else {
(0, 0)
};
if self.io_labels.len() <= itx {
self.io_labels.push((String::default(), String::default()));
}
if self.io_labels_and_prev.len() <= itx {
self.io_labels_and_prev.push(((0, 0), (io_r_pt, io_w_pt)));
}
if let Some((io_curr, io_prev)) = self.io_labels_and_prev.get_mut(itx) {
let r_rate = ((io_r_pt.saturating_sub(io_prev.0)) as f64
/ time_since_last_harvest)
.round() as u64;
let w_rate = ((io_w_pt.saturating_sub(io_prev.1)) as f64
/ time_since_last_harvest)
.round() as u64;
*io_curr = (r_rate, w_rate);
*io_prev = (io_r_pt, io_w_pt);
if let Some(io_labels) = self.io_labels.get_mut(itx) {
let converted_read = get_simple_byte_values(r_rate, false);
let converted_write = get_simple_byte_values(w_rate, false);
*io_labels = (
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1),
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1),
);
}
}
} else {
(0, 0)
};
if self.io_labels.len() <= itx {
self.io_labels.push((String::default(), String::default()));
}
if self.io_labels_and_prev.len() <= itx {
self.io_labels_and_prev.push(((0, 0), (io_r_pt, io_w_pt)));
} else if let Some((io_curr, io_prev)) = self.io_labels_and_prev.get_mut(itx) {
let r_rate = ((io_r_pt.saturating_sub(io_prev.0)) as f64
/ time_since_last_harvest)
.round() as u64;
let w_rate = ((io_w_pt.saturating_sub(io_prev.1)) as f64
/ time_since_last_harvest)
.round() as u64;
*io_curr = (r_rate, w_rate);
*io_prev = (io_r_pt, io_w_pt);
if let Some(io_labels) = self.io_labels.get_mut(itx) {
*io_labels = ("N/A".to_string(), "N/A".to_string());
}
}
}
}

View File

@ -160,16 +160,32 @@ impl DataCollector {
self.sys.refresh_cpu();
}
if cfg!(not(target_os = "linux")) {
if cfg!(any(target_arch = "arm", target_arch = "aarch64")) {
// ARM stuff
if self.widgets_to_harvest.use_proc {
self.sys.refresh_processes();
}
if self.widgets_to_harvest.use_temp {
self.sys.refresh_components();
}
}
if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
self.sys.refresh_networks();
if self.widgets_to_harvest.use_net {
self.sys.refresh_networks();
}
if self.widgets_to_harvest.use_mem {
self.sys.refresh_memory();
}
} else {
if cfg!(not(target_os = "linux")) {
if self.widgets_to_harvest.use_proc {
self.sys.refresh_processes();
}
if self.widgets_to_harvest.use_temp {
self.sys.refresh_components();
}
}
if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
self.sys.refresh_networks();
}
}
let current_instant = std::time::Instant::now();
@ -230,25 +246,96 @@ impl DataCollector {
}
}
// ASYNC
let network_data_fut = network::get_network_data(
&self.sys,
self.last_collection_time,
&mut self.total_rx,
&mut self.total_tx,
current_instant,
self.widgets_to_harvest.use_net,
);
// Async if Heim
let network_data_fut = {
#[cfg(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm"))]
{
network::get_sysinfo_network_data(
&self.sys,
self.last_collection_time,
&mut self.total_rx,
&mut self.total_tx,
current_instant,
self.widgets_to_harvest.use_net,
)
}
#[cfg(not(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm")))]
{
network::get_heim_network_data(
self.last_collection_time,
&mut self.total_rx,
&mut self.total_tx,
current_instant,
self.widgets_to_harvest.use_net,
)
}
};
let mem_data_fut = {
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
mem::get_sysinfo_mem_data_list(&self.sys, self.widgets_to_harvest.use_mem)
}
let mem_data_fut = mem::get_mem_data_list(self.widgets_to_harvest.use_mem);
let swap_data_fut = mem::get_swap_data_list(self.widgets_to_harvest.use_mem);
let disk_data_fut = disks::get_disk_usage_list(self.widgets_to_harvest.use_disk);
let disk_io_usage_fut = disks::get_io_usage_list(false, self.widgets_to_harvest.use_disk);
let temp_data_fut = temperature::get_temperature_data(
&self.sys,
&self.temperature_type,
self.widgets_to_harvest.use_temp,
);
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
{
mem::get_heim_mem_data_list(self.widgets_to_harvest.use_mem)
}
};
let swap_data_fut = {
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
mem::get_sysinfo_swap_data_list(&self.sys, self.widgets_to_harvest.use_mem)
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
{
mem::get_heim_swap_data_list(self.widgets_to_harvest.use_mem)
}
};
let disk_data_fut = {
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
disks::get_sysinfo_disk_usage_list(&self.sys, self.widgets_to_harvest.use_disk)
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
{
disks::get_heim_disk_usage_list(self.widgets_to_harvest.use_disk)
}
};
let disk_io_usage_fut = {
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
disks::get_sysinfo_io_usage_list(&self.sys, self.widgets_to_harvest.use_disk)
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
{
disks::get_heim_io_usage_list(false, self.widgets_to_harvest.use_disk)
}
};
let temp_data_fut = {
#[cfg(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm"))]
{
temperature::get_sysinfo_temperature_data(
&self.sys,
&self.temperature_type,
self.widgets_to_harvest.use_temp,
)
}
#[cfg(not(any(
not(target_os = "linux"),
target_arch = "aarch64",
target_arch = "arm"
)))]
{
temperature::get_heim_temperature_data(
&self.temperature_type,
self.widgets_to_harvest.use_temp,
)
}
};
let (net_data, mem_res, swap_res, disk_res, io_res, temp_res) = join!(
network_data_fut,
@ -259,7 +346,6 @@ impl DataCollector {
temp_data_fut
);
// After async
if let Some(net_data) = net_data {
self.total_rx = net_data.total_rx;
self.total_tx = net_data.total_tx;

View File

@ -1,6 +1,3 @@
use futures::stream::StreamExt;
use heim::units::information;
#[derive(Debug, Clone, Default)]
pub struct DiskHarvest {
pub name: String,
@ -16,16 +13,60 @@ pub struct IOData {
pub write_bytes: u64,
}
pub type IOHarvest = std::collections::HashMap<String, IOData>;
pub type IOHarvest = std::collections::HashMap<String, Option<IOData>>;
pub async fn get_io_usage_list(
get_physical: bool, actually_get: bool,
/// Meant for ARM use.
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_io_usage_list(
_sys: &sysinfo::System, _actually_get: bool,
) -> crate::utils::error::Result<Option<IOHarvest>> {
let io_hash: std::collections::HashMap<String, Option<IOData>> =
std::collections::HashMap::new();
Ok(Some(io_hash))
// TODO: Sysinfo disk I/O usage.
// ...sadly, this cannot be done as of now (other than me writing my own), it requires further
// work. See https://github.com/GuillaumeGomez/sysinfo/issues/304.
}
/// Meant for ARM use.
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_disk_usage_list(
sys: &sysinfo::System, actually_get: bool,
) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
use sysinfo::{DiskExt, SystemExt};
if !actually_get {
return Ok(None);
}
let mut io_hash: std::collections::HashMap<String, IOData> = std::collections::HashMap::new();
let mut vec_disks = sys
.get_disks()
.iter()
.map(|disk| DiskHarvest {
name: disk.get_name().to_string_lossy().into(),
mount_point: disk.get_mount_point().to_string_lossy().into(),
free_space: disk.get_available_space(),
used_space: disk.get_total_space() - disk.get_available_space(),
total_space: disk.get_total_space(),
})
.collect::<Vec<DiskHarvest>>();
vec_disks.sort_by(|a, b| a.name.cmp(&b.name));
Ok(Some(vec_disks))
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_io_usage_list(
get_physical: bool, actually_get: bool,
) -> crate::utils::error::Result<Option<IOHarvest>> {
use futures::stream::StreamExt;
if !actually_get {
return Ok(None);
}
let mut io_hash: std::collections::HashMap<String, Option<IOData>> =
std::collections::HashMap::new();
if get_physical {
let mut physical_counter_stream = heim::disk::io_counters_physical();
while let Some(io) = physical_counter_stream.next().await {
@ -33,10 +74,10 @@ pub async fn get_io_usage_list(
let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable");
io_hash.insert(
mount_point.to_string(),
IOData {
read_bytes: io.read_bytes().get::<information::megabyte>(),
write_bytes: io.write_bytes().get::<information::megabyte>(),
},
Some(IOData {
read_bytes: io.read_bytes().get::<heim::units::information::megabyte>(),
write_bytes: io.write_bytes().get::<heim::units::information::megabyte>(),
}),
);
}
} else {
@ -46,10 +87,10 @@ pub async fn get_io_usage_list(
let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable");
io_hash.insert(
mount_point.to_string(),
IOData {
read_bytes: io.read_bytes().get::<information::byte>(),
write_bytes: io.write_bytes().get::<information::byte>(),
},
Some(IOData {
read_bytes: io.read_bytes().get::<heim::units::information::byte>(),
write_bytes: io.write_bytes().get::<heim::units::information::byte>(),
}),
);
}
}
@ -57,9 +98,12 @@ pub async fn get_io_usage_list(
Ok(Some(io_hash))
}
pub async fn get_disk_usage_list(
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_disk_usage_list(
actually_get: bool,
) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
use futures::stream::StreamExt;
if !actually_get {
return Ok(None);
}
@ -73,9 +117,9 @@ pub async fn get_disk_usage_list(
let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?;
vec_disks.push(DiskHarvest {
free_space: usage.free().get::<information::byte>(),
used_space: usage.used().get::<information::byte>(),
total_space: usage.total().get::<information::byte>(),
free_space: usage.free().get::<heim::units::information::byte>(),
used_space: usage.used().get::<heim::units::information::byte>(),
total_space: usage.total().get::<heim::units::information::byte>(),
mount_point: (partition
.mount_point()
.to_str()

View File

@ -1,5 +1,3 @@
use heim::units::information;
#[derive(Debug, Clone)]
pub struct MemHarvest {
pub mem_total_in_mb: u64,
@ -15,7 +13,40 @@ impl Default for MemHarvest {
}
}
pub async fn get_mem_data_list(
/// Meant for ARM use.
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_mem_data_list(
sys: &sysinfo::System, actually_get: bool,
) -> crate::utils::error::Result<Option<MemHarvest>> {
use sysinfo::SystemExt;
if !actually_get {
return Ok(None);
}
Ok(Some(MemHarvest {
mem_total_in_mb: sys.get_total_memory() / 1024,
mem_used_in_mb: sys.get_used_memory() / 1024,
}))
}
/// Meant for ARM use.
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_swap_data_list(
sys: &sysinfo::System, actually_get: bool,
) -> crate::utils::error::Result<Option<MemHarvest>> {
use sysinfo::SystemExt;
if !actually_get {
return Ok(None);
}
Ok(Some(MemHarvest {
mem_total_in_mb: sys.get_total_swap() / 1024,
mem_used_in_mb: sys.get_used_swap() / 1024,
}))
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_mem_data_list(
actually_get: bool,
) -> crate::utils::error::Result<Option<MemHarvest>> {
if !actually_get {
@ -25,13 +56,16 @@ pub async fn get_mem_data_list(
let memory = heim::memory::memory().await?;
Ok(Some(MemHarvest {
mem_total_in_mb: memory.total().get::<information::megabyte>(),
mem_used_in_mb: memory.total().get::<information::megabyte>()
- memory.available().get::<information::megabyte>(),
mem_total_in_mb: memory.total().get::<heim::units::information::megabyte>(),
mem_used_in_mb: memory.total().get::<heim::units::information::megabyte>()
- memory
.available()
.get::<heim::units::information::megabyte>(),
}))
}
pub async fn get_swap_data_list(
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_swap_data_list(
actually_get: bool,
) -> crate::utils::error::Result<Option<MemHarvest>> {
if !actually_get {
@ -41,7 +75,7 @@ pub async fn get_swap_data_list(
let memory = heim::memory::swap().await?;
Ok(Some(MemHarvest {
mem_total_in_mb: memory.total().get::<information::megabyte>(),
mem_used_in_mb: memory.used().get::<information::megabyte>(),
mem_total_in_mb: memory.total().get::<heim::units::information::megabyte>(),
mem_used_in_mb: memory.used().get::<heim::units::information::megabyte>(),
}))
}

View File

@ -1,10 +1,5 @@
use std::time::Instant;
use futures::StreamExt;
use heim::net;
use heim::units::information::byte;
use sysinfo::{NetworkExt, System, SystemExt};
#[derive(Default, Clone, Debug)]
pub struct NetworkHarvest {
pub rx: u64,
@ -20,30 +15,67 @@ impl NetworkHarvest {
}
}
pub async fn get_network_data(
sys: &System, prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
curr_time: Instant, actually_get: bool,
/// Meant for Windows and ARM use.
#[cfg(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_network_data(
sys: &sysinfo::System, prev_net_access_time: Instant, prev_net_rx: &mut u64,
prev_net_tx: &mut u64, curr_time: Instant, actually_get: bool,
) -> Option<NetworkHarvest> {
use sysinfo::{NetworkExt, SystemExt};
if !actually_get {
return None;
}
let mut io_data = net::io_counters();
let mut total_rx: u64 = 0;
let mut total_tx: u64 = 0;
if cfg!(target_os = "windows") {
let networks = sys.get_networks();
for (_, network) in networks {
total_rx += network.get_total_received();
total_tx += network.get_total_transmitted();
}
let networks = sys.get_networks();
for (_, network) in networks {
total_rx += network.get_total_received();
total_tx += network.get_total_transmitted();
}
let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64();
let (rx, tx) = if elapsed_time == 0.0 {
(0, 0)
} else {
while let Some(io) = io_data.next().await {
if let Ok(io) = io {
total_rx += io.bytes_recv().get::<byte>();
total_tx += io.bytes_sent().get::<byte>();
}
(
((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64,
((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64,
)
};
*prev_net_rx = total_rx;
*prev_net_tx = total_tx;
Some(NetworkHarvest {
rx,
tx,
total_rx,
total_tx,
})
}
#[cfg(not(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_network_data(
prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
curr_time: Instant, actually_get: bool,
) -> Option<NetworkHarvest> {
use futures::StreamExt;
if !actually_get {
return None;
}
let mut io_data = heim::net::io_counters();
let mut total_rx: u64 = 0;
let mut total_tx: u64 = 0;
while let Some(io) = io_data.next().await {
if let Ok(io) = io {
total_rx += io.bytes_recv().get::<heim::units::information::byte>();
total_tx += io.bytes_sent().get::<heim::units::information::byte>();
}
}

View File

@ -1,9 +1,5 @@
use std::cmp::Ordering;
use futures::StreamExt;
use heim::units::thermodynamic_temperature;
use sysinfo::{ComponentExt, System, SystemExt};
#[derive(Default, Debug, Clone)]
pub struct TempHarvest {
pub component_name: Option<String>,
@ -24,61 +20,90 @@ impl Default for TemperatureType {
}
}
pub async fn get_temperature_data(
sys: &System, temp_type: &TemperatureType, actually_get: bool,
/// Meant for ARM and non-Linux usage.
#[cfg(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm"))]
pub async fn get_sysinfo_temperature_data(
sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool,
) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> {
use sysinfo::{ComponentExt, SystemExt};
fn convert_celsius_to_kelvin(celsius: f32) -> f32 {
celsius + 273.15
}
fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
(celsius * (9.0 / 5.0)) + 32.0
}
if !actually_get {
return Ok(None);
}
let mut temperature_vec: Vec<TempHarvest> = Vec::new();
if cfg!(target_os = "linux") {
let mut sensor_data = heim::sensors::temperatures();
while let Some(sensor) = sensor_data.next().await {
if let Ok(sensor) = sensor {
temperature_vec.push(TempHarvest {
component_name: Some(sensor.unit().to_string()),
component_label: if let Some(label) = sensor.label() {
Some(label.to_string())
} else {
None
},
temperature: match temp_type {
TemperatureType::Celsius => sensor
.current()
.get::<thermodynamic_temperature::degree_celsius>(
),
TemperatureType::Kelvin => {
sensor.current().get::<thermodynamic_temperature::kelvin>()
}
TemperatureType::Fahrenheit => sensor
.current()
.get::<thermodynamic_temperature::degree_fahrenheit>(
),
},
});
}
}
} else {
let sensor_data = sys.get_components();
for component in sensor_data {
let sensor_data = sys.get_components();
for component in sensor_data {
temperature_vec.push(TempHarvest {
component_name: None,
component_label: Some(component.get_label().to_string()),
temperature: match temp_type {
TemperatureType::Celsius => component.get_temperature(),
TemperatureType::Kelvin => convert_celsius_to_kelvin(component.get_temperature()),
TemperatureType::Fahrenheit => {
convert_celsius_to_fahrenheit(component.get_temperature())
}
},
});
}
temp_vec_sort(&mut temperature_vec);
Ok(Some(temperature_vec))
}
#[cfg(not(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm")))]
pub async fn get_heim_temperature_data(
temp_type: &TemperatureType, actually_get: bool,
) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> {
use futures::StreamExt;
if !actually_get {
return Ok(None);
}
let mut temperature_vec: Vec<TempHarvest> = Vec::new();
use heim::units::thermodynamic_temperature;
let mut sensor_data = heim::sensors::temperatures();
while let Some(sensor) = sensor_data.next().await {
if let Ok(sensor) = sensor {
temperature_vec.push(TempHarvest {
component_name: None,
component_label: Some(component.get_label().to_string()),
component_name: Some(sensor.unit().to_string()),
component_label: if let Some(label) = sensor.label() {
Some(label.to_string())
} else {
None
},
temperature: match temp_type {
TemperatureType::Celsius => component.get_temperature(),
TemperatureType::Celsius => sensor
.current()
.get::<thermodynamic_temperature::degree_celsius>(),
TemperatureType::Kelvin => {
convert_celsius_to_kelvin(component.get_temperature())
}
TemperatureType::Fahrenheit => {
convert_celsius_to_fahrenheit(component.get_temperature())
sensor.current().get::<thermodynamic_temperature::kelvin>()
}
TemperatureType::Fahrenheit => sensor
.current()
.get::<thermodynamic_temperature::degree_fahrenheit>(
),
},
});
}
}
temp_vec_sort(&mut temperature_vec);
Ok(Some(temperature_vec))
}
fn temp_vec_sort(temperature_vec: &mut Vec<TempHarvest>) {
// By default, sort temperature, then by alphabetically!
// TODO: [TEMPS] Allow users to control this.
@ -97,14 +122,4 @@ pub async fn get_temperature_data(
.partial_cmp(&b.component_name)
.unwrap_or(Ordering::Equal)
});
Ok(Some(temperature_vec))
}
fn convert_celsius_to_kelvin(celsius: f32) -> f32 {
celsius + 273.15
}
fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
(celsius * (9.0 / 5.0)) + 32.0
}

View File

@ -117,15 +117,8 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S
current_data
.disk_harvest
.iter()
.zip(&current_data.io_labels_and_prev)
.for_each(|(disk, (io_label, _io_prev))| {
let converted_read = get_simple_byte_values(io_label.0, false);
let converted_write = get_simple_byte_values(io_label.1, false);
let io_activity = (
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1),
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1),
);
.zip(&current_data.io_labels)
.for_each(|(disk, (io_read, io_write))| {
let converted_free_space = get_simple_byte_values(disk.free_space, false);
let converted_total_space = get_simple_byte_values(disk.total_space, false);
disk_vector.push(vec![
@ -140,8 +133,8 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S
"{:.*}{}",
0, converted_total_space.0, converted_total_space.1
),
io_activity.0,
io_activity.1,
io_read.to_string(),
io_write.to_string(),
]);
});
@ -348,7 +341,7 @@ pub fn convert_network_data_points(
}
} else {
let rx_display = format!(
"RX: {:<9} Total: {:<9}",
"RX: {:<9} All: {:<9}",
format!("{:.1}{:3}", rx_converted_result.0, rx_converted_result.1),
format!(
"{:.1}{:3}",
@ -356,7 +349,7 @@ pub fn convert_network_data_points(
)
);
let tx_display = format!(
"TX: {:<9} Total: {:<9}",
"TX: {:<9} All: {:<9}",
format!("{:.1}{:3}", tx_converted_result.0, tx_converted_result.1),
format!(
"{:.1}{:3}",

View File

@ -42,6 +42,7 @@ impl From<std::io::Error> for BottomError {
}
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
impl From<heim::Error> for BottomError {
fn from(err: heim::Error) -> Self {
BottomError::InvalidHeim(err.to_string())

View File

@ -148,6 +148,17 @@ fn test_empty_battery() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
#[test]
fn test_lone_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
Command::new(get_binary_location())
.arg("-C")
.arg("./tests/invalid_configs/lone_default_widget_count.toml")
.assert()
.failure()
.stderr(predicate::str::contains("it must be used with"));
Ok(())
}
#[test]
fn test_invalid_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
Command::new(get_binary_location())
@ -155,6 +166,6 @@ fn test_invalid_default_widget_count() -> Result<(), Box<dyn std::error::Error>>
.arg("./tests/invalid_configs/invalid_default_widget_count.toml")
.assert()
.failure()
.stderr(predicate::str::contains("it must be used with"));
.stderr(predicate::str::contains("invalid number"));
Ok(())
}

View File

@ -1,2 +1,3 @@
[flags]
default_widget_count = 3
default_widget_type="CPU"
default_widget_count=18446744073709551616

View File

@ -2,4 +2,5 @@
[[row.child]]
type="cpu"
[[row.child]]
type="not_real"
type="not_real"

View File

@ -0,0 +1,2 @@
[flags]
default_widget_count = 3

View File

@ -1,2 +1,2 @@
[flags]
basic = "test"
basic = "test"