Show difference of last measurement to pressure average of the the last three hours and an arrow indicating the trend in the widget

master
Marco Heiming 2022-06-22 11:55:07 +02:00
parent 574736f3ff
commit 2dce374a18
6 changed files with 240 additions and 214 deletions

View File

@ -3,3 +3,4 @@
0.03: Fix crash 0.03: Fix crash
0.04: Use Prompt with dismiss and pause 0.04: Use Prompt with dismiss and pause
Improve barometer value median calculation Improve barometer value median calculation
0.05: Show difference of last measurement to pressure average of the the last three hours and an arrow indicating the trend in the widget

View File

@ -19,7 +19,9 @@ Get a notification when the pressure reaches defined thresholds.
* Pause delay: Same as Dismiss delay but longer (useful for meetings and such). From 30 to 240 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:
1. pressure value of last measurement
2. difference of last measurement to pressure average of the the last three hours and an arrow indicating the trend
## Creator ## Creator
Marco ([myxor](https://github.com/myxor)) Marco ([myxor](https://github.com/myxor))

View File

@ -9,6 +9,7 @@
"tags": "tool,barometer", "tags": "tool,barometer",
"supports": ["BANGLEJS2"], "supports": ["BANGLEJS2"],
"readme": "README.md", "readme": "README.md",
"screenshots": [{"url":"screenshot-dark.png"}],
"storage": [ "storage": [
{"name":"widbaroalarm.wid.js","url":"widget.js"}, {"name":"widbaroalarm.wid.js","url":"widget.js"},
{"name":"widbaroalarm.settings.js","url":"settings.js"}, {"name":"widbaroalarm.settings.js","url":"settings.js"},

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,49 +1,43 @@
(function() { (function() {
let medianPressure; let medianPressure;
let threeHourAvrPressure; let threeHourAvrPressure;
let currentPressures = []; let currentPressures = [];
let stop = false; // semaphore 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";
const storage = require('Storage'); const storage = require('Storage');
let settings; let settings;
function loadSettings() { function loadSettings() {
settings = Object.assign( settings =
storage.readJSON("widbaroalarm.default.json", true) || {}, Object.assign(storage.readJSON("widbaroalarm.default.json", true) || {},
storage.readJSON(SETTINGS_FILE, true) || {} storage.readJSON(SETTINGS_FILE, true) || {});
); }
}
loadSettings(); loadSettings();
function setting(key) { return settings[key]; }
function setting(key) { function saveSetting(key, value) {
return settings[key];
}
function saveSetting(key, value) {
settings[key] = value; settings[key] = value;
storage.write(SETTINGS_FILE, settings); storage.write(SETTINGS_FILE, settings);
} }
const interval = setting("interval"); const interval = setting("interval");
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, key) { function showAlarm(body, key) {
if (body == undefined) return; if (body == undefined)
return;
stop = true; stop = true;
E.showPrompt(body, { E.showPrompt(body, {
title: "Pressure alarm", title : "Pressure alarm",
buttons: { buttons : {"Ok" : 1, "Dismiss" : 2, "Pause" : 3}
"Ok": 1,
"Dismiss": 2,
"Pause": 3
}
}).then(function(v) { }).then(function(v) {
const tsNow = Math.round(Date.now() / 1000); // seconds const tsNow = Math.round(Date.now() / 1000); // seconds
@ -51,19 +45,20 @@
saveSetting(key, tsNow); saveSetting(key, tsNow);
} }
if (v == 2) { if (v == 2) {
// save timestamp of the future so that we do not warn again for the same event until then // save timestamp of the future so that we do not warn again for the same
// event until then
saveSetting(key, tsNow + 60 * setting('dismissDelayMin')); saveSetting(key, tsNow + 60 * setting('dismissDelayMin'));
} }
if (v == 3) { if (v == 3) {
// save timestamp of the future so that we do not warn again for the same event until then // save timestamp of the future so that we do not warn again for the same
// event until then
saveSetting(key, tsNow + 60 * setting('pauseDelayMin')); saveSetting(key, tsNow + 60 * setting('pauseDelayMin'));
} }
stop = false; stop = false;
load(); load();
}); });
if (setting("buzz") && if (setting("buzz") && !(storage.readJSON('setting.json', 1) || {}).quiet) {
!(storage.readJSON('setting.json', 1) || {}).quiet) {
Bangle.buzz(); Bangle.buzz();
} }
@ -71,24 +66,21 @@
stop = false; stop = false;
load(); load();
}, 20000); }, 20000);
} }
function doWeNeedToWarn(key) {
function doWeNeedToWarn(key) {
const tsNow = Math.round(Date.now() / 1000); // seconds const tsNow = Math.round(Date.now() / 1000); // seconds
return setting(key) == 0 || setting(key) < tsNow; return setting(key) == 0 || setting(key) < tsNow;
} }
function checkForAlarms(pressure) { function checkForAlarms(pressure) {
if (pressure == undefined || pressure <= 0) return; if (pressure == undefined || pressure <= 0)
return;
let alreadyWarned = false; let alreadyWarned = false;
const ts = Math.round(Date.now() / 1000); // seconds const ts = Math.round(Date.now() / 1000); // seconds
const d = { const d = {"ts" : ts, "p" : pressure};
"ts": ts,
"p": pressure
};
// delete entries older than 3h // delete entries older than 3h
for (let i = 0; i < history3.length; i++) { for (let i = 0; i < history3.length; i++) {
@ -105,7 +97,8 @@
// Is below the alarm threshold? // Is below the alarm threshold?
if (pressure <= setting("min")) { if (pressure <= setting("min")) {
if (!doWeNeedToWarn("lastLowWarningTs")) { if (!doWeNeedToWarn("lastLowWarningTs")) {
showAlarm("Pressure low: " + Math.round(pressure) + " hPa", "lastLowWarningTs"); showAlarm("Pressure low: " + Math.round(pressure) + " hPa",
"lastLowWarningTs");
alreadyWarned = true; alreadyWarned = true;
} }
} else { } else {
@ -117,7 +110,8 @@
// Is above the alarm threshold? // Is above the alarm threshold?
if (pressure >= setting("max")) { if (pressure >= setting("max")) {
if (doWeNeedToWarn("lastHighWarningTs")) { if (doWeNeedToWarn("lastHighWarningTs")) {
showAlarm("Pressure high: " + Math.round(pressure) + " hPa", "lastHighWarningTs"); showAlarm("Pressure high: " + Math.round(pressure) + " hPa",
"lastHighWarningTs");
alreadyWarned = true; alreadyWarned = true;
} }
} else { } else {
@ -146,7 +140,9 @@
if (diffPressure > drop3halarm) { if (diffPressure > drop3halarm) {
if (doWeNeedToWarn("lastDropWarningTs")) { if (doWeNeedToWarn("lastDropWarningTs")) {
showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " + showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " +
Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "lastDropWarningTs"); Math.round(oldestPressure) + " to " +
Math.round(pressure) + " hPa",
"lastDropWarningTs");
} }
} else { } else {
saveSetting("lastDropWarningTs", 0); saveSetting("lastDropWarningTs", 0);
@ -160,7 +156,9 @@
if (diffPressure > raise3halarm) { if (diffPressure > raise3halarm) {
if (doWeNeedToWarn("lastRaiseWarningTs")) { if (doWeNeedToWarn("lastRaiseWarningTs")) {
showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " + showAlarm((Math.round(diffPressure * 10) / 10) + " hPa/3h from " +
Math.round(oldestPressure) + " to " + Math.round(pressure) + " hPa", "lastRaiseWarningTs"); Math.round(oldestPressure) + " to " +
Math.round(pressure) + " hPa",
"lastRaiseWarningTs");
} }
} else { } else {
saveSetting("lastRaiseWarningTs", 0); saveSetting("lastRaiseWarningTs", 0);
@ -176,8 +174,11 @@
// write data to storage // write data to storage
storage.writeJSON(LOG_FILE, history3); storage.writeJSON(LOG_FILE, history3);
// calculate 3h average for widget calculcate3hAveragePressure();
if (history3.length > 0) { }
function calculcate3hAveragePressure() {
if (history3 != undefined && 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"];
@ -186,22 +187,23 @@
} else { } else {
threeHourAvrPressure = undefined; threeHourAvrPressure = undefined;
} }
} }
/*
/*
turn on barometer power turn on barometer power
take multiple 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; if (stop)
return;
const MEDIANLENGTH = 20; const MEDIANLENGTH = 20;
Bangle.setBarometerPower(true, "widbaroalarm"); Bangle.setBarometerPower(true, "widbaroalarm");
Bangle.on('pressure', function(e) { Bangle.on('pressure', function(e) {
while (currentPressures.length > MEDIANLENGTH) currentPressures.pop(); while (currentPressures.length > MEDIANLENGTH)
currentPressures.pop();
currentPressures.unshift(e.pressure); currentPressures.unshift(e.pressure);
median = currentPressures.slice().sort(); median = currentPressures.slice().sort();
@ -215,54 +217,74 @@
} }
}); });
setTimeout(function() { setTimeout(function() { turnOff(); }, 10000);
turnOff(); }
}, 10000);
}
function turnOff() { function turnOff() {
if (Bangle.isBarometerOn()) if (Bangle.isBarometerOn())
Bangle.setBarometerPower(false, "widbaroalarm"); Bangle.setBarometerPower(false, "widbaroalarm");
} }
function reload() { function reload() { check(); }
check();
}
function draw() { function draw() {
if (global.WIDGETS != undefined && typeof global.WIDGETS === "object") { if (global.WIDGETS != undefined && typeof global.WIDGETS === "object") {
global.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")) { if (setting("show")) {
g.setFont("6x8", 1).setFontAlign(1, 0); g.setFont("6x8", 1).setFontAlign(1, 0);
const x = this.x, y = this.y;
if (medianPressure == undefined) { if (medianPressure == undefined) {
// trigger a new check
check(); check();
const x = this.x,
y = this.y; // lets load last value from log (if available)
if (history3.length > 0) {
medianPressure = history3[history3.length - 1]["p"];
}
g.drawString("...", x + 24, y + 6); g.drawString("...", x + 24, y + 6);
setTimeout(function() {
g.setFont("6x8", 1).setFontAlign(1, 0); g.setFont("6x8", 1).setFontAlign(1, 0);
g.drawString(Math.round(medianPressure), x + 24, y + 6); g.drawString(Math.round(medianPressure), x + 24, y + 6);
}, 10000);
} else { } else {
g.drawString(Math.round(medianPressure), this.x + 24, this.y + 6); g.drawString(Math.round(medianPressure), x + 24, y + 6);
} }
if (threeHourAvrPressure != undefined && threeHourAvrPressure > 0) { if (threeHourAvrPressure == undefined) {
g.drawString(Math.round(threeHourAvrPressure), this.x + 24, this.y + 6 + 10); calculcate3hAveragePressure();
} }
if (threeHourAvrPressure != undefined) {
if (medianPressure != undefined) {
let icon;
const diff = threeHourAvrPressure - medianPressure;
if (diff == 0) {
icon = atob("DAyBAAAAAAAAIAEAGD+AEAIAAAAAAA=="); // allow right
} else {
if (diff < 0) {
icon = atob("DAyBAAAAAAAAfAHALATAgBAAAAAAAA=="); // arrow up
} else {
icon = atob("DAyBAAAAAAABAAgATALAHAHAeAAAAA=="); // arrow down
} }
} }
if (interval > 0) { g.drawImage(icon, x, y + 6 + 4);
g.drawString((diff < 0 ? "+" : "-" ) + Math.round(diff), x + 24, y + 6 + 10);
}
}
}
}
if (interval > 0) {
setInterval(check, interval * 60000); setInterval(check, interval * 60000);
} }
draw(); draw();
})(); })();