mirror of https://github.com/espruino/BangleApps
Weather: refactoring and reduced ram usage
These changes reduce the memory usage of the ram widget by up to 70 JSVars, depending on the weather.pull/817/head
parent
50ec8d970e
commit
5925628cf6
|
@ -571,7 +571,7 @@
|
|||
{ "id": "weather",
|
||||
"name": "Weather",
|
||||
"icon": "icon.png",
|
||||
"version":"0.07",
|
||||
"version":"0.08",
|
||||
"description": "Show Gadgetbridge weather report",
|
||||
"readme": "readme.md",
|
||||
"tags": "widget,outdoors",
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
0.04: Adjust "weather unknown" message according to Bluetooth connection.
|
||||
0.05: Add wind direction.
|
||||
0.06: Use setUI for launcher.
|
||||
0.07: Add theme support and unknown icon.
|
||||
0.07: Add theme support and unknown icon.
|
||||
0.08: Refactor and reduce widget ram usage.
|
|
@ -1,5 +1,6 @@
|
|||
(() => {
|
||||
const weather = require('weather');
|
||||
let current = weather.get();
|
||||
|
||||
function formatDuration(millis) {
|
||||
let pluralize = (n, w) => n + " " + w + (n == 1 ? "" : "s");
|
||||
|
@ -10,16 +11,15 @@
|
|||
}
|
||||
|
||||
function draw() {
|
||||
let w = weather.current;
|
||||
g.reset();
|
||||
g.clearRect(0, 24, 239, 239);
|
||||
|
||||
weather.drawIcon(w.txt, 65, 90, 55);
|
||||
weather.drawIcon(current.txt, 65, 90, 55);
|
||||
const locale = require("locale");
|
||||
|
||||
g.reset();
|
||||
|
||||
const temp = locale.temp(w.temp-273.15).match(/^(\D*\d*)(.*)$/);
|
||||
const temp = locale.temp(current.temp-273.15).match(/^(\D*\d*)(.*)$/);
|
||||
let width = g.setFont("Vector", 40).stringWidth(temp[1]);
|
||||
width += g.setFont("Vector", 20).stringWidth(temp[2]);
|
||||
g.setFont("Vector", 40).setFontAlign(-1, -1, 0);
|
||||
|
@ -31,19 +31,19 @@
|
|||
g.setFontAlign(-1, 0, 0);
|
||||
g.drawString("Humidity", 135, 130);
|
||||
g.setFontAlign(1, 0, 0);
|
||||
g.drawString(w.hum+"%", 225, 130);
|
||||
if ('wind' in w) {
|
||||
g.drawString(current.hum+"%", 225, 130);
|
||||
if ('wind' in current) {
|
||||
g.setFontAlign(-1, 0, 0);
|
||||
g.drawString("Wind", 135, 142);
|
||||
g.setFontAlign(1, 0, 0);
|
||||
g.drawString(locale.speed(w.wind)+' '+w.wrose.toUpperCase(), 225, 142);
|
||||
g.drawString(locale.speed(current.wind)+' '+current.wrose.toUpperCase(), 225, 142);
|
||||
}
|
||||
|
||||
g.setFont("6x8", 2).setFontAlign(0, 0, 0);
|
||||
g.drawString(w.loc, 120, 170);
|
||||
g.drawString(current.loc, 120, 170);
|
||||
|
||||
g.setFont("6x8", 1).setFontAlign(0, 0, 0);
|
||||
g.drawString(w.txt.charAt(0).toUpperCase()+w.txt.slice(1), 120, 190);
|
||||
g.drawString(current.txt.charAt(0).toUpperCase()+current.txt.slice(1), 120, 190);
|
||||
|
||||
drawUpdateTime();
|
||||
|
||||
|
@ -51,8 +51,8 @@
|
|||
}
|
||||
|
||||
function drawUpdateTime() {
|
||||
if (!weather.current || !weather.current.time) return;
|
||||
let text = `Last update received ${formatDuration(Date.now() - weather.current.time)} ago`;
|
||||
if (!current || !current.time) return;
|
||||
let text = `Last update received ${formatDuration(Date.now() - current.time)} ago`;
|
||||
g.reset();
|
||||
g.clearRect(0, 202, 239, 210);
|
||||
g.setFont("6x8", 1).setFontAlign(0, 0, 0);
|
||||
|
@ -60,8 +60,9 @@
|
|||
}
|
||||
|
||||
function update() {
|
||||
current = weather.get();
|
||||
NRF.removeListener("connect", update);
|
||||
if (weather.current) {
|
||||
if (current) {
|
||||
draw();
|
||||
} else if (NRF.getSecurityStatus().connected) {
|
||||
E.showMessage("Weather unknown\n\nIs Gadgetbridge\nweather reporting\nset up on your\nphone?");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const storage = require('Storage');
|
||||
|
||||
let expiryTimeout = undefined;
|
||||
let expiryTimeout;
|
||||
function scheduleExpiry(json) {
|
||||
if (expiryTimeout) {
|
||||
clearTimeout(expiryTimeout);
|
||||
|
@ -9,53 +9,35 @@ function scheduleExpiry(json) {
|
|||
let expiry = "expiry" in json ? json.expiry : 2*3600000;
|
||||
if (json.weather && json.weather.time && expiry) {
|
||||
let t = json.weather.time + expiry - Date.now();
|
||||
expiryTimeout = setTimeout(() => {
|
||||
expiryTimeout = undefined;
|
||||
|
||||
let json = storage.readJSON('weather.json')||{};
|
||||
delete json.weather;
|
||||
storage.write('weather.json', json);
|
||||
|
||||
exports.current = undefined;
|
||||
exports.emit("update");
|
||||
}, t);
|
||||
expiryTimeout = setTimeout(update, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert numeric direction into human-readable label
|
||||
*
|
||||
* @param {number} deg - Direction in degrees
|
||||
* @return {string|null} - Nearest compass point
|
||||
*/
|
||||
function compassRose(deg) {
|
||||
if (typeof deg === 'undefined') return null;
|
||||
while (deg<0 || deg>360) {
|
||||
deg = (deg+360)%360;
|
||||
}
|
||||
return ['n','ne','e','se','s','sw','w','nw','n'][Math.floor((deg+22.5)/45)];
|
||||
}
|
||||
|
||||
function setCurrentWeather(json) {
|
||||
scheduleExpiry(json);
|
||||
exports.current = json.weather;
|
||||
}
|
||||
|
||||
function update(weatherEvent) {
|
||||
let weather = Object.assign({}, weatherEvent);
|
||||
weather.time = Date.now();
|
||||
if ('wdir' in weather) {
|
||||
weather.wrose = compassRose(weather.wdir);
|
||||
}
|
||||
delete weather.t;
|
||||
|
||||
let json = storage.readJSON('weather.json')||{};
|
||||
json.weather = weather;
|
||||
|
||||
if (weatherEvent) {
|
||||
let weather = weatherEvent.clone();
|
||||
delete weather.t;
|
||||
weather.time = Date.now();
|
||||
if (weather.wdir != null) {
|
||||
// Convert numeric direction into human-readable label
|
||||
let deg = weather.wdir;
|
||||
while (deg<0 || deg>360) {
|
||||
deg = (deg+360)%360;
|
||||
}
|
||||
weather.wrose = ['n','ne','e','se','s','sw','w','nw','n'][Math.floor((deg+22.5)/45)];
|
||||
}
|
||||
|
||||
json.weather = weather;
|
||||
}
|
||||
else {
|
||||
delete json.weather;
|
||||
}
|
||||
|
||||
storage.write('weather.json', json);
|
||||
|
||||
setCurrentWeather(json);
|
||||
|
||||
exports.emit("update");
|
||||
scheduleExpiry(json);
|
||||
exports.emit("update", json.weather);
|
||||
}
|
||||
|
||||
const _GB = global.GB;
|
||||
|
@ -64,7 +46,11 @@ global.GB = (event) => {
|
|||
if (_GB) setTimeout(_GB, 0, event);
|
||||
};
|
||||
|
||||
setCurrentWeather(storage.readJSON('weather.json')||{});
|
||||
exports.get = function() {
|
||||
return storage.readJSON('weather.json').weather;
|
||||
}
|
||||
|
||||
scheduleExpiry(storage.readJSON('weather.json')||{});
|
||||
|
||||
exports.drawIcon = function(cond, x, y, r) {
|
||||
function drawSun(x, y, r) {
|
||||
|
|
|
@ -1,45 +1,23 @@
|
|||
(() => {
|
||||
const weather = require('weather');
|
||||
|
||||
function draw() {
|
||||
const w = weather.current;
|
||||
if (!w) return;
|
||||
g.reset();
|
||||
g.clearRect(this.x, this.y, this.x+this.width-1, this.y+23);
|
||||
if (w.txt) {
|
||||
weather.drawIcon(w.txt, this.x+10, this.y+8, 7.5);
|
||||
}
|
||||
if (w.temp) {
|
||||
let t = require('locale').temp(w.temp-273.15); // applies conversion
|
||||
t = t.match(/[\d\-]*/)[0]; // but we have no room for units
|
||||
g.reset();
|
||||
g.setFontAlign(0, 1); // center horizontally at bottom of widget
|
||||
g.setFont('6x8', 1);
|
||||
g.drawString(t, this.x+10, this.y+24);
|
||||
}
|
||||
}
|
||||
|
||||
var dirty = false;
|
||||
|
||||
function update() {
|
||||
if (!WIDGETS["weather"].width) {
|
||||
WIDGETS["weather"].width = 20;
|
||||
Bangle.drawWidgets();
|
||||
} else if (Bangle.isLCDOn()) {
|
||||
WIDGETS["weather"].draw();
|
||||
} else {
|
||||
dirty = true;
|
||||
weather.on("update", w => {
|
||||
if (w) {
|
||||
if (!WIDGETS["weather"].width) {
|
||||
WIDGETS["weather"].width = 20;
|
||||
Bangle.drawWidgets();
|
||||
} else if (Bangle.isLCDOn()) {
|
||||
WIDGETS["weather"].draw();
|
||||
} else {
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WIDGETS["weather"].width = 0;
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
}
|
||||
|
||||
function hide() {
|
||||
WIDGETS["weather"].width = 0;
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
|
||||
weather.on("update", () => {
|
||||
if (weather.current) update();
|
||||
else hide();
|
||||
});
|
||||
|
||||
Bangle.on('lcdPower', on => {
|
||||
|
@ -51,7 +29,23 @@
|
|||
|
||||
WIDGETS["weather"] = {
|
||||
area: "tl",
|
||||
width: weather.current ? 20 : 0,
|
||||
draw: draw,
|
||||
width: weather.get() ? 20 : 0,
|
||||
draw: function() {
|
||||
const w = weather.get();
|
||||
if (!w) return;
|
||||
g.reset();
|
||||
g.clearRect(this.x, this.y, this.x+this.width-1, this.y+23);
|
||||
if (w.txt) {
|
||||
weather.drawIcon(w.txt, this.x+10, this.y+8, 7.5);
|
||||
}
|
||||
if (w.temp) {
|
||||
let t = require('locale').temp(w.temp-273.15); // applies conversion
|
||||
t = t.match(/[\d\-]*/)[0]; // but we have no room for units
|
||||
g.reset();
|
||||
g.setFontAlign(0, 1); // center horizontally at bottom of widget
|
||||
g.setFont('6x8', 1);
|
||||
g.drawString(t, this.x+10, this.y+24);
|
||||
}
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
|
Loading…
Reference in New Issue