BangleApps/apps/hworldclock/app.js

266 lines
6.9 KiB
JavaScript
Raw Normal View History

2022-06-11 13:16:18 +00:00
const big = g.getWidth()>200;
// Font for primary time and date
const primaryTimeFontSize = big?6:5;
const primaryDateFontSize = big?3:2;
require("Font5x9Numeric7Seg").add(Graphics);
require("FontTeletext10x18Ascii").add(Graphics);
// Font for single secondary time
const secondaryTimeFontSize = 4;
const secondaryTimeZoneFontSize = 2;
// Font / columns for multiple secondary times
const secondaryRowColFontSize = 2;
const xcol1 = 10;
const xcol2 = g.getWidth() - xcol1;
const font = "6x8";
/* TODO: we could totally use 'Layout' here and
avoid a whole bunch of hard-coded offsets */
const xyCenter = g.getWidth() / 2;
const xyCenterSeconds = xyCenter + (big ? 85 : 68);
const yAmPm = xyCenter - (big ? 70 : 48);
const yposTime = big ? 70 : 55;
const yposTime2 = yposTime + (big ? 100 : 60);
const yposDate = big ? 135 : 95;
const yposWorld = big ? 170 : 120;
const OFFSET_TIME_ZONE = 0;
const OFFSET_HOURS = 1;
var offsets = require("Storage").readJSON("hworldclock.settings.json") || [];
//=======Sun
setting = require("Storage").readJSON("setting.json",1);
E.setTimeZone(setting.timezone); // timezone = 1 for MEZ, = 2 for MESZ
SunCalc = require("hsuncalc.js");
const LOCATION_FILE = "mylocation.json";
var rise = "07:00";
var set = "20:00";
var pos = {altitude: 20, azimuth: 135};
var noonpos = {altitude: 37, azimuth: 180};
//=======Sun
var ampm = "AM";
// TESTING CODE
// Used to test offset array values during development.
// Uncomment to override secondary offsets value
/*
const mockOffsets = {
zeroOffsets: [],
oneOffset: [["UTC", 0]],
twoOffsets: [
["Tokyo", 9],
["UTC", 0],
],
fourOffsets: [
["Tokyo", 9],
["UTC", 0],
["Denver", -7],
["Miami", -5],
],
};*/
// Uncomment one at a time to test various offsets array scenarios
//offsets = mockOffsets.zeroOffsets; // should render nothing below primary time
//offsets = mockOffsets.oneOffset; // should render larger in two rows
//offsets = mockOffsets.twoOffsets; // should render two in columns
//offsets = mockOffsets.fourOffsets; // should render in columns
// END TESTING CODE
// Check settings for what type our clock should be
var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false;
// timeout used to update every minute
var drawTimeout;
var drawTimeoutSeconds;
g.setBgColor(0, 0, 0);
// schedule a draw for the next minute
function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
}
function doublenum(x) {
return x < 10 ? "0" + x : "" + x;
}
function getCurrentTimeFromOffset(dt, offset) {
return new Date(dt.getTime() + offset * 60 * 60 * 1000);
}
function updatePos() {
coord = require("Storage").readJSON(LOCATION_FILE,1)|| {"lat":53.3,"lon":10.1,"location":"Pattensen"};
pos = SunCalc.getPosition(Date.now(), coord.lat, coord.lon);
times = SunCalc.getTimes(Date.now(), coord.lat, coord.lon);
rise = times.sunrise.toString().split(" ")[4].substr(0,5);
set = times.sunset.toString().split(" ")[4].substr(0,5);
noonpos = SunCalc.getPosition(times.solarNoon, coord.lat, coord.lon);
}
function drawSeconds() {
// get date
var d = new Date();
var da = d.toString().split(" ");
// default draw styles
g.reset();
g.setBgColor(0, 0, 0);
// drawSting centered
g.setFontAlign(0, 0);
// draw time
var time = da[4].split(":");
var seconds = time[2];
g.setFont("5x9Numeric7Seg",primaryTimeFontSize - 3);
g.setColor("#22ff05");
//g.setFont(font, primaryTimeFontSize-3);
g.drawString(`${seconds}`, xyCenterSeconds, yposTime+14, true);
2022-06-11 16:22:37 +00:00
queueDraw();
2022-06-11 13:16:18 +00:00
}
function draw() {
// get date
var d = new Date();
var da = d.toString().split(" ");
// default draw styles
g.reset();
g.setBgColor(0, 0, 0);
// drawSting centered
g.setFontAlign(0, 0);
// draw time
var time = da[4].split(":");
var hours = time[0],
minutes = time[1];
if (_12hour){
//do 12 hour stuff
if (hours > 12) {
ampm = "PM";
hours = hours - 12;
} else {
ampm = "AM";
}
}
//g.setFont(font, primaryTimeFontSize);
g.setFont("5x9Numeric7Seg",primaryTimeFontSize);
g.setColor("#22ff05");
g.drawString(`${doublenum(hours)}:${minutes}`, xyCenter-10, yposTime, true);
// am / PM ?
if (_12hour){
//do 12 hour stuff
//var ampm = require("locale").medidian(new Date()); Not working
g.setFont("Vector", 17);
g.setColor("#22ff05");
g.drawString(ampm, xyCenterSeconds, yAmPm, true);
}
drawSeconds(); // To make sure...
// draw Day, name of month, Date
//DATE
var localDate = require("locale").date(new Date(), 1);
localDate = localDate.substring(0, localDate.length - 5)
g.setFont("Vector", 17);
g.drawString(require("locale").dow(new Date(), 1).toUpperCase() + ", " + localDate, xyCenter, yposDate, true);
g.setFont(font, primaryDateFontSize);
// set gmt to UTC+0
var gmt = new Date(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
// Loop through offset(s) and render
offsets.forEach((offset, index) => {
dx = getCurrentTimeFromOffset(gmt, offset[OFFSET_HOURS]);
hours = doublenum(dx.getHours());
minutes = doublenum(dx.getMinutes());
if (offsets.length === 1) {
var date = [require("locale").dow(new Date(), 1), require("locale").date(new Date(), 1)];
// For a single secondary timezone, draw it bigger and drop time zone to second line
const xOffset = 30;
g.setFont(font, secondaryTimeFontSize);
g.drawString(`${hours}:${minutes}`, xyCenter, yposTime2, true);
g.setFont(font, secondaryTimeZoneFontSize);
g.drawString(offset[OFFSET_TIME_ZONE], xyCenter, yposTime2 + 30, true);
// draw Day, name of month, Date
g.setFont(font, secondaryTimeZoneFontSize);
g.drawString(date, xyCenter, yposDate, true);
} else if (index < 3) {
// For > 1 extra timezones, render as columns / rows
g.setFont(font, secondaryRowColFontSize);
g.setFontAlign(-1, 0);
g.drawString(
offset[OFFSET_TIME_ZONE],
xcol1,
yposWorld + index * 15,
true
);
g.setFontAlign(1, 0);
g.drawString(`${hours}:${minutes}`, xcol2, yposWorld + index * 15, true);
}
});
g.setFontAlign(-1, 0);
g.setFont("Vector",12);
g.drawString(`^${rise}`, 10, 3 + yposWorld + 3 * 15, true); // draw riseset
g.setFontAlign(1, 0);
g.drawString(`v${set}`, xcol2, 3 + yposWorld + 3 * 15, true); // draw riseset
queueDraw();
}
// clean app screen
g.clear();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
updatePos();
2022-06-11 16:22:37 +00:00
setInterval(drawSeconds, 1E3/2);
2022-06-11 13:16:18 +00:00
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
if (on) {
draw(); // draw immediately, queue redraw
setInterval(updatePos, 60*5E3); // refesh every 5 mins
setInterval(drawSeconds, 1E3);
updatePos();
} else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeout = undefined;
drawTimeoutSeconds = undefined;
setInterval(updatePos, 60*50E3); // refesh every 50 mins
setInterval(drawSeconds, 10E3);
updatePos();
}
});
// draw now
draw();