feat: add fertilizer pump test functionality with web integration and HAL support

This commit is contained in:
2026-04-30 20:37:07 +02:00
parent 542ff578bc
commit 0ca09ed498
7 changed files with 43 additions and 2 deletions

View File

@@ -164,6 +164,7 @@ pub trait BoardInteraction<'a> {
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<()>; async fn can_power(&mut self, state: bool) -> FatResult<()>;
async fn extra2(&mut self, enable: bool) -> FatResult<()>;
async fn backup_config(&mut self, config: &PlantControllerConfig) -> FatResult<()>; async fn backup_config(&mut self, config: &PlantControllerConfig) -> FatResult<()>;
async fn read_backup(&mut self) -> FatResult<PlantControllerConfig>; async fn read_backup(&mut self) -> FatResult<PlantControllerConfig>;

View File

@@ -484,6 +484,15 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
Ok(()) Ok(())
} }
async fn extra2(&mut self, enable: bool) -> FatResult<()> {
if enable {
self.extra2.set_high();
} else {
self.extra2.set_low();
}
Ok(())
}
async fn backup_config(&mut self, controller_config: &PlantControllerConfig) -> FatResult<()> { async fn backup_config(&mut self, controller_config: &PlantControllerConfig) -> FatResult<()> {
let mut buffer: [u8; 4096 - BACKUP_HEADER_MAX_SIZE] = [0; 4096 - BACKUP_HEADER_MAX_SIZE]; let mut buffer: [u8; 4096 - BACKUP_HEADER_MAX_SIZE] = [0; 4096 - BACKUP_HEADER_MAX_SIZE];
let length = postcard::to_slice(controller_config, &mut buffer)?.len(); let length = postcard::to_slice(controller_config, &mut buffer)?.len();

View File

@@ -17,8 +17,8 @@ use crate::webserver::get_log::{get_live_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, board_test, can_power, detect_sensors, fertilizer_pump_test, night_lamp_test, pump_test,
write_time, set_config, wifi_scan, write_time,
}; };
use crate::{bail, BOARD_ACCESS}; use crate::{bail, BOARD_ACCESS};
use alloc::borrow::ToOwned; use alloc::borrow::ToOwned;
@@ -116,6 +116,7 @@ impl Handler for HTTPRequestRouter {
"/pumptest" => Some(pump_test(conn).await), "/pumptest" => Some(pump_test(conn).await),
"/can_power" => Some(can_power(conn).await), "/can_power" => Some(can_power(conn).await),
"/lamptest" => Some(night_lamp_test(conn).await), "/lamptest" => Some(night_lamp_test(conn).await),
"/fertilizerpumptest" => Some(fertilizer_pump_test(conn).await),
"/boardtest" => Some(board_test().await), "/boardtest" => Some(board_test().await),
"/detect_sensors" => Some(detect_sensors(conn).await), "/detect_sensors" => Some(detect_sensors(conn).await),
"/reboot" => { "/reboot" => {

View File

@@ -102,6 +102,19 @@ where
Ok(None) Ok(None)
} }
pub(crate) async fn fertilizer_pump_test<T, const N: usize>(
_request: &mut Connection<'_, T, N>,
) -> FatResult<Option<String>>
where
T: Read + Write,
{
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.extra2(true).await?;
embassy_time::Timer::after_millis(1000).await;
board.board_hal.extra2(false).await?;
Ok(None)
}
pub(crate) async fn write_time<T, const N: usize>( pub(crate) async fn write_time<T, const N: usize>(
request: &mut Connection<'_, T, N>, request: &mut Connection<'_, T, N>,
) -> FatResult<Option<String>> ) -> FatResult<Option<String>>

View File

@@ -22,3 +22,8 @@
<div class="boardkey">Pump corrosion protection (weekly)</div> <div class="boardkey">Pump corrosion protection (weekly)</div>
<input type="checkbox" id="hardware_pump_corrosion_protection"> <input type="checkbox" id="hardware_pump_corrosion_protection">
</div> </div>
<div class="subtitle">Fertilizer Pump:</div>
<div class="flexcontainer">
<button class="subtitle" id="fertilizer_pump_test">Test Fertilizer Pump</button>
</div>

View File

@@ -5,6 +5,7 @@ export class HardwareConfigView {
private readonly hardware_board_value: HTMLSelectElement; private readonly hardware_board_value: HTMLSelectElement;
private readonly hardware_battery_value: HTMLSelectElement; private readonly hardware_battery_value: HTMLSelectElement;
private readonly hardware_pump_corrosion_protection: HTMLInputElement; private readonly hardware_pump_corrosion_protection: HTMLInputElement;
private readonly fertilizer_pump_test: HTMLButtonElement;
constructor(controller:Controller){ constructor(controller:Controller){
(document.getElementById("hardwareview") as HTMLElement).innerHTML = require('./hardware.html') as string; (document.getElementById("hardwareview") as HTMLElement).innerHTML = require('./hardware.html') as string;
@@ -33,6 +34,11 @@ export class HardwareConfigView {
this.hardware_pump_corrosion_protection = document.getElementById("hardware_pump_corrosion_protection") as HTMLInputElement; this.hardware_pump_corrosion_protection = document.getElementById("hardware_pump_corrosion_protection") as HTMLInputElement;
this.hardware_pump_corrosion_protection.onchange = controller.configChanged this.hardware_pump_corrosion_protection.onchange = controller.configChanged
this.fertilizer_pump_test = document.getElementById("fertilizer_pump_test") as HTMLButtonElement;
this.fertilizer_pump_test.onclick = () => {
controller.testFertilizerPump();
}
} }
setConfig(hardware: BoardHardware) { setConfig(hardware: BoardHardware) {

View File

@@ -304,6 +304,12 @@ export class Controller {
}) })
} }
testFertilizerPump() {
fetch(PUBLIC_URL + "/fertilizerpumptest", {
method: "POST"
})
}
testPlant(plantId: number) { testPlant(plantId: number) {
let counter = 0 let counter = 0
let limit = 30 let limit = 30