Compare commits

...

4 Commits

Author SHA1 Message Date
8ff2763580 add website part of log view 2025-03-20 22:47:39 +01:00
67c653fa8b log webview 2025-03-20 22:47:18 +01:00
9bace8d8c5 fix error when no backup 2025-03-20 22:47:18 +01:00
16756aba94 minor frequency adjustment 2025-03-20 22:47:18 +01:00
7 changed files with 148 additions and 21 deletions

View File

@ -32,7 +32,7 @@ use tank::*;
const TIME_ZONE: Tz = Berlin;
const MOIST_SENSOR_MAX_FREQUENCY: u32 = 5000; // 60kHz (500Hz margin)
const MOIST_SENSOR_MAX_FREQUENCY: u32 = 5500; // 60kHz (500Hz margin)
const MOIST_SENSOR_MIN_FREQUENCY: u32 = 150; // this is really really dry, think like cactus levels
const FROM: (f32, f32) = (

View File

@ -188,7 +188,14 @@ fn backup_info(
};
serde_json::to_string(&wbh)?
}
Err(_) => "{\"error\":\"Header could not be parsed\"".to_owned(),
Err(_) => {
//TODO make better
let wbh = WebBackupHeader {
timestamp: "no backup".to_owned(),
size: 0,
};
serde_json::to_string(&wbh)?
}
};
anyhow::Ok(Some(json))
}

View File

@ -1,3 +1,21 @@
interface LogArray extends Array<LogEntry>{}
interface LogEntry {
timestamp: string,
message_id: number,
a: number,
b: number,
txt_short: string,
txt_long: string
}
interface LogLocalisation extends Array<LogLocalisationEntry>{}
interface LogLocalisationEntry {
msg_type: string,
message: string
}
interface BackupHeader {
timestamp: string,
size: number

View File

@ -0,0 +1,7 @@
<style>
</style>
<button id="loadLog">Load Logs</button>
<div id="logpanel">
</div>

View File

@ -0,0 +1,47 @@
import { Controller } from "./main";
export class LogView {
private readonly logpanel: HTMLElement;
private readonly loadLog: HTMLButtonElement;
loglocale: LogLocalisation | undefined;
constructor(controller: Controller) {
(document.getElementById("logview") as HTMLElement).innerHTML = require('./log.html') as string;
this.logpanel = document.getElementById("logpanel") as HTMLElement
this.loadLog = document.getElementById("loadLog") as HTMLButtonElement
controller.loadLogLocaleConfig();
this.loadLog.onclick = () => {
controller.loadLog();
}
}
setLogLocalisation(loglocale: LogLocalisation) {
this.loglocale = loglocale;
}
setLog(logs: LogArray) {
this.logpanel.textContent = ""
logs.forEach(entry => {
let message = this.loglocale!![entry.message_id];
let template = message.message
template = template.replace("${number_a}", entry.a.toString());
template = template.replace("${number_b}", entry.b.toString());
template = template.replace("${txt_short}", entry.txt_short.toString());
template = template.replace("${txt_long}", entry.txt_long.toString());
let ts = new Date(entry.timestamp);
let div = document.createElement("div")
let timestampDiv = document.createElement("div")
let messageDiv = document.createElement("div")
timestampDiv.innerText = ts.toISOString();
messageDiv.innerText = template;
div.appendChild(timestampDiv)
div.appendChild(messageDiv)
this.logpanel.appendChild(div)
}
)
}
}

View File

@ -171,6 +171,10 @@
<button id="exit">Exit</button>
<button id="reboot">Reboot</button>
<div class="flexcontainer">
<div id="logview" class="subcontainercontainer"></div>
</div>
<script src="bundle.js"></script>
</div>

View File

@ -17,10 +17,33 @@ import { ProgressView } from "./progress";
import { OTAView } from "./ota";
import { BatteryView } from "./batteryview";
import { FileView } from './fileview';
import { LogView } from './log';
export class Controller {
getBackupInfo() {
fetch(PUBLIC_URL + "/backup_info")
loadLogLocaleConfig() {
return fetch(PUBLIC_URL + "/log_localization")
.then(response => response.json())
.then(json => json as LogLocalisation)
.then(loglocale => {
controller.logView.setLogLocalisation(loglocale)
})
.catch(error => {
console.log(error);
});
}
loadLog() {
return fetch(PUBLIC_URL + "/log")
.then(response => response.json())
.then(json => json as LogArray)
.then(logs => {
controller.logView.setLog(logs)
})
.catch(error => {
console.log(error);
});
}
getBackupInfo() : Promise<void> {
return fetch(PUBLIC_URL + "/backup_info")
.then(response => response.json())
.then(json => json as BackupHeader)
.then(header => {
@ -30,8 +53,8 @@ export class Controller {
console.log(error);
});
}
updateFileList() {
fetch(PUBLIC_URL + "/files")
updateFileList() : Promise<void> {
return fetch(PUBLIC_URL + "/files")
.then(response => response.json())
.then(json => json as FileList)
.then(filelist => {
@ -90,8 +113,8 @@ export class Controller {
controller.updateFileList()
}
updateRTCData() {
fetch(PUBLIC_URL + "/time")
updateRTCData() : Promise<void> {
return fetch(PUBLIC_URL + "/time")
.then(response => response.json())
.then(json => json as GetTime)
.then(time => {
@ -102,8 +125,8 @@ export class Controller {
console.log(error);
});
}
updateBatteryData() {
fetch(PUBLIC_URL + "/battery")
updateBatteryData(): Promise<void> {
return fetch(PUBLIC_URL + "/battery")
.then(response => response.json())
.then(json => json as BatteryState)
.then(battery => {
@ -112,7 +135,7 @@ export class Controller {
.catch(error => {
controller.batteryView.update(null)
console.log(error);
});
})
}
uploadNewFirmware(file: File) {
var current = 0;
@ -139,9 +162,9 @@ export class Controller {
ajax.open("POST", PUBLIC_URL + "/ota");
ajax.send(file);
}
version() {
version() : Promise<void> {
controller.progressview.addIndeterminate("version", "Getting buildVersion")
fetch(PUBLIC_URL + "/version")
return fetch(PUBLIC_URL + "/version")
.then(response => response.json())
.then(json => json as VersionInfo)
.then(versionInfo => {
@ -160,9 +183,9 @@ export class Controller {
})
}
downloadConfig() {
downloadConfig() :Promise<void> {
controller.progressview.addIndeterminate("get_config", "Downloading Config")
fetch(PUBLIC_URL + "/get_config")
return fetch(PUBLIC_URL + "/get_config")
.then(response => response.json())
.then(loaded => {
var currentConfig = loaded as PlantControllerConfig;
@ -399,6 +422,7 @@ export class Controller {
readonly progressview: ProgressView;
readonly batteryView: BatteryView;
readonly fileview: FileView;
readonly logView: LogView
constructor() {
this.timeView = new TimeView(this)
this.plantViews = new PlantViews(this)
@ -410,6 +434,7 @@ export class Controller {
this.firmWareView = new OTAView(this)
this.progressview = new ProgressView(this)
this.fileview = new FileView(this)
this.logView = new LogView(this)
this.rebootBtn = document.getElementById("reboot") as HTMLButtonElement
this.rebootBtn.onclick = () => {
controller.reboot();
@ -421,12 +446,31 @@ export class Controller {
}
}
const controller = new Controller();
controller.updateRTCData();
controller.updateBatteryData();
controller.downloadConfig();
controller.progressview.removeProgress("rebooting");
controller.progressview.addProgress("initial", 0, "read rtc");
controller.updateRTCData().then(_ => {
controller.progressview.addProgress("initial", 20, "read battery");
controller.updateBatteryData().then(_ => {
controller.progressview.addProgress("initial", 40, "read config");
controller.downloadConfig().then(_ => {
controller.progressview.addProgress("initial", 50, "read version");
controller.version().then(_ => {
controller.progressview.addProgress("initial", 70, "read filelist");
controller.updateFileList().then(_ => {
controller.progressview.addProgress("initial", 90, "read backupinfo");
controller.getBackupInfo().then(_ => {
controller.progressview.removeProgress("initial");
})
})
})
});
})
})
;
//controller.measure_moisture();
controller.version();
controller.updateFileList();
controller.getBackupInfo();
controller.progressview.removeProgress("rebooting");