1
0
Fork 0

Merge pull request #1887 from myxor/baroalarm_v0.04

Baroalarm v0.04
master
Gordon Williams 2022-06-13 15:52:28 +01:00 committed by GitHub
commit 204666134a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 78 deletions

View File

@ -1,3 +1,5 @@
0.01: Initial version 0.01: Initial version
0.02: Do not warn multiple times for the same exceedance 0.02: Do not warn multiple times for the same exceed
0.03: Fix crash 0.03: Fix crash
0.04: Use Prompt with dismiss and pause
Improve barometer value median calculation

View File

@ -15,7 +15,8 @@ Get a notification when the pressure reaches defined thresholds.
0 to disable this alarm. 0 to disable this alarm.
* Show widget: Enable/disable widget visibility * Show widget: Enable/disable widget visibility
* Buzz on alarm: Enable/disable buzzer on alarm * Buzz on alarm: Enable/disable buzzer on alarm
* Dismiss delay: Delay added before the next alert if the alert is dismissed. From 5 to 60 min
* Pause delay: Same as Dismiss delay but longer (useful for meetings and such). From 30 to 240 min
## Widget ## Widget
The widget shows two rows: pressure value of last measurement and pressure average of the the last three hours. The widget shows two rows: pressure value of last measurement and pressure average of the the last three hours.

View File

@ -7,5 +7,7 @@
"drop3halarm": 2, "drop3halarm": 2,
"raise3halarm": 0, "raise3halarm": 0,
"show": true, "show": true,
"interval": 15 "interval": 15,
"dismissDelayMin": 15,
"pauseDelayMin": 60
} }

View File

@ -2,13 +2,12 @@
"id": "widbaroalarm", "id": "widbaroalarm",
"name": "Barometer Alarm Widget", "name": "Barometer Alarm Widget",
"shortName": "Barometer Alarm", "shortName": "Barometer Alarm",
"version": "0.03", "version": "0.04",
"description": "A widget that can alarm on when the pressure reaches defined thresholds.", "description": "A widget that can alarm on when the pressure reaches defined thresholds.",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",
"tags": "tool,barometer", "tags": "tool,barometer",
"supports": ["BANGLEJS2"], "supports": ["BANGLEJS2"],
"dependencies": {"notify":"type"},
"readme": "README.md", "readme": "README.md",
"storage": [ "storage": [
{"name":"widbaroalarm.wid.js","url":"widget.js"}, {"name":"widbaroalarm.wid.js","url":"widget.js"},

View File

@ -87,6 +87,26 @@
}, },
onchange: x => save('buzz', x) onchange: x => save('buzz', x)
}, },
'Dismiss delay': {
value: settings.dismissDelayMin,
min: 5, max: 60,
onchange: v => {
save('dismissDelayMin', v)
},
format: x => {
return x + " min";
}
},
'Pause delay': {
value: settings.pauseDelayMin,
min: 30, max: 240,
onchange: v => {
save('pauseDelayMin', v)
},
format: x => {
return x + " min";
}
},
}; };
E.showMenu(menu); E.showMenu(menu);
} }

View File

@ -2,6 +2,7 @@
let medianPressure; let medianPressure;
let threeHourAvrPressure; let threeHourAvrPressure;
let currentPressures = []; let currentPressures = [];
let stop = false; // semaphore
const LOG_FILE = "widbaroalarm.log.json"; const LOG_FILE = "widbaroalarm.log.json";
const SETTINGS_FILE = "widbaroalarm.json"; const SETTINGS_FILE = "widbaroalarm.json";
@ -32,24 +33,50 @@
let history3 = storage.readJSON(LOG_FILE, true) || []; // history of recent 3 hours let history3 = storage.readJSON(LOG_FILE, true) || []; // history of recent 3 hours
function showAlarm(body, title) { function showAlarm(body, key) {
if (body == undefined) return; if (body == undefined) return;
stop = true;
require("notify").show({ E.showPrompt(body, {
title: title || "Pressure", title: "Pressure alarm",
body: body, buttons: {
icon: require("heatshrink").decompress(atob("jEY4cA///gH4/++mkK30kiWC4H8x3BGDmSGgYDCgmSoEAg3bsAIDpAIFkmSpMAm3btgIFDQwIGNQpTYkAIJwAHEgMoCA0JgMEyBnBCAW3KoQQDhu3oAIH5JnDBAW24IIBEYm2EYwACBCIACA")) "Ok": 1,
"Dismiss": 2,
"Pause": 3
}
}).then(function(v) {
const tsNow = Math.round(Date.now() / 1000); // seconds
if (v == 1) {
saveSetting(key, tsNow);
}
if (v == 2) {
// save timestamp of the future so that we do not warn again for the same event until then
saveSetting(key, tsNow + 60 * setting('dismissDelayMin'));
}
if (v == 3) {
// save timestamp of the future so that we do not warn again for the same event until then
saveSetting(key, tsNow + 60 * setting('pauseDelayMin'));
}
stop = false;
load();
}); });
if (setting("buzz") && if (setting("buzz") &&
!(storage.readJSON('setting.json', 1) || {}).quiet) { !(storage.readJSON('setting.json', 1) || {}).quiet) {
Bangle.buzz(); Bangle.buzz();
} }
setTimeout(function() {
stop = false;
load();
}, 20000);
} }
function didWeAlreadyWarn(key) { function doWeNeedToWarn(key) {
return setting(key) == undefined || setting(key) > 0; const tsNow = Math.round(Date.now() / 1000); // seconds
return setting(key) == 0 || setting(key) < tsNow;
} }
function checkForAlarms(pressure) { function checkForAlarms(pressure) {
@ -77,31 +104,25 @@
if (setting("lowalarm")) { if (setting("lowalarm")) {
// Is below the alarm threshold? // Is below the alarm threshold?
if (pressure <= setting("min")) { if (pressure <= setting("min")) {
if (!didWeAlreadyWarn("lastLowWarningTs")) { if (!doWeNeedToWarn("lastLowWarningTs")) {
showAlarm("Pressure low: " + Math.round(pressure) + " hPa"); showAlarm("Pressure low: " + Math.round(pressure) + " hPa", "lastLowWarningTs");
saveSetting("lastLowWarningTs", ts);
alreadyWarned = true; alreadyWarned = true;
} }
} else { } else {
saveSetting("lastLowWarningTs", 0); saveSetting("lastLowWarningTs", 0);
} }
} else {
saveSetting("lastLowWarningTs", 0);
} }
if (setting("highalarm")) { if (setting("highalarm")) {
// Is above the alarm threshold? // Is above the alarm threshold?
if (pressure >= setting("max")) { if (pressure >= setting("max")) {
if (!didWeAlreadyWarn("lastHighWarningTs")) { if (doWeNeedToWarn("lastHighWarningTs")) {
showAlarm("Pressure high: " + Math.round(pressure) + " hPa"); showAlarm("Pressure high: " + Math.round(pressure) + " hPa", "lastHighWarningTs");
saveSetting("lastHighWarningTs", ts);
alreadyWarned = true; alreadyWarned = true;
} }
} else { } else {
saveSetting("lastHighWarningTs", 0); saveSetting("lastHighWarningTs", 0);
} }
} else {
saveSetting("lastHighWarningTs", 0);
} }
if (history3.length > 0 && !alreadyWarned) { if (history3.length > 0 && !alreadyWarned) {
@ -110,22 +131,22 @@
const raise3halarm = setting("raise3halarm"); const raise3halarm = setting("raise3halarm");
if (drop3halarm > 0 || raise3halarm > 0) { if (drop3halarm > 0 || raise3halarm > 0) {
// we need at least 30min of data for reliable detection // we need at least 30min of data for reliable detection
if (history3[0]["ts"] > ts - (30 * 60)) { const diffDateAge = Math.abs(history3[0]["ts"] - ts);
if (diffDateAge < 10 * 60) { // todo change to 1800
return; return;
} }
// Get oldest entry: // Get oldest entry:
const oldestPressure = history3[0]["p"]; const oldestPressure = history3[0]["p"];
if (oldestPressure != undefined && oldestPressure > 0) { if (oldestPressure != undefined && oldestPressure > 0) {
const diff = oldestPressure - pressure; const diffPressure = Math.abs(oldestPressure - pressure);
// drop alarm // drop alarm
if (drop3halarm > 0 && oldestPressure > pressure) { if (drop3halarm > 0 && oldestPressure > pressure) {
if (Math.abs(diff) > drop3halarm) { if (diffPressure > drop3halarm) {
if (!didWeAlreadyWarn("lastDropWarningTs")) { if (doWeNeedToWarn("lastDropWarningTs")) {
showAlarm((Math.round(Math.abs(diff) * 10) / 10) + " hPa/3h from " + showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " +
Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "Pressure drop"); Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "lastDropWarningTs");
saveSetting("lastDropWarningTs", ts);
} }
} else { } else {
saveSetting("lastDropWarningTs", 0); saveSetting("lastDropWarningTs", 0);
@ -136,11 +157,10 @@
// raise alarm // raise alarm
if (raise3halarm > 0 && oldestPressure < pressure) { if (raise3halarm > 0 && oldestPressure < pressure) {
if (Math.abs(diff) > raise3halarm) { if (diffPressure > raise3halarm) {
if (!didWeAlreadyWarn("lastRaiseWarningTs")) { if (doWeNeedToWarn("lastRaiseWarningTs")) {
showAlarm((Math.round(Math.abs(diff) * 10) / 10) + " hPa/3h from " + showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " +
Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "Pressure raise"); Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "lastRaiseWarningTs");
saveSetting("lastRaiseWarningTs", ts);
} }
} else { } else {
saveSetting("lastRaiseWarningTs", 0); saveSetting("lastRaiseWarningTs", 0);
@ -157,51 +177,52 @@
storage.writeJSON(LOG_FILE, history3); storage.writeJSON(LOG_FILE, history3);
// calculate 3h average for widget // calculate 3h average for widget
if (history3.length > 0) {
let sum = 0; let sum = 0;
for (let i = 0; i < history3.length; i++) { for (let i = 0; i < history3.length; i++) {
sum += history3[i]["p"]; sum += history3[i]["p"];
} }
threeHourAvrPressure = sum / history3.length; threeHourAvrPressure = sum / history3.length;
} } else {
threeHourAvrPressure = undefined;
function baroHandler(data) {
if (data) {
const pressure = Math.round(data.pressure);
if (pressure == undefined || pressure <= 0) return;
currentPressures.push(pressure);
} }
} }
/* /*
turn on barometer power turn on barometer power
take 5 measurements take multiple measurements
sort the results sort the results
take the middle one (median) take the middle one (median)
turn off barometer power turn off barometer power
*/ */
function check() { function check() {
if (stop) return;
const MEDIANLENGTH = 20;
Bangle.setBarometerPower(true, "widbaroalarm"); Bangle.setBarometerPower(true, "widbaroalarm");
setTimeout(function() { Bangle.on('pressure', function(e) {
currentPressures = []; while (currentPressures.length > MEDIANLENGTH) currentPressures.pop();
currentPressures.unshift(e.pressure);
median = currentPressures.slice().sort();
Bangle.getPressure().then(baroHandler); if (median.length > 10) {
Bangle.getPressure().then(baroHandler); var mid = median.length >> 1;
Bangle.getPressure().then(baroHandler); medianPressure = Math.round(E.sum(median.slice(mid - 4, mid + 5)) / 9);
Bangle.getPressure().then(baroHandler); if (medianPressure > 0) {
Bangle.getPressure().then(baroHandler); turnOff();
setTimeout(function() {
Bangle.setBarometerPower(false, "widbaroalarm");
currentPressures.sort();
// take median value
medianPressure = currentPressures[3];
checkForAlarms(medianPressure); checkForAlarms(medianPressure);
}, 1000); }
}, 500); }
});
setTimeout(function() {
turnOff();
}, 10000);
}
function turnOff() {
if (Bangle.isBarometerOn())
Bangle.setBarometerPower(false, "widbaroalarm");
} }
function reload() { function reload() {
@ -209,31 +230,39 @@
} }
function draw() { function draw() {
if (global.WIDGETS != undefined && typeof WIDGETS === "object") { if (global.WIDGETS != undefined && typeof global.WIDGETS === "object") {
WIDGETS["baroalarm"] = { global.WIDGETS["baroalarm"] = {
width: setting("show") ? 24 : 0, width: setting("show") ? 24 : 0,
reload: reload, reload: reload,
area: "tr", area: "tr",
draw: draw draw: draw
}; };
} }
g.reset(); g.reset();
if (setting("show") && medianPressure != undefined) { if (setting("show")) {
g.setFont("6x8", 1).setFontAlign(1, 0); g.setFont("6x8", 1).setFontAlign(1, 0);
if (medianPressure == undefined) {
check();
const x = this.x,
y = this.y;
g.drawString("...", x + 24, y + 6);
setTimeout(function() {
g.setFont("6x8", 1).setFontAlign(1, 0);
g.drawString(Math.round(medianPressure), x + 24, y + 6);
}, 10000);
} else {
g.drawString(Math.round(medianPressure), this.x + 24, this.y + 6); g.drawString(Math.round(medianPressure), this.x + 24, this.y + 6);
}
if (threeHourAvrPressure != undefined && threeHourAvrPressure > 0) { if (threeHourAvrPressure != undefined && threeHourAvrPressure > 0) {
g.drawString(Math.round(threeHourAvrPressure), this.x + 24, this.y + 6 + 10); g.drawString(Math.round(threeHourAvrPressure), this.x + 24, this.y + 6 + 10);
} }
} }
} }
// Let's delay the first check a bit
setTimeout(function() {
check();
if (interval > 0) { if (interval > 0) {
setInterval(check, interval * 60000); setInterval(check, interval * 60000);
} }
}, 1000); draw();
})(); })();