Javascript cleanup

This commit is contained in:
2026-03-04 12:03:39 +01:00
parent 56b9d04cf8
commit 627790b5fc
7 changed files with 31 additions and 303 deletions

8
README
View File

@@ -149,16 +149,16 @@ Bill of materials (WIP)
1x buzzer 12V, passive
1x MOSFET 2N7000
1x resistor 150 Ω
1x wiring set for buttons, 0.25 mm², 15cm each
8x black (GND)
7x colored (signal)
1x wiring set for buttons, 0.25 mm²
7x black (GND), 10cm each
7x colored (signal), 15cm each
1x screw terminal block 2pol. 2.54mm
1x 3D enclosure consisting of front and back
1x nut tool, 3D-printed
4x mounting screws M4 countersunk
4x enclosure screws M2.5, long
8x PCB screws M2.5, short
1x silicone sealing cord 2 mm
1x silicone sealing cord 2 mm, l=380mm
1x SHT31 I²C module
1x female header 2.54 mm
1x pin header 2.54mm

View File

@@ -157,22 +157,22 @@ Bauteilliste (WIP)
1x Buzzer 12V, passiv
1x MOSFET 2N7000
1x Widerstand 150 Ω
1x Kabelsatz für Tasten, 0,25 mm², je 15cm lang
8x schwarz (GND)
7x farbig (Signal)
1x Kabelsatz für Tasten, 0,25 mm²
7x schwarz (GND), je 10cm lang
7x farbig (Signal), je 15cm lang
1x Terminalblock 2pol. 2,54mm schraubbar
1x 3D-Gehäuse bestehend auf Front- und Rückseite
1x Mutternwerkzeug 3D-Druck
4x Befestigungsschraube M4 Senkkopf
4x Gehäuseschraube M2,5, lang
8x Platinenschraube M2,5, kurz
1x Silikondichtschnur 2mm
1x Silikondichtschnur 2mm, l=380mm
1x SHT31 I²C-Modul
1x Buchsenleiste 2,54 mm
1x Stiftleiste 2,54mm
2x Jumper
1x Polyfuse
1x Schrumpfschlauch
1x Schrumpfschlauch
Konfiguration
-------------

View File

@@ -53,6 +53,15 @@ def postbuild(source, target, env):
firmware = env.subst("$BUILD_DIR/${PROGNAME}.bin")
(fwname, fwversion) = getFirmwareInfo(firmware)
pcbvers = "unknown"
for x in env["BUILD_FLAGS"]:
if not x.startswith('-D'):
continue
opt = x[2:].strip()
if opt.startswith("HARDWARE_"):
pcbvers = x.split('_')[1].lower()
print(f"compiled for pcb version {pcbvers}")
esptool = env.get('UPLOADER')
uploaderflags = env.subst("${UPLOADERFLAGS}")
base = env.subst("$PIOENV")
@@ -91,9 +100,9 @@ def postbuild(source, target, env):
env.Execute(' '.join(cmd), "#merging bin files")
# Create symlinks to better identify firmware
fw_update = os.path.join(outdir, f"{base}-{fwversion}-update.bin")
fw_update = os.path.join(outdir, f"{base}_{pcbvers}-{fwversion}-update.bin")
os.symlink(firmware, fw_update)
fw_full = os.path.join(outdir, f"{base}-{fwversion}-all.bin")
fw_full = os.path.join(outdir, f"{base}_{pcbvers}-{fwversion}-all.bin")
os.symlink(outfile, fw_full)
env.AddPostAction(

View File

@@ -29,7 +29,6 @@ extra_scripts =
post:extra_post.py
lib_ldf_mode = chain
monitor_speed = 115200
# monitor_raw = yes
build_flags =
-DPIO_ENV_BUILD=$PIOENV
-DBOARD_HAS_PSRAM
@@ -43,13 +42,12 @@ build_flags =
build_unflags =
-std=gnu++11
custom_version = 0.1.1
custom_version = 0.2.0
custom_versionformat = DEVELOP # Version format switch: e.g.DEVELOP=dev<yyyymmdd>|RELEASE=1.0.0
[env:obpkp61]
build_type = release # debug | release
board = esp32_s3_nano
#board = arduino_nano_esp32 # ATTENTION! Pin numbering scheme changes
board_upload.flash_size = 16MB
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
upload_port = /dev/ttyACM0

View File

@@ -282,8 +282,10 @@ void setup() {
pinMode(KEY_6, INPUT_PULLUP);
pinMode(KEY_DST, INPUT_PULLUP);
#ifdef HARDWARE_V2
// Light sensor input
pinMode(LDR, INPUT);
#endif
// Early signal system activity, red while booting
digitalWrite(RGBLED_R, HIGH);
@@ -738,6 +740,7 @@ void loop() {
case BUTTON_5: // reset
LOGI(TAG, "Device reset");
esp_rom_uart_tx_wait_idle(0);
ledcWrite(LEDC_RGBLED_B, 0); // blue config light off
led_blink(LEDC_RGBLED_G, 3, 4095, 500);
ESP.restart();
break;

View File

@@ -164,6 +164,7 @@ void webserver_init() {
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
ledcWrite(LEDC_RGBLED_B, 0); // blue config light off
led_blink(LEDC_RGBLED_G, 3, 4095, 500);
esp_rom_uart_tx_wait_idle(0);
ESP.restart();

View File

@@ -95,35 +95,11 @@
let even = true; //first counter
if (statusPage){
for (let k in jsonData) {
if (typeof (jsonData[k]) === 'object') {
if (k.indexOf('count') == 0) {
createCounterDisplay(statusPage, k.replace("count", "").replace(/in$/, " in").replace(/out$/, " out"), k, even);
even = !even;
for (let sk in jsonData[k]) {
let key = k + "." + sk;
if (typeof (jsonData[k][sk]) === 'object') {
//msg details
updateMsgDetails(key, jsonData[k][sk]);
}
else {
let el = document.getElementById(key);
if (el) el.textContent = jsonData[k][sk];
}
}
}
if (k.indexOf("ch") == 0) {
//channel def
let name = k.substring(2);
channelList[name] = jsonData[k];
}
}
else {
let el = document.getElementById(k);
if (el) el.textContent = jsonData[k];
forEl('.status-' + k, function (el) {
el.textContent = jsonData[k];
});
}
let el = document.getElementById(k);
if (el) el.textContent = jsonData[k];
forEl('.status-' + k, function (el) {
el.textContent = jsonData[k];
});
}
}
lastUpdate = (new Date()).getTime();
@@ -341,33 +317,6 @@
})
.catch(function (e) { });
}
function createCounterDisplay(parent, label, key, isEven) {
if (parent.querySelector("#" + key)) {
return;
}
let clazz = "row icon-row counter-row";
if (isEven) clazz += " even";
let row = addEl('div', clazz, parent);
row.setAttribute("id", key);
let icon = addEl('span', 'icon icon-more', row);
addEl('span', 'label', row, label);
let value = addEl('span', 'value', row, '---');
value.setAttribute('id', key + ".sumOk");
let display = addEl('div', clazz + " msgDetails hidden", parent);
display.setAttribute('id', key + ".ok");
row.addEventListener('click', function (ev) {
let rs = display.classList.toggle('hidden');
if (rs) {
icon.classList.add('icon-more');
icon.classList.remove('icon-less');
}
else {
icon.classList.remove('icon-more');
icon.classList.add('icon-less');
}
});
callListeners(api.EVENTS.counterDisplayCreated,row);
}
function validKey(key) {
if (!key) return;
return key.replace(/[^a-z_:A-Z0-9-]/g, '');
@@ -470,7 +419,6 @@
if (!(condition instanceof Array)) condition = [condition];
return condition;
}
function conditionOk(name){
let condition = getConditions(name);
if (!condition) return true;
@@ -504,97 +452,6 @@
else row.classList.add('hidden');
}
let caliv = 0;
function createCalSetInput(configItem, frame, clazz) {
let el = addEl('input', clazz, frame);
let cb = addEl('button', '', frame, 'C');
//el.disabled=true;
cb.addEventListener('click', (ev) => {
let cs = document.getElementById("calset").cloneNode(true);
cs.classList.remove("hidden");
cs.querySelector(".heading").textContent = configItem.label || configItem.name;
let vel = cs.querySelector(".val");
if (caliv != 0) window.clearInterval(caliv);
caliv = window.setInterval(() => {
if (document.body.contains(cs)) {
fetch(apiPrefix + "/api/calibrate?name=" + encodeURIComponent(configItem.name))
.then((r) => r.text())
.then((txt) => {
if (txt != vel.textContent) {
vel.textContent = txt;
}
})
.catch((e) => {
alert(e);
hideOverlay();
window.clearInterval(caliv);
})
}
else {
window.clearInterval(caliv);
}
}, 200);
showOverlay(cs, false, [{
label: 'Set', click: () => {
el.value = vel.textContent;
let cev = new Event('change');
el.dispatchEvent(cev);
}
}]);
})
el.setAttribute('name', configItem.name)
return el;
}
function createCalValInput(configItem, frame, clazz) {
let el = addEl('input', clazz, frame);
let cb = addEl('button', '', frame, 'C');
//el.disabled=true;
cb.addEventListener('click', (ev) => {
const sv = function (val, cfg) {
if (configItem.eval) {
let v = parseFloat(val);
let c = parseFloat(cfg);
return (eval(configItem.eval));
}
return v;
};
let cs = document.getElementById("calval").cloneNode(true);
cs.classList.remove("hidden");
cs.querySelector(".heading").textContent = configItem.label || configItem.name;
let vel = cs.querySelector(".val");
let vinp = cs.querySelector("input");
vinp.value = el.value;
if (caliv != 0) window.clearInterval(caliv);
caliv = window.setInterval(() => {
if (document.body.contains(cs)) {
fetch(apiPrefix + "/api/calibrate?name=" + encodeURIComponent(configItem.name))
.then((r) => r.text())
.then((txt) => {
txt = sv(txt, vinp.value);
if (txt != vel.textContent) {
vel.textContent = txt;
}
})
.catch((e) => {
alert(e);
hideOverlay();
window.clearInterval(caliv);
})
}
else {
window.clearInterval(caliv);
}
}, 200);
showOverlay(cs, false, [{
label: 'Set', click: () => {
el.value = vinp.value;
let cev = new Event('change');
el.dispatchEvent(cev);
}
}]);
})
el.setAttribute('name', configItem.name)
return el;
}
function createInput(configItem, frame, clazz) {
let el;
if (configItem.type === 'boolean' || configItem.type === 'list') {
@@ -628,9 +485,6 @@
el.setAttribute('name', configItem.name);
return el;
}
if (configItem.type === 'filter') {
return createFilterInput(configItem, frame, clazz);
}
el = addEl('input', clazz, frame);
if (configItem.readOnly) el.setAttribute('disabled', true);
el.setAttribute('name', configItem.name)
@@ -684,54 +538,6 @@
}
}
function createFilterInput(configItem, frame) {
let el = addEl('div', 'filter', frame);
let ais = createInput({
type: 'list',
name: configItem.name + "_ais",
list: ['aison', 'aisoff'],
readOnly: configItem.readOnly
}, el);
let mode = createInput({
type: 'list',
name: configItem.name + "_mode",
list: ['whitelist', 'blacklist'],
readOnly: configItem.readOnly
}, el);
let sentences = createInput({
type: 'text',
name: configItem.name + "_sentences",
readOnly: configItem.readOnly
}, el);
let data = addEl('input', undefined, el);
data.setAttribute('type', 'hidden');
let changeFunction = function () {
let cv = data.value || "";
let parts = cv.split(":");
ais.value = (parts[0] == '0') ? "aisoff" : "aison";
mode.value = (parts[1] == '0') ? "whitelist" : "blacklist";
sentences.value = parts[2] || "";
}
let updateFunction = function () {
let nv = (ais.value == 'aison') ? "1" : "0";
nv += ":";
nv += (mode.value == 'blacklist') ? "1" : "0";
nv += ":";
nv += sentences.value;
data.value = nv;
let chev = new Event('change');
data.dispatchEvent(chev);
}
mode.addEventListener('change', updateFunction);
ais.addEventListener("change", updateFunction);
sentences.addEventListener("change", updateFunction);
data.addEventListener('change', function (ev) {
changeFunction();
});
data.setAttribute('name', configItem.name);
if (configItem.readOnly) data.setAttribute('disabled', true);
return data;
}
let moreicons = ['icon-more', 'icon-less'];
function collapseCategories(parent, expand) {
@@ -1270,41 +1076,6 @@
return s + parts[0].substr(parts[0].length - dig);
}
let valueFormatters = {
formatCourse: {
f: function (v) {
let x = parseFloat(v);
let rt = x * 180.0 / Math.PI;
if (rt > 360) rt -= 360;
if (rt < 0) rt += 360;
return rt.toFixed(0);
},
u: '°'
},
formatKnots: {
f: function (v) {
let x = parseFloat(v);
x = x * 3600.0 / 1852.0;
return x.toFixed(2);
},
u: 'kn'
},
formatWind: {
f: function (v) {
let x = parseFloat(v);
x = x * 180.0 / Math.PI;
if (x > 180) x = -1 * (360 - x);
return x.toFixed(0);
},
u: '°'
},
mtr2nm: {
f: function (v) {
let x = parseFloat(v);
x = x / 1852.0;
return x.toFixed(2);
},
u: 'nm'
},
kelvinToC: {
f: function (v) {
let x = parseFloat(v);
@@ -1320,46 +1091,6 @@
},
u: ''
},
formatDepth: {
f: function (v) {
let x = parseFloat(v);
return x.toFixed(1);
},
u: 'm'
},
formatLatitude: {
f: function (v) {
let x = parseFloat(v);
if (isNaN(x)) return '-----';
return formatLonLatsDecimal(x, 'lat');
},
u: ''
},
formatLongitude: {
f: function (v) {
let x = parseFloat(v);
if (isNaN(x)) return '-----';
return formatLonLatsDecimal(x, 'lon');
},
u: ''
},
formatRot: {
f: function (v) {
let x = parseFloat(v);
if (isNaN(x)) return '---';
x = x * 180.0 / Math.PI;
return x.toFixed(2);
},
u: '°/s'
},
formatXte: {
f: function (v) {
let x = parseFloat(v);
if (isNaN(x)) return '---';
return x.toFixed(0);
},
u: 'm'
},
formatDate: {
f: function (v) {
v = parseFloat(v);
@@ -1388,8 +1119,6 @@
},
u: ''
}
}
Object.freeze(valueFormatters);
for (let k in valueFormatters){
@@ -1412,17 +1141,6 @@
}
return u;
}
function sourceName(v) {
if (v == 0) return "N2K";
for (let n in channelList) {
if (v == channelList[n].id) return n;
if (v >= channelList[n].id && v <= channelList[n].max) {
return n;
}
}
if (v < minUser) return "---";
return "USER[" + v + "]";
}
let lastSelectList = [];
buttonHandlers.uploadBin=function(ev) {
let el = document.getElementById("uploadFile");
@@ -1686,8 +1404,7 @@
config: 2, //called when the config data is loaded,data is the config object
dataItemCreated: 4, //data is an object with
// name: the item name, element: the frame item of the boat data display
status: 5, //status received, data is the status object
counterDisplayCreated: 6 //data is the row for the display
status: 5 //status received, data is the status object
}
};
function callListeners(event,data){