gled-core 2.34.0

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! The temperature of the machine the engine runs on, which every interface
//! shows, wherever it runs: the hottest of the machine's sensors, read once a
//! second. On a Raspberry Pi 5 that is the SoC's sensor, which covers the CPU
//! and the GPU on the same die.

use std::time::Duration;

use kanal::{Receiver, bounded};
use sysinfo::Components;

const INTERVAL: Duration = Duration::from_secs(1);

/// Starts reading the sensors. The receiver gets the hottest reading in °C
/// once a second, `None` on a machine without temperature sensors.
pub(crate) fn start_thread() -> Receiver<Option<f32>> {
    let (sender, receiver) = bounded(1);

    std::thread::Builder::new()
        .name("gled:temperature".to_owned())
        .spawn(move || {
            #[cfg(feature = "profiling")]
            profiling::register_thread!("temperature");

            loop {
                // Listed anew every time: sensors come and go with the
                // drivers, a USB device or a fan being plugged in.
                let hottest = Components::new_with_refreshed_list()
                    .iter()
                    .filter_map(|component| component.temperature())
                    .filter(|temperature| temperature.is_finite())
                    .reduce(f32::max);
                if sender.send(hottest).is_err() {
                    tracing::debug!("the engine is gone, stopping to read the temperature");
                    return;
                }
                std::thread::sleep(INTERVAL);
            }
        })
        .expect("Could not spawn temperature thread");

    receiver
}