optimization

This commit is contained in:
DmitryBorisenko33
2026-02-08 23:38:55 +01:00
parent 710f7b14ae
commit 3ad761e6f2
2 changed files with 76 additions and 131 deletions

View File

@@ -151,7 +151,7 @@ _settings_store: dict = {} # slot -> dict
def get_settings(http_host: str, http_port: int, slot: int = 0) -> dict: def get_settings(http_host: str, http_port: int, slot: int = 0) -> dict:
"""Settings JSON; serverip must point to mock HTTP for ver.json. System page needs timezone, wg, log, mqttin, i2c, pinSCL, pinSDA, i2cFreq.""" """Settings JSON; serverip must point to mock HTTP for ver.json. System page needs timezone, wg, log, mqttin, i2c, pinSCL, pinSDA, i2cFreq."""
base = { base = {
"name": "MockDevice", "name": f"MockDevice-{slot}",
"apssid": "IoTmanager", "apssid": "IoTmanager",
"appass": "", "appass": "",
"routerssid": "", "routerssid": "",
@@ -182,23 +182,25 @@ def get_settings(http_host: str, http_port: int, slot: int = 0) -> dict:
return base return base
def get_errors() -> dict: def get_errors(slot: int = 0) -> dict:
"""Errors JSON for System page: bn, bt, bver, wver, timenow, upt, uptm, uptw, rssi, heap, freeBytes, fl, rst.""" """Errors JSON for System page (per device): bn, bt, bver, wver, timenow, upt, uptm, uptw, rssi, heap, freeBytes, fl, rst."""
import time import time
ts = int(time.time())
# Different system info per device slot so UI shows which device is selected
return { return {
"bn": "esp32", "bn": f"esp32-d{slot}",
"bt": "2024-01-01 12:00", "bt": f"2024-0{1 + slot}-0{1 + slot} 12:00",
"bver": "1.0.0", "bver": f"1.0.{slot}",
"wver": "4.2.0", "wver": f"4.2.{slot}",
"timenow": str(int(time.time())), "timenow": str(ts),
"upt": "1d 02:30", "upt": f"{1 + slot}d 0{2 + slot}:{30 + slot * 5}",
"uptm": "1d 02:30", "uptm": f"{1 + slot}d 0{2 + slot}:{30 + slot * 5}",
"uptw": "1d 02:30", "uptw": f"{1 + slot}d 0{2 + slot}:{30 + slot * 5}",
"rssi": 5, "rssi": -65 + slot * 10,
"heap": "120000", "heap": str(120000 - slot * 10000),
"freeBytes": "2.1M", "freeBytes": f"{2 - slot * 0.2:.1f}M",
"fl": "1024", "fl": str(1024 + slot * 512),
"rst": "Software reset", "rst": "Software reset" if slot == 0 else "Power-on reset",
} }
@@ -360,7 +362,7 @@ async def handle_ws_message(ws, message: str, slot: int) -> None:
await send_bin("config", json.dumps(get_config_json())) await send_bin("config", json.dumps(get_config_json()))
await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot))) await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot)))
await send_bin("ssidli", json.dumps(get_ssid_list())) await send_bin("ssidli", json.dumps(get_ssid_list()))
await send_bin("errors", json.dumps(get_errors())) await send_bin("errors", json.dumps(get_errors(slot)))
return return
if cmd == "/list|": if cmd == "/list|":
@@ -380,12 +382,12 @@ async def handle_ws_message(ws, message: str, slot: int) -> None:
return return
if cmd == "/system|": if cmd == "/system|":
await send_bin("errors", json.dumps(get_errors())) await send_bin("errors", json.dumps(get_errors(slot)))
await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot))) await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot)))
return return
if cmd == "/dev|": if cmd == "/dev|":
await send_bin("errors", json.dumps(get_errors())) await send_bin("errors", json.dumps(get_errors(slot)))
await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot))) await send_bin("settin", json.dumps(get_settings(HTTP_HOST, HTTP_PORT, slot)))
await send_bin("config", json.dumps(get_config_json())) await send_bin("config", json.dumps(get_config_json()))
await send_bin("itemsj", json.dumps(get_items_json())) await send_bin("itemsj", json.dumps(get_items_json()))
@@ -414,7 +416,7 @@ async def handle_ws_message(ws, message: str, slot: int) -> None:
try: try:
data = json.loads(payload) data = json.loads(payload)
_settings_store[slot] = data _settings_store[slot] = data
await send_bin("errors", json.dumps(get_errors())) await send_bin("errors", json.dumps(get_errors(slot)))
except json.JSONDecodeError: except json.JSONDecodeError:
pass pass
return return

View File

@@ -350,39 +350,25 @@ export default class WebSocketManager {
} }
sortingLayout(ws) { sortingLayout(ws) {
this.layoutJson.sort(function (a, b) { this.layoutJson.sort((a, b) => (a.descr || "").localeCompare(b.descr || ""));
if (a.descr < b.descr) return -1; const pageSet = new Set(this.layoutJson.map((w) => w.page));
if (a.descr > b.descr) return 1; this.pages = [...pageSet].sort((a, b) => a.localeCompare(b)).map((page) => ({ page }));
return 0; if (this.debug) console.log("[3]", ws, "layout sort, requested params...");
});
this.pages = [];
const newPage = Array.from(new Set(Array.from(this.layoutJson, ({ page }) => page)));
newPage.forEach(function (item) {
this.pages = [...this.pages, JSON.parse(JSON.stringify({ page: item }))];
}, this);
this.pages.sort(function (a, b) {
if (a.page < b.page) return -1;
if (a.page > b.page) return 1;
return 0;
});
this.layoutJson = this.layoutJson;
console.log("[3]", ws, "layout sort, requested params...");
this.wsSendMsg(ws, "/params|"); this.wsSendMsg(ws, "/params|");
this._emitLayoutJsonUpdated(); this._emitLayoutJsonUpdated();
} }
updateAllStatuses(ws) { updateAllStatuses(ws) {
const topicToIndex = new Map();
for (let i = 0; i < this.layoutJson.length; i++) {
const t = this.layoutJson[i].topic;
if (t) topicToIndex.set(t.slice(t.lastIndexOf("/") + 1), i);
}
for (const [key, value] of Object.entries(this.paramsJson)) { for (const [key, value] of Object.entries(this.paramsJson)) {
for (let i = 0; i < this.layoutJson.length; i++) { const i = topicToIndex.get(key);
let topic = this.layoutJson[i].topic; if (i !== undefined) {
if (topic) { if (this.debug) console.log("[i]", "updated =>" + key, value);
topic = topic.substring(topic.lastIndexOf("/") + 1, topic.length); this.layoutJson[i].status = value;
if (key === topic) {
console.log("[i]", "updated =>" + topic, value);
this.layoutJson[i].status = value;
break;
}
}
} }
} }
this.wsSendMsg(ws, "/charts|"); this.wsSendMsg(ws, "/charts|");
@@ -390,51 +376,35 @@ export default class WebSocketManager {
} }
updateWidget(newStatusJson) { updateWidget(newStatusJson) {
for (let i = 0; i < this.layoutJson.length; i++) { const i = this.layoutJson.findIndex((w) => w.topic === newStatusJson.topic);
if (this.layoutJson[i].topic === newStatusJson.topic) { if (i === -1) return;
this.layoutJson[i] = this.jsonConcat(this.layoutJson[i], newStatusJson); this.jsonConcat(this.layoutJson[i], newStatusJson);
this.layoutJson[i].sent = false; this.layoutJson[i].sent = false;
break;
}
}
this._emitLayoutJsonUpdated(); this._emitLayoutJsonUpdated();
} }
async apdateWidgetByArray(newStatusJson) { apdateWidgetByArray(newStatusJson) {
console.log("[i]", "collecting arrays"); const i = this.layoutJson.findIndex((w) => w.topic === newStatusJson.topic);
let error = true; if (i === -1) {
if (this.layoutJson.length > 0) { if (this.debug) console.log("[E]", "topic not found", newStatusJson.topic);
for (let i = 0; i < this.layoutJson.length; i++) { this._emitLayoutJsonUpdated();
if (this.layoutJson[i].topic === newStatusJson.topic) { return;
error = false;
this.layoutJson[i] = this.jsonConcatEx(this.layoutJson[i], newStatusJson);
let prevArr = this.layoutJson[i].status;
let newArr = newStatusJson.status;
if (prevArr) {
prevArr = [...prevArr, ...newArr];
this.layoutJson[i].status = prevArr;
} else {
this.layoutJson[i].status = newArr;
}
this.layoutJson[i].sent = false;
}
}
} else {
console.log("[E]", "layoutJson missing");
} }
if (error) console.log("[E]", "topic not found ", newStatusJson.topic); this.jsonConcatEx(this.layoutJson[i], newStatusJson);
const prev = this.layoutJson[i].status;
const next = newStatusJson.status;
this.layoutJson[i].status = Array.isArray(prev) ? [...prev, ...(next || [])] : next || [];
this.layoutJson[i].sent = false;
this._emitLayoutJsonUpdated(); this._emitLayoutJsonUpdated();
} }
jsonConcat(o1, o2) { jsonConcat(o1, o2) {
for (const key in o2) { Object.assign(o1, o2);
o1[key] = o2[key];
}
return o1; return o1;
} }
jsonConcatEx(o1, o2) { jsonConcatEx(o1, o2) {
for (const key in o2) { for (const key of Object.keys(o2)) {
if (key !== "status") o1[key] = o2[key]; if (key !== "status") o1[key] = o2[key];
} }
return o1; return o1;
@@ -479,12 +449,7 @@ export default class WebSocketManager {
} }
getSelectedDeviceData(ws) { getSelectedDeviceData(ws) {
for (let i = 0; i < this.deviceList.length; i++) { this.selectedDeviceData = this.deviceList.find((d) => d.ws === ws);
if (this.deviceList[i].ws === ws) {
this.selectedDeviceData = this.deviceList[i];
break;
}
}
} }
selectedDeviceDataRefresh() { selectedDeviceDataRefresh() {
@@ -493,18 +458,14 @@ export default class WebSocketManager {
} }
wsPush(ws, topic, status) { wsPush(ws, topic, status) {
const key = topic.substring(topic.lastIndexOf("/") + 1, topic.length); const key = topic.slice(topic.lastIndexOf("/") + 1);
this.wsSendMsg(ws, "/control|" + key + "/" + status); this.wsSendMsg(ws, "/control|" + key + "/" + status);
} }
addCoreMsg(msg) { addCoreMsg(msg) {
if (this.coreMessages.length >= LOG_MAX_MESSAGES) this.coreMessages.shift(); if (this.coreMessages.length >= LOG_MAX_MESSAGES) this.coreMessages.shift();
this.coreMessages = [...this.coreMessages, { msg }]; this.coreMessages.push({ msg, time: Date.now() });
this.coreMessages.sort(function (a, b) { this.coreMessages.sort((a, b) => (b.time || 0) - (a.time || 0));
if (a.time > b.time) return -1;
if (a.time < b.time) return 1;
return 0;
});
} }
_getInput() { _getInput() {
@@ -524,48 +485,30 @@ export default class WebSocketManager {
} }
generateLayout() { generateLayout() {
const { mqttPrefix = "", id: settingsId = "" } = this.settingsJson;
const prefix = `${mqttPrefix}/${settingsId}/`;
const layout = []; const layout = [];
for (let i = 0; i < this.configJson.length; i++) { for (const config of this.configJson) {
const config = Object.assign({}, this.configJson[i]); const widget = this.widgetsJson.find((w) => w.name === config.widget);
const setWidget = config.widget; if (!widget) {
let error = true; if (this.debug) console.log("[E]", "widget not found:", config.widget);
for (let w = 0; w < this.widgetsJson.length; w++) { continue;
if (setWidget === this.widgetsJson[w].name) { }
const widget = Object.assign({}, this.widgetsJson[w]); if (config.widget !== "nil") {
widget.page = config.page; const item = { ...widget, page: config.page, descr: config.descr, topic: prefix + config.id };
widget.descr = config.descr; layout.push(item);
widget.topic = if (item.widget === "chart" && item.type !== "bar") {
this.settingsJson.mqttPrefix + "/" + this.settingsJson.id + "/" + config.id; layout.push({
if (setWidget !== "nil") layout.push(widget); ...this._getInput(),
if (widget.widget === "chart" && widget.type !== "bar") { page: config.page,
const input = this._getInput(); descr: config.descr,
input.page = config.page; topic: prefix + config.id + "-date",
input.topic = });
this.settingsJson.mqttPrefix +
"/" +
this.settingsJson.id +
"/" +
config.id +
"-date";
input.descr = config.descr;
layout.push(input);
}
error = false;
break;
} else {
error = true;
} }
} }
if (error) console.log("[E]", "error, widget not found: " + setWidget);
}
layout.sort(function (a, b) {
if (a.descr < b.descr) return -1;
if (a.descr > b.descr) return 1;
return 0;
});
for (let i = 0; i < layout.length; i++) {
layout[i].order = i;
} }
layout.sort((a, b) => (a.descr || "").localeCompare(b.descr || ""));
layout.forEach((item, i) => (item.order = i));
return layout; return layout;
} }