update: refactor and enhance CAN sensor initialization, reorganize GPIO assignments, improve error detection and logging, and streamline TWAI handling

This commit is contained in:
2026-01-31 00:06:42 +01:00
parent 355388aa62
commit ce10d084f8
8 changed files with 70 additions and 16 deletions

View File

@@ -140,4 +140,8 @@ impl<'a> BoardInteraction<'a> for Initial<'a> {
async fn get_mptt_current(&mut self) -> Result<Current, FatError> { async fn get_mptt_current(&mut self) -> Result<Current, FatError> {
bail!("Please configure board revision") bail!("Please configure board revision")
} }
async fn can_power(&mut self, state: bool) -> FatResult<()> {
bail!("Please configure board revision")
}
} }

View File

@@ -162,6 +162,7 @@ pub trait BoardInteraction<'a> {
fn set_config(&mut self, config: PlantControllerConfig); fn set_config(&mut self, config: PlantControllerConfig);
async fn get_mptt_voltage(&mut self) -> FatResult<Voltage>; async fn get_mptt_voltage(&mut self) -> FatResult<Voltage>;
async fn get_mptt_current(&mut self) -> FatResult<Current>; async fn get_mptt_current(&mut self) -> FatResult<Current>;
async fn can_power(&mut self, state: bool) -> FatResult<()>;
// Return JSON string with autodetected sensors per plant. Default: not supported. // Return JSON string with autodetected sensors per plant. Default: not supported.
async fn detect_sensors(&mut self) -> FatResult<DetectionResult> { async fn detect_sensors(&mut self) -> FatResult<DetectionResult> {

View File

@@ -387,22 +387,13 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
let mut twai = create_twai(); let mut twai = create_twai();
loop {
let rec = twai.receive();
match rec {
Ok(_) => {}
Err(err) => {
info!("Error receiving CAN message: {err:?}");
break;
}
}
}
Timer::after_millis(10).await; Timer::after_millis(10).await;
let mut moistures = Moistures::default(); let mut moistures = Moistures::default();
let _ = wait_for_can_measurements(&mut twai, &mut moistures) let _ = wait_for_can_measurements(&mut twai, &mut moistures)
.with_timeout(Duration::from_millis(2000)) .with_timeout(Duration::from_millis(5000))
.await; .await;
teardown_twai(twai); teardown_twai(twai);
self.can_power.set_low(); self.can_power.set_low();
@@ -413,7 +404,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
self.can_power.set_high(); self.can_power.set_high();
let mut twai = create_twai(); let mut twai = create_twai();
// Give CAN some time to stabilize // Give CAN some time to stabilize
Timer::after_millis(10).await; Timer::after_millis(3000).await;
info!("Sending info messages now"); info!("Sending info messages now");
// Send a few test messages per potential sensor node // Send a few test messages per potential sensor node
@@ -522,6 +513,17 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
async fn get_mptt_current(&mut self) -> FatResult<Current> { async fn get_mptt_current(&mut self) -> FatResult<Current> {
self.charger.get_mppt_current() self.charger.get_mppt_current()
} }
async fn can_power(&mut self, state: bool) -> FatResult<()> {
if state && self.can_power.is_set_low(){
self.can_power.set_high();
create_twai();
} else {
teardown_twai(create_twai());
self.can_power.set_low();
}
Ok(())
}
} }

View File

@@ -18,9 +18,7 @@ use crate::webserver::get_json::{
use crate::webserver::get_log::get_log; use crate::webserver::get_log::get_log;
use crate::webserver::get_static::{serve_bundle, serve_favicon, serve_index}; use crate::webserver::get_static::{serve_bundle, serve_favicon, serve_index};
use crate::webserver::ota::ota_operations; use crate::webserver::ota::ota_operations;
use crate::webserver::post_json::{ use crate::webserver::post_json::{board_test, can_power, detect_sensors, night_lamp_test, pump_test, set_config, wifi_scan, write_time};
board_test, detect_sensors, night_lamp_test, pump_test, set_config, wifi_scan, write_time,
};
use crate::{bail, BOARD_ACCESS}; use crate::{bail, BOARD_ACCESS};
use alloc::borrow::ToOwned; use alloc::borrow::ToOwned;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
@@ -103,6 +101,7 @@ impl Handler for HTTPRequestRouter {
"/time" => Some(write_time(conn).await), "/time" => Some(write_time(conn).await),
"/backup_config" => Some(backup_config(conn).await), "/backup_config" => Some(backup_config(conn).await),
"/pumptest" => Some(pump_test(conn).await), "/pumptest" => Some(pump_test(conn).await),
"/can_power" => Some(can_power(conn).await),
"/lamptest" => Some(night_lamp_test(conn).await), "/lamptest" => Some(night_lamp_test(conn).await),
"/boardtest" => Some(board_test().await), "/boardtest" => Some(board_test().await),
"/detect_sensors" => Some(detect_sensors().await), "/detect_sensors" => Some(detect_sensors().await),

View File

@@ -29,6 +29,11 @@ pub struct TestPump {
pump: usize, pump: usize,
} }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct CanPower {
state: bool,
}
pub(crate) async fn wifi_scan<T, const N: usize>( pub(crate) async fn wifi_scan<T, const N: usize>(
_request: &mut Connection<'_, T, N>, _request: &mut Connection<'_, T, N>,
) -> FatResult<Option<String>> { ) -> FatResult<Option<String>> {
@@ -117,3 +122,22 @@ where
board.board_hal.set_config(config); board.board_hal.set_config(config);
Ok(Some("Ok".to_string())) Ok(Some("Ok".to_string()))
} }
pub(crate) async fn can_power<T, const N: usize>(
request: &mut Connection<'_, T, N>,
) -> FatResult<Option<String>>
where
T: Read + Write,
{
let actual_data = read_up_to_bytes_from_request(request, None).await?;
let pump_test: CanPower = serde_json::from_slice(&actual_data)?;
let mut board = BOARD_ACCESS.get().await.lock().await;
let config = &board.board_hal.can_power(pump_test.state).await?;
let enable = pump_test.state;
info!(
"set can power to {enable}"
);
Ok(None)
}

View File

@@ -141,6 +141,10 @@ export interface TestPump {
pump: number pump: number
} }
export interface CanPower {
state: boolean
}
export interface SetTime { export interface SetTime {
time: string time: string
} }

View File

@@ -164,6 +164,7 @@
<h3>Plants:</h3> <h3>Plants:</h3>
<button id="measure_moisture">Measure Moisture</button> <button id="measure_moisture">Measure Moisture</button>
<button id="detect_sensors" style="display:none">Detect/Test Sensors</button> <button id="detect_sensors" style="display:none">Detect/Test Sensors</button>
<input id="can_power" type="checkbox">Power CAN</input>
<div id="plants" class="plantlist"></div> <div id="plants" class="plantlist"></div>
<div class="flexcontainer-rev"> <div class="flexcontainer-rev">

View File

@@ -29,7 +29,7 @@ import {
SetTime, SSIDList, TankInfo, SetTime, SSIDList, TankInfo,
TestPump, TestPump,
VersionInfo, VersionInfo,
FileList, SolarState, PumpTestResult, DetectionResult FileList, SolarState, PumpTestResult, DetectionResult, CanPower
} from "./api"; } from "./api";
import {SolarView} from "./solarview"; import {SolarView} from "./solarview";
import {toast} from "./toast"; import {toast} from "./toast";
@@ -527,6 +527,18 @@ export class Controller {
setTimeout(this.waitForReboot, 1000) setTimeout(this.waitForReboot, 1000)
} }
private setCanPower(checked: boolean) {
var body: CanPower = {
state : checked
}
var pretty = JSON.stringify(body, undefined, 1);
fetch(PUBLIC_URL + "/can_power", {
method: "POST",
body: pretty
})
}
initialConfig: PlantControllerConfig | null = null initialConfig: PlantControllerConfig | null = null
readonly rebootBtn: HTMLButtonElement readonly rebootBtn: HTMLButtonElement
readonly exitBtn: HTMLButtonElement readonly exitBtn: HTMLButtonElement
@@ -544,6 +556,7 @@ export class Controller {
readonly fileview: FileView; readonly fileview: FileView;
readonly logView: LogView readonly logView: LogView
readonly detectBtn: HTMLButtonElement readonly detectBtn: HTMLButtonElement
readonly can_power: HTMLInputElement;
constructor() { constructor() {
this.timeView = new TimeView(this) this.timeView = new TimeView(this)
@@ -569,9 +582,15 @@ export class Controller {
this.exitBtn.onclick = () => { this.exitBtn.onclick = () => {
controller.exit(); controller.exit();
} }
this.can_power = document.getElementById("can_power") as HTMLInputElement
this.can_power.onchange = () => {
controller.setCanPower(this.can_power.checked);
} }
} }
}
const controller = new Controller(); const controller = new Controller();
controller.progressview.removeProgress("rebooting"); controller.progressview.removeProgress("rebooting");