weather: Use Layout library

pull/825/head
Ben Whittaker 2021-09-27 13:53:23 -04:00
parent 6f477a9a06
commit e088b3be33
1 changed files with 90 additions and 79 deletions

View File

@ -1,96 +1,107 @@
(() => { const Layout = require('Layout');
const weather = require('weather'); const locale = require('locale');
let current = weather.get(); const weather = require('weather');
let current = weather.get();
function formatDuration(millis) { Bangle.loadWidgets();
let pluralize = (n, w) => n + " " + w + (n == 1 ? "" : "s");
if (millis < 60000) return "< 1 minute";
if (millis < 3600000) return pluralize(Math.floor(millis/60000), "minute");
if (millis < 86400000) return pluralize(Math.floor(millis/3600000), "hour");
return pluralize(Math.floor(millis/86400000), "day");
}
function draw() { var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [
g.reset(); {filly: 1},
g.clearRect(0, 24, 239, 239); {type: "h", filly: 0, c: [
{type: "custom", width: g.getWidth()/2, height: g.getWidth()/2, valign: -1, txt: "unknown", id: "icon",
render: l => weather.drawIcon(l.txt, l.x+l.w/2, l.y+l.h/2, l.w/2-5)},
{type: "v", c: [
{type: "h", pad: 2, c: [
{type: "txt", font: "18%", id: "temp", label: "000"},
{type: "txt", font: "12%", valign: -1, id: "tempUnit", label: "°C"},
]},
{filly: 1},
{type: "txt", font: "6x8", pad: 2, halign: 1, label: "Humidity"},
{type: "txt", font: "9%", pad: 2, halign: 1, id: "hum", label: "000%"},
{filly: 1},
{type: "txt", font: "6x8", pad: 2, halign: -1, label: "Wind"},
{type: "h", halign: -1, c: [
{type: "txt", font: "9%", pad: 2, id: "wind", label: "00"},
{type: "txt", font: "6x8", pad: 2, valign: -1, id: "windUnit", label: "km/h"},
]},
]},
]},
{filly: 1},
{type: "txt", font: "9%", id: "cond", label: "Weather line 1"},
{filly: 1},
{type: "h", c: [
{type: "txt", font: "6x8", pad: 2, id: "loc", label: "Toronto"},
{fillx: 1},
{type: "txt", font: "6x8", pad: 2, id: "updateTime", label: "15 minutes ago"},
]},
{filly: 1},
]}, null, {lazy: true});
weather.drawIcon(current.txt, 65, 90, 55); function formatDuration(millis) {
const locale = require("locale"); let pluralize = (n, w) => n + " " + w + (n == 1 ? "" : "s");
if (millis < 60000) return "< 1 minute";
if (millis < 3600000) return pluralize(Math.floor(millis/60000), "minute");
if (millis < 86400000) return pluralize(Math.floor(millis/3600000), "hour");
return pluralize(Math.floor(millis/86400000), "day");
}
g.reset(); function draw() {
layout.icon.txt = current.txt;
const temp = locale.temp(current.temp-273.15).match(/^(\D*\d*)(.*)$/);
layout.temp.label = temp[1];
layout.tempUnit.label = temp[2];
layout.hum.label = current.hum+"%";
const wind = locale.speed(current.wind).match(/^(\D*\d*)(.*)$/);
layout.wind.label = wind[1];
layout.windUnit.label = wind[2] + " " + current.wrose.toUpperCase();
// TODO: split long weather conditions across multiple lines
layout.cond.label = current.txt.charAt(0).toUpperCase()+current.txt.slice(1);
layout.loc.label = current.loc;
layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`;
layout.update();
layout.render();
}
const temp = locale.temp(current.temp-273.15).match(/^(\D*\d*)(.*)$/); function drawUpdateTime() {
let width = g.setFont("Vector", 40).stringWidth(temp[1]); if (!current || !current.time) return;
width += g.setFont("Vector", 20).stringWidth(temp[2]); layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`;
g.setFont("Vector", 40).setFontAlign(-1, -1, 0); layout.update();
g.drawString(temp[1], 180-width/2, 70); layout.render();
g.setFont("Vector", 20).setFontAlign(1, -1, 0); }
g.drawString(temp[2], 180+width/2, 70);
g.setFont("6x8", 1); function update() {
g.setFontAlign(-1, 0, 0); current = weather.get();
g.drawString("Humidity", 135, 130); NRF.removeListener("connect", update);
g.setFontAlign(1, 0, 0); if (current) {
g.drawString(current.hum+"%", 225, 130); draw();
if ('wind' in current) { } else {
g.setFontAlign(-1, 0, 0); delete layout.rects;
g.drawString("Wind", 135, 142); if (NRF.getSecurityStatus().connected) {
g.setFontAlign(1, 0, 0);
g.drawString(locale.speed(current.wind)+' '+current.wrose.toUpperCase(), 225, 142);
}
g.setFont("6x8", 2).setFontAlign(0, 0, 0);
g.drawString(current.loc, 120, 170);
g.setFont("6x8", 1).setFontAlign(0, 0, 0);
g.drawString(current.txt.charAt(0).toUpperCase()+current.txt.slice(1), 120, 190);
drawUpdateTime();
g.flip();
}
function drawUpdateTime() {
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);
g.drawString(text, 120, 206);
}
function update() {
current = weather.get();
NRF.removeListener("connect", update);
if (current) {
draw();
} else if (NRF.getSecurityStatus().connected) {
E.showMessage("Weather unknown\n\nIs Gadgetbridge\nweather reporting\nset up on your\nphone?"); E.showMessage("Weather unknown\n\nIs Gadgetbridge\nweather reporting\nset up on your\nphone?");
} else { } else {
E.showMessage("Weather unknown\n\nGadgetbridge\nnot connected"); E.showMessage("Weather unknown\n\nGadgetbridge\nnot connected");
NRF.on("connect", update); NRF.on("connect", update);
} }
} }
}
let interval = setInterval(drawUpdateTime, 60000); let interval = setInterval(drawUpdateTime, 60000);
Bangle.on('lcdPower', (on) => { Bangle.on('lcdPower', (on) => {
if (interval) { if (interval) {
clearInterval(interval); clearInterval(interval);
interval = undefined; interval = undefined;
} }
if (on) { if (on) {
drawUpdateTime(); drawUpdateTime();
interval = setInterval(drawUpdateTime, 60000); interval = setInterval(drawUpdateTime, 60000);
} }
}); });
weather.on("update", update); weather.on("update", update);
update(); update();
// Show launcher when middle button pressed // Show launcher when middle button pressed
Bangle.setUI("clock"); Bangle.setUI("clock");
Bangle.loadWidgets(); Bangle.drawWidgets();
Bangle.drawWidgets();
})()