Javascript cleanup
This commit is contained in:
8
README
8
README
@@ -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
|
||||
|
||||
@@ -157,16 +157,16 @@ 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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
285
web/index.js
285
web/index.js
@@ -95,29 +95,6 @@
|
||||
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) {
|
||||
@@ -125,7 +102,6 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
lastUpdate = (new Date()).getTime();
|
||||
if (reloadConfig) {
|
||||
reloadConfig = false;
|
||||
@@ -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){
|
||||
|
||||
Reference in New Issue
Block a user