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