progress new ui
This commit is contained in:
parent
74f9c17461
commit
5fedbec433
@ -258,7 +258,7 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
Err(err) => {
|
||||
println!("Missing normal config, entering config mode {}", err);
|
||||
//config upload will trigger reboot!
|
||||
let _ = board.wifi_ap();
|
||||
let _ = board.wifi_ap(Option::None);
|
||||
drop(board);
|
||||
let reboot_now = Arc::new(AtomicBool::new(false));
|
||||
let _webserver = httpd(reboot_now.clone());
|
||||
@ -293,6 +293,7 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
board.general_fault(true);
|
||||
}
|
||||
}
|
||||
if (config.network.mqtt_url.is_some()){
|
||||
match board.mqtt(&config) {
|
||||
Ok(_) => {
|
||||
println!("Mqtt connection ready");
|
||||
@ -303,6 +304,7 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Offline mode");
|
||||
board.general_fault(true);
|
||||
@ -312,6 +314,16 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
println!("No wifi configured");
|
||||
}
|
||||
|
||||
if !wifi && to_config {
|
||||
println!("Could not connect to station and config mode forced, switching to ap mode!");
|
||||
match board.wifi_ap(Some(config.network.ap_ssid.clone())) {
|
||||
Ok(_) => {
|
||||
println!("Started ap, continuing")
|
||||
},
|
||||
Err(err) => println!("Could not start config override ap mode due to {}", err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
let timezone_time = cur.with_timezone(&TIME_ZONE);
|
||||
println!(
|
||||
"Running logic at utc {} and {} {}",
|
||||
|
@ -514,9 +514,10 @@ impl PlantCtrlBoard<'_> {
|
||||
unsafe { gpio_hold_en(self.general_fault.pin()) };
|
||||
}
|
||||
|
||||
pub fn wifi_ap(&mut self) -> Result<()> {
|
||||
pub fn wifi_ap(&mut self, ap_ssid: Option<heapless::String<32>>) -> Result<()> {
|
||||
let ssid = ap_ssid.unwrap_or(heapless::String::from_str("PlantCtrl Emergency Mode").unwrap());
|
||||
let apconfig = AccessPointConfiguration {
|
||||
ssid: heapless::String::from_str("PlantCtrl").unwrap(),
|
||||
ssid,
|
||||
auth_method: AuthMethod::None,
|
||||
ssid_hidden: false,
|
||||
..Default::default()
|
||||
@ -643,6 +644,7 @@ impl PlantCtrlBoard<'_> {
|
||||
}
|
||||
|
||||
pub fn get_rtc_time(&mut self) -> Result<DateTime<Utc>> {
|
||||
|
||||
match self.rtc.datetime() {
|
||||
OkStd(rtc_time) => {
|
||||
return Ok(rtc_time.and_utc());
|
||||
@ -743,11 +745,18 @@ impl PlantCtrlBoard<'_> {
|
||||
.base_topic
|
||||
.as_ref()
|
||||
.context("missing base topic")?;
|
||||
if base_topic.is_empty() {
|
||||
bail!("Mqtt base_topic was empty")
|
||||
}
|
||||
let mqtt_url = config
|
||||
.network
|
||||
.mqtt_url
|
||||
.as_ref()
|
||||
.context("missing mqtt url")?;
|
||||
if mqtt_url.is_empty() {
|
||||
bail!("Mqtt url was empty")
|
||||
}
|
||||
|
||||
|
||||
let last_will_topic = format!("{}/state", base_topic);
|
||||
let mqtt_client_config = MqttClientConfiguration {
|
||||
@ -805,26 +814,41 @@ impl PlantCtrlBoard<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
embedded_svc::mqtt::client::EventPayload::Connected(_) => {
|
||||
esp_idf_svc::mqtt::client::EventPayload::Connected(_) => {
|
||||
mqtt_connected_event_received_copy
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
mqtt_connected_event_ok_copy.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
println!("Mqtt connected");
|
||||
}
|
||||
embedded_svc::mqtt::client::EventPayload::Disconnected => {
|
||||
esp_idf_svc::mqtt::client::EventPayload::Disconnected => {
|
||||
mqtt_connected_event_received_copy
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
mqtt_connected_event_ok_copy.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
println!("Mqtt disconnected");
|
||||
}
|
||||
embedded_svc::mqtt::client::EventPayload::Error(esp_error) => {
|
||||
esp_idf_svc::mqtt::client::EventPayload::Error(esp_error) => {
|
||||
println!("EspMqttError reported {:?}", esp_error);
|
||||
mqtt_connected_event_received_copy
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
mqtt_connected_event_ok_copy.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
println!("Mqtt error");
|
||||
}
|
||||
_ => {}
|
||||
esp_idf_svc::mqtt::client::EventPayload::BeforeConnect => {
|
||||
println!("Mqtt before connect")
|
||||
},
|
||||
esp_idf_svc::mqtt::client::EventPayload::Subscribed(_) => {
|
||||
println!("Mqtt subscribed")
|
||||
},
|
||||
esp_idf_svc::mqtt::client::EventPayload::Unsubscribed(_) => {
|
||||
println!("Mqtt unsubscribed")
|
||||
},
|
||||
esp_idf_svc::mqtt::client::EventPayload::Published(_) => {
|
||||
println!("Mqtt published")
|
||||
},
|
||||
esp_idf_svc::mqtt::client::EventPayload::Deleted(_) => {
|
||||
println!("Mqtt deleted")
|
||||
},
|
||||
|
||||
}
|
||||
})?;
|
||||
|
||||
|
@ -24,7 +24,7 @@ interface TankConfig {
|
||||
interface PlantControllerConfig {
|
||||
network: NetworkConfig,
|
||||
tank: TankConfig,
|
||||
nightLamp: NightLampConfig,
|
||||
night_lamp: NightLampConfig,
|
||||
plants: PlantConfig[]
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<div id="remote_ip">remote ip</div>
|
||||
<h2>WIFI</h2>
|
||||
<input type="button" id="scan" value="Scan">
|
||||
<br>
|
||||
@ -52,12 +53,12 @@
|
||||
<div id="configform">
|
||||
<h3>Mqtt:</h3>
|
||||
<div>
|
||||
<input type="text" id="mqtt_url">
|
||||
MQTT Url
|
||||
<input type="text" id="mqtt_url" placeholder="mqtt://192.168.1.1:1883">
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" id="base_topic">
|
||||
Base Topic
|
||||
<input type="text" id="base_topic" placeholder="plants/one">
|
||||
</div>
|
||||
|
||||
|
||||
@ -114,13 +115,6 @@
|
||||
</form>
|
||||
|
||||
<h3>Plants:</h3>
|
||||
|
||||
|
||||
<div>
|
||||
<input type="number" min="2" max="100" id="max_consecutive_pump_count">
|
||||
Max consecutive pump count:
|
||||
</div>
|
||||
|
||||
<div id="plants"></div>
|
||||
</div>
|
||||
<button id="submit">Submit</button>
|
||||
|
@ -10,18 +10,59 @@ import { NightLampView } from "./nightmode";
|
||||
import { TankConfigView } from "./tanks";
|
||||
|
||||
|
||||
export class SubmitView{
|
||||
json: HTMLInputElement;
|
||||
submitFormBtn: HTMLButtonElement;
|
||||
submit_status: HTMLElement;
|
||||
|
||||
constructor(controller: Controller){
|
||||
this.json = document.getElementById('json') as HTMLInputElement
|
||||
this.submitFormBtn = document.getElementById("submit") as HTMLButtonElement
|
||||
this.submit_status = document.getElementById("submit_status") as HTMLElement
|
||||
this.submitFormBtn.onclick = () => {
|
||||
controller.uploadConfig(this.json.value, (status:string) => {
|
||||
this.submit_status.innerHTML = status;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setJson(pretty: string) {
|
||||
this.json.value = pretty
|
||||
}
|
||||
}
|
||||
|
||||
export class Controller {
|
||||
downloadConfig() {
|
||||
fetch(PUBLIC_URL + "/get_config")
|
||||
.then(response => response.json())
|
||||
.then(loaded => {
|
||||
var currentConfig = loaded as PlantControllerConfig;
|
||||
this.setConfig(currentConfig);
|
||||
//sync json view initially
|
||||
this.configChanged();
|
||||
})
|
||||
}
|
||||
uploadConfig(json: string, statusCallback: (status: string) => void) {
|
||||
fetch(PUBLIC_URL + "/set_config", {
|
||||
method: "POST",
|
||||
body: json,
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(text => statusCallback(text))
|
||||
}
|
||||
readonly timeView: TimeView;
|
||||
readonly plantViews: PlantViews;
|
||||
readonly networkView: NetworkConfigView;
|
||||
readonly tankView: TankConfigView;
|
||||
readonly nightLampView: NightLampView;
|
||||
readonly submitView: SubmitView;
|
||||
constructor() {
|
||||
this.timeView = new TimeView(this)
|
||||
this.plantViews = new PlantViews(this)
|
||||
this.networkView = new NetworkConfigView(this)
|
||||
this.networkView = new NetworkConfigView(this, PUBLIC_URL)
|
||||
this.tankView = new TankConfigView(this)
|
||||
this.nightLampView = new NightLampView(this)
|
||||
this.submitView = new SubmitView(this)
|
||||
}
|
||||
|
||||
syncRTCFromBrowser(){
|
||||
@ -36,7 +77,10 @@ export class Controller {
|
||||
}
|
||||
|
||||
configChanged() {
|
||||
updateJson()
|
||||
const current = controller.getConfig();
|
||||
var pretty = JSON.stringify(current, undefined, 1);
|
||||
console.log(pretty)
|
||||
controller.submitView.setJson(pretty);
|
||||
}
|
||||
|
||||
testPlant(plantId: number) {
|
||||
@ -72,7 +116,7 @@ export class Controller {
|
||||
return {
|
||||
network: controller.networkView.getConfig(),
|
||||
tank: controller.tankView.getConfig(),
|
||||
nightLamp: controller.nightLampView.getConfig(),
|
||||
night_lamp: controller.nightLampView.getConfig(),
|
||||
plants: controller.plantViews.getConfig()
|
||||
}
|
||||
}
|
||||
@ -95,60 +139,13 @@ export class Controller {
|
||||
setConfig(current: PlantControllerConfig) {
|
||||
this.tankView.setConfig(current.tank);
|
||||
this.networkView.setConfig(current.network);
|
||||
this.nightLampView.setConfig(current.nightLamp);
|
||||
this.nightLampView.setConfig(current.night_lamp);
|
||||
this.plantViews.setConfig(current.plants);
|
||||
}
|
||||
}
|
||||
|
||||
const controller = new Controller();
|
||||
setTimeout(controller.updateRealTimeData, 1000);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function updateJson() {
|
||||
const current = controller.getConfig();
|
||||
|
||||
console.log(current);
|
||||
|
||||
var pretty = JSON.stringify(current, undefined, 1);
|
||||
console.log(pretty)
|
||||
}
|
||||
|
||||
let fromWrapper = (() => {
|
||||
let json = document.getElementById('json') as HTMLInputElement
|
||||
let submitFormBtn = document.getElementById("submit") as HTMLButtonElement
|
||||
let submit_status = document.getElementById("submit_status") as HTMLElement
|
||||
|
||||
if (submitFormBtn) {
|
||||
|
||||
submitFormBtn.onclick = function () {
|
||||
updateJson()
|
||||
fetch(PUBLIC_URL + "/set_config", {
|
||||
method: "POST",
|
||||
body: json.value,
|
||||
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(text => submit_status.innerText = text)
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
fetch(PUBLIC_URL + "/get_config")
|
||||
.then(response => response.json())
|
||||
.then(loaded => {
|
||||
var currentConfig = loaded as PlantControllerConfig;
|
||||
controller.setConfig(currentConfig);
|
||||
var pretty = JSON.stringify(currentConfig, undefined, 1);
|
||||
json.value = pretty;
|
||||
}
|
||||
)
|
||||
})
|
||||
fromWrapper()
|
||||
controller.downloadConfig();
|
||||
|
||||
|
||||
|
||||
|
@ -16,7 +16,9 @@ export class NetworkConfigView {
|
||||
private readonly base_topic: HTMLInputElement;
|
||||
private readonly ssidlist: HTMLElement;
|
||||
|
||||
constructor(controller: Controller) {
|
||||
constructor(controller: Controller, publicIp: string) {
|
||||
(document.getElementById("remote_ip") as HTMLElement).innerText = publicIp;
|
||||
|
||||
this.ap_ssid = (document.getElementById("ap_ssid") as HTMLInputElement);
|
||||
this.ap_ssid.onchange = controller.configChanged
|
||||
|
||||
@ -48,10 +50,10 @@ export class NetworkConfigView {
|
||||
getConfig(): NetworkConfig {
|
||||
return {
|
||||
ap_ssid: this.ap_ssid.value,
|
||||
ssid: this.ssid.value,
|
||||
password: this.password.value,
|
||||
mqtt_url: this.mqtt_url.value,
|
||||
base_topic: this.base_topic.value
|
||||
ssid: this.ssid.value ?? null,
|
||||
password: this.password.value ?? null,
|
||||
mqtt_url: this.mqtt_url.value ?? null,
|
||||
base_topic: this.base_topic.value ?? null
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
|
||||
declare const PLANT_COUNT = 8;
|
||||
const PLANT_COUNT = 8;
|
||||
|
||||
|
||||
import { Controller } from ".";
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Controller } from ".";
|
||||
|
||||
export class TankConfigView {
|
||||
private readonly max_consecutive_pump_count: HTMLInputElement;
|
||||
private readonly tank_useable_ml: HTMLInputElement;
|
||||
private readonly tank_empty_percent: HTMLInputElement;
|
||||
private readonly tank_full_percent: HTMLInputElement;
|
||||
@ -10,8 +9,6 @@ export class TankConfigView {
|
||||
private readonly tank_allow_pumping_if_sensor_error: HTMLInputElement;
|
||||
|
||||
constructor(controller:Controller){
|
||||
this.max_consecutive_pump_count = document.getElementById("max_consecutive_pump_count") as HTMLInputElement;
|
||||
this.max_consecutive_pump_count.onchange = controller.configChanged
|
||||
this.tank_useable_ml = document.getElementById("tank_useable_ml") as HTMLInputElement;
|
||||
this.tank_useable_ml.onchange = controller.configChanged
|
||||
this.tank_empty_percent = document.getElementById("tank_empty_percent") as HTMLInputElement;
|
||||
|
@ -6,7 +6,7 @@ const isDevServer = process.env.WEBPACK_SERVE;
|
||||
console.log("Dev server is " + isDevServer);
|
||||
var host;
|
||||
if (isDevServer){
|
||||
host = 'http://10.23.43.24';
|
||||
host = 'http://192.168.1.172';
|
||||
} else {
|
||||
host = '';
|
||||
}
|
||||
@ -36,7 +36,7 @@ module.exports = {
|
||||
rules: [
|
||||
{
|
||||
test: /\.html$/,
|
||||
type: 'asset/source'
|
||||
type: 'asset/source',
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
|
Loading…
Reference in New Issue
Block a user