From bbe5fd5452a20d2ad2612f394f77deb4680b99c5 Mon Sep 17 00:00:00 2001 From: KenwoodFox Date: Thu, 18 Jun 2026 14:09:14 -0400 Subject: [PATCH] Add enhanced fan logic --- README.md | 2 +- docker-compose.yml | 18 ------------- src/config.rs | 4 +-- src/daemon.rs | 5 +++- src/tasks/renogy.rs | 61 ++++++++++++++++++++++++++++++++++++------ src/tasks/thermal.rs | 39 +++------------------------ systemd/towerd.service | 4 +-- 7 files changed, 66 insertions(+), 67 deletions(-) delete mode 100644 docker-compose.yml diff --git a/README.md b/README.md index 88ebfc8..edc8009 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,6 @@ TOWERD_RENOGY_TIMEOUT_MS=1000 ``` Thank you to [ESP32ArduinoRenogy](https://github.com/wrybread/ESP32ArduinoRenogy) for doing all the hard work! - ## systemd `towerd` loads `/etc/towerd/env` via `EnvironmentFile`. If using Docker for InfluxDB, ensure Docker starts before towerd: @@ -149,3 +148,4 @@ Wants=docker.service ``` Add those lines to `/etc/systemd/system/towerd.service` under `[Unit]`. + diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 7b0925b..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,18 +0,0 @@ -services: - influxdb: - image: influxdb:2.7 - restart: unless-stopped - ports: - - "127.0.0.1:8086:8086" - volumes: - - influx-data:/var/lib/influxdb2 - environment: - DOCKER_INFLUXDB_INIT_MODE: setup - DOCKER_INFLUXDB_INIT_USERNAME: admin - DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_INIT_PASSWORD} - DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_INIT_ORG:-tower} - DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_INIT_BUCKET:-tower} - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_INIT_ADMIN_TOKEN} - -volumes: - influx-data: diff --git a/src/config.rs b/src/config.rs index e11cc24..a400b94 100644 --- a/src/config.rs +++ b/src/config.rs @@ -34,8 +34,8 @@ impl Default for Config { Self { status_pin: 4, fan_pin: 17, - fan_on_temp_c: 40.0, - fan_off_temp_c: 35.0, + fan_on_temp_c: 35.0, + fan_off_temp_c: 30.0, poll_interval_s: 2.0, thermal_alarm_temp_c: 80.0, influx: InfluxConfig::from_env(), diff --git a/src/daemon.rs b/src/daemon.rs index 4dbc66e..5368d1f 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -31,7 +31,7 @@ pub async fn run(config: Config) -> anyhow::Result<()> { result = tasks::status::run(config.status_pin, status_rx) => { result?; } - result = tasks::thermal::run(config.clone(), fan.clone(), alarms.clone()) => { + result = tasks::thermal::run(config.clone(), alarms.clone()) => { result?; } result = async { @@ -44,6 +44,9 @@ pub async fn run(config: Config) -> anyhow::Result<()> { } result = tasks::renogy::run( config.renogy.clone(), + config.fan_on_temp_c, + config.fan_off_temp_c, + fan.clone(), config.influx.clone(), alarms.clone(), ) => { diff --git a/src/tasks/renogy.rs b/src/tasks/renogy.rs index 52c5165..715330f 100644 --- a/src/tasks/renogy.rs +++ b/src/tasks/renogy.rs @@ -8,12 +8,16 @@ use tracing::{debug, info, warn}; use crate::alarm::SharedAlarms; use crate::config::{InfluxConfig, RenogyConfig}; +use crate::gpio::{Fan, SharedFan}; use crate::renogy::{self, Client as RenogyClient, ControllerData, ControllerInfo}; const RECONNECT_INTERVAL_S: f64 = 15.0; pub async fn run( config: RenogyConfig, + fan_on_temp_c: f64, + fan_off_temp_c: f64, + fan: SharedFan, influx: Option, alarms: SharedAlarms, ) -> anyhow::Result<()> { @@ -43,7 +47,16 @@ pub async fn run( continue; }; - match connect_and_poll(&port, &config, influx.as_ref(), &alarms).await { + match connect_and_poll( + &port, + &config, + fan_on_temp_c, + fan_off_temp_c, + &fan, + influx.as_ref(), + &alarms, + ) + .await { Ok(()) => return Ok(()), Err(e) => { alarms.set_fault("renogy", true).await; @@ -57,6 +70,9 @@ pub async fn run( async fn connect_and_poll( port: &str, config: &RenogyConfig, + fan_on_temp_c: f64, + fan_off_temp_c: f64, + fan: &SharedFan, influx: Option<&InfluxConfig>, alarms: &SharedAlarms, ) -> anyhow::Result<()> { @@ -104,13 +120,23 @@ async fn connect_and_poll( // Clear fault alarms.set_fault("renogy", false).await; - // Debug log - debug!( - battery_v = data.battery_voltage, - battery_soc = data.battery_soc, - solar_w = data.solar_watts, - "Renogy poll ok" - ); + { + let mut fan = fan.lock().await; + update_fan( + &mut fan, + fan_on_temp_c, + fan_off_temp_c, + data.controller_temperature_c, + ); + debug!( + battery_v = data.battery_voltage, + battery_soc = data.battery_soc, + controller_temp_c = data.controller_temperature_c, + solar_w = data.solar_watts, + fan = if fan.on() { "on" } else { "off" }, + "Renogy poll ok" + ); + } // Publish data if let (Some(client), Some(influx)) = (&influx_client, influx) { @@ -124,6 +150,25 @@ async fn connect_and_poll( } } +fn update_fan(fan: &mut Fan, on_temp_c: f64, off_temp_c: f64, controller_temp_c: u8) { + let temp_c = f64::from(controller_temp_c); + if !fan.on() && temp_c > on_temp_c { + fan.set_on(true); + info!( + controller_temp_c = temp_c, + threshold = on_temp_c, + "Fan on" + ); + } else if fan.on() && temp_c <= off_temp_c { + fan.set_on(false); + info!( + controller_temp_c = temp_c, + threshold = off_temp_c, + "Fan off" + ); + } +} + // Publish data to InfluxDB async fn publish( client: &InfluxClient, diff --git a/src/tasks/thermal.rs b/src/tasks/thermal.rs index 3672d3d..a1b2e1c 100644 --- a/src/tasks/thermal.rs +++ b/src/tasks/thermal.rs @@ -1,57 +1,26 @@ use std::time::Duration; use tokio::time::MissedTickBehavior; -use tracing::{debug, info}; +use tracing::debug; use crate::alarm::SharedAlarms; use crate::config::Config; -use crate::gpio::{Fan, SharedFan}; use crate::thermal; -pub async fn run(config: Config, fan: SharedFan, alarms: SharedAlarms) -> anyhow::Result<()> { - // Setup the interval for the thermal task +pub async fn run(config: Config, alarms: SharedAlarms) -> anyhow::Result<()> { let mut interval = tokio::time::interval(Duration::from_secs_f64(config.poll_interval_s)); interval.set_missed_tick_behavior(MissedTickBehavior::Skip); - loop { // Main loop + loop { interval.tick().await; - // Read the temperature let temp_c = tokio::task::spawn_blocking(thermal::read_cpu_temp_c) .await??; - // Check if the temperature is over the alarm threshold let over_temp = temp_c >= config.thermal_alarm_temp_c; alarms.set_fault("thermal", over_temp).await; - // Update the fan - let mut fan = fan.lock().await; - update_fan(&mut fan, &config, temp_c); - - // Debug logging - debug!( - temp_c, - fan = if fan.on() { "on" } else { "off" }, - alarm = ?alarms.status(), - ); - } -} - -fn update_fan(fan: &mut Fan, config: &Config, temp_c: f64) { - if !fan.on() && temp_c >= config.fan_on_temp_c { - fan.set_on(true); - info!( - temp_c, - threshold = config.fan_on_temp_c, - "Fan on" - ); - } else if fan.on() && temp_c <= config.fan_off_temp_c { - fan.set_on(false); - info!( - temp_c, - threshold = config.fan_off_temp_c, - "Fan off" - ); + debug!(temp_c, alarm = ?alarms.status()); } } diff --git a/systemd/towerd.service b/systemd/towerd.service index 19ee70f..fe836c2 100644 --- a/systemd/towerd.service +++ b/systemd/towerd.service @@ -1,7 +1,7 @@ [Unit] Description=Tower Daemon -After=multi-user.target docker.service -Wants=docker.service +After=multi-user.target influxdb.service +Wants=influxdb.service [Service] Type=simple