1
0
Fork 0
BangleApps/apps/hworldclock/app.js

462 lines
13 KiB
JavaScript
Raw Normal View History

2022-11-16 07:20:05 +00:00
{ // must be inside our own scope here so that when we are unloaded everything disappears
2022-06-16 15:43:30 +00:00
// ------- Settings file
const SETTINGSFILE = "hworldclock.json";
let secondsMode;
let showSunInfo;
let colorWhenDark;
let rotationTarget;
2022-06-16 15:43:30 +00:00
// ------- Settings file
//const BANGLEJS2 = process.env.HWVERSION == 2;
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;
let font5x9 = require("Font5x9Numeric7Seg").add(Graphics);
let font10x18 = require("FontTeletext10x18Ascii").add(Graphics);
2022-06-11 13:16:18 +00:00
// Font for single secondary time
2022-12-12 16:14:27 +00:00
const secondaryTimeFontSize = 4;
2022-06-11 13:16:18 +00:00
const secondaryTimeZoneFontSize = 2;
// Font / columns for multiple secondary times
const secondaryRowColFontSize = 2;
const xcol1 = 10;
const xcol2 = g.getWidth() - xcol1;
const font = "6x8";
2022-12-12 16:14:27 +00:00
let drag;
2022-06-11 13:16:18 +00:00
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;
let PosInterval = 0;
let offsets = require("Storage").readJSON("hworldclock.settings.json") || [];
2022-06-11 13:16:18 +00:00
//=======Sun
let setting = require("Storage").readJSON("setting.json",1);
2022-06-11 13:16:18 +00:00
E.setTimeZone(setting.timezone); // timezone = 1 for MEZ, = 2 for MESZ
//https://raw.githubusercontent.com/pebl-hank/BangleApps/master/modules/suncalc.js
let SunCalc = require("suncalc"); // from modules folder
2022-06-11 13:16:18 +00:00
const LOCATION_FILE = "mylocation.json";
let rise = "read";
let set = "...";
2022-06-30 08:15:01 +00:00
//var pos = {altitude: 20, azimuth: 135};
//var noonpos = {altitude: 37, azimuth: 180};
2022-06-11 13:16:18 +00:00
//=======Sun
let ampm = "AM";
let defaultRotation = setting.rotate || 0;
let currentRotation = defaultRotation;
2022-06-11 13:16:18 +00:00
// 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],
],
};*/
2022-06-16 15:43:30 +00:00
// Example hworldclock.settings.json
// [["London","0"],["NY","-5"],["Denver","-6"]]
2022-06-11 13:16:18 +00:00
// 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
2022-12-12 16:14:27 +00:00
2022-06-16 15:43:30 +00:00
// ================ Load settings
// Helper function default setting
let def = function(value, def) {
return value !== undefined ? value : def;
2022-06-16 15:43:30 +00:00
}
let settings = require('Storage').readJSON(SETTINGSFILE, true) || {};
secondsMode = def(settings.secondsMode, "when unlocked");
showSunInfo = def(settings.showSunInfo, true);
singleOffsetSmall = def(settings.singleOffsetSmall, false);
colorWhenDark = def(settings.colorWhenDark, "green");
rotationTarget = def(settings.rotationTarget, "90");
rotationTarget = parseInt(rotationTarget) || 0;
if (rotationTarget == 90) rotationTarget = 1; // very lame, but works for now.
if (rotationTarget == 180) rotationTarget = 2;
if (rotationTarget == 270) rotationTarget = 3;
// ================ Load settings
2022-06-11 13:16:18 +00:00
// Check settings for what type our clock should be
let _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||false;
2022-06-11 13:16:18 +00:00
// timeout used to update every minute
let drawTimeout;
let drawTimeoutSeconds;
let secondsTimeout;
2022-06-11 13:16:18 +00:00
2022-06-12 20:44:32 +00:00
g.setBgColor(g.theme.bg);
2022-06-11 13:16:18 +00:00
// schedule a draw for the next minute
let queueDraw = function() {
2022-06-11 13:16:18 +00:00
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
2022-06-30 08:15:01 +00:00
drawTimeout = undefined;
draw();
}, 60000 - (Date.now() % 60000));
2022-06-11 13:16:18 +00:00
}
// schedule a draw for the next second
let queueDrawSeconds = function() {
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = setTimeout(function() {
2022-06-30 08:15:01 +00:00
drawTimeoutSeconds = undefined;
drawSeconds();
//console.log("TO: " + secondsTimeout);
}, secondsTimeout - (Date.now() % secondsTimeout));
}
let doublenum = function(x) {
2022-06-11 13:16:18 +00:00
return x < 10 ? "0" + x : "" + x;
}
let getCurrentTimeFromOffset = function(dt, offset) {
2022-06-11 13:16:18 +00:00
return new Date(dt.getTime() + offset * 60 * 60 * 1000);
}
let updatePos = function() {
let coord = require("Storage").readJSON(LOCATION_FILE,1)|| {"lat":0,"lon":0,"location":"-"}; //{"lat":53.3,"lon":10.1,"location":"Pattensen"};
2022-07-01 17:12:53 +00:00
if (coord.lat != 0 && coord.lon != 0) {
2022-12-12 16:14:27 +00:00
//pos = SunCalc.getPosition(Date.now(), coord.lat, coord.lon);
2022-06-11 13:16:18 +00:00
times = SunCalc.getTimes(Date.now(), coord.lat, coord.lon);
2022-07-01 17:12:53 +00:00
rise = "^" + times.sunrise.toString().split(" ")[4].substr(0,5);
set = "v" + times.sunset.toString().split(" ")[4].substr(0,5);
2022-12-12 16:14:27 +00:00
//noonpos = SunCalc.getPosition(times.solarNoon, coord.lat, coord.lon);
2022-07-01 17:12:53 +00:00
} else {
rise = null;
set = null;
}
2022-06-11 13:16:18 +00:00
}
let drawSeconds = function() {
2022-06-11 13:16:18 +00:00
// get date
2022-11-16 07:20:05 +00:00
let d = new Date();
let da = d.toString().split(" ");
2022-06-11 13:16:18 +00:00
// default draw styles
2022-06-30 08:15:01 +00:00
g.reset().setBgColor(g.theme.bg).setFontAlign(0, 0);
2022-06-11 13:16:18 +00:00
// draw time
2022-11-16 07:20:05 +00:00
let time = da[4].split(":");
let seconds = time[2];
2022-06-11 13:16:18 +00:00
g.setFont("5x9Numeric7Seg",primaryTimeFontSize - 3);
2022-06-12 20:44:32 +00:00
if (g.theme.dark) {
2022-06-16 15:43:30 +00:00
if (colorWhenDark == "green") {
g.setColor("#22ff05");
} else {
g.setColor(g.theme.fg);
}
2022-06-12 20:44:32 +00:00
} else {
g.setColor(g.theme.fg);
}
2022-06-16 15:43:30 +00:00
if (Bangle.isLocked() && secondsMode != "always") seconds = seconds.slice(0, -1) + ':::'; // we use :: as the font does not have an x
2022-12-12 16:14:27 +00:00
g.drawString(`${seconds}`, xyCenterSeconds, yposTime+14, true);
queueDrawSeconds();
2022-06-11 13:16:18 +00:00
}
let draw = function() {
2022-06-11 13:16:18 +00:00
// get date
2022-11-16 07:20:05 +00:00
let d = new Date();
let da = d.toString().split(" ");
2022-06-11 13:16:18 +00:00
// default draw styles
2022-06-30 08:15:01 +00:00
g.reset().setBgColor(g.theme.bg).setFontAlign(0, 0);
2022-06-11 13:16:18 +00:00
// draw time
2022-11-16 07:20:05 +00:00
let time = da[4].split(":");
let hours = time[0],
2022-06-11 13:16:18 +00:00
minutes = time[1];
2022-12-12 16:14:27 +00:00
2022-06-11 13:16:18 +00:00
if (_12hour){
//do 12 hour stuff
if (hours > 12) {
ampm = "PM";
2022-12-12 16:14:27 +00:00
hours = hours - 12;
if (hours < 10) hours = doublenum(hours);
2022-06-11 13:16:18 +00:00
} else {
2022-12-12 16:14:27 +00:00
ampm = "AM";
}
}
2022-06-11 13:16:18 +00:00
g.setFont("5x9Numeric7Seg",primaryTimeFontSize);
2022-06-12 20:44:32 +00:00
if (g.theme.dark) {
2022-06-16 15:43:30 +00:00
if (colorWhenDark == "green") {
g.setColor("#22ff05");
} else {
g.setColor(g.theme.fg);
}
2022-06-12 20:44:32 +00:00
} else {
g.setColor(g.theme.fg);
}
2022-06-11 21:08:03 +00:00
g.drawString(`${hours}:${minutes}`, xyCenter-10, yposTime, true);
2022-12-12 16:14:27 +00:00
2022-06-11 13:16:18 +00:00
// am / PM ?
if (_12hour){
//do 12 hour stuff
2022-11-16 07:20:05 +00:00
//let ampm = require("locale").medidian(new Date()); Not working
2022-06-11 13:16:18 +00:00
g.setFont("Vector", 17);
g.drawString(ampm, xyCenterSeconds, yAmPm, true);
2022-12-12 16:14:27 +00:00
}
2022-06-11 13:16:18 +00:00
2022-06-16 15:43:30 +00:00
if (secondsMode != "none") drawSeconds(); // To make sure...
2022-12-12 16:14:27 +00:00
// draw Day, name of month, Date
2022-06-11 13:16:18 +00:00
//DATE
2022-11-16 07:20:05 +00:00
let localDate = require("locale").date(new Date(), 1);
localDate = localDate.substring(0, localDate.length - 5);
2022-07-01 16:30:26 +00:00
g.setFont("Vector", 17);
g.drawString(require("locale").dow(new Date(), 1).toUpperCase() + ", " + localDate, xyCenter, yposDate, true);
2022-06-11 13:16:18 +00:00
g.setFont(font, primaryDateFontSize);
// set gmt to UTC+0
2022-11-16 07:20:05 +00:00
let gmt = new Date(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
2022-06-11 13:16:18 +00:00
// 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 && !singleOffsetSmall) {
2022-12-12 16:14:27 +00:00
let date = [require("locale").dow(new Date(), 1), require("locale").date(new Date(), 1)];
2022-06-11 13:16:18 +00:00
// For a single secondary timezone, draw it bigger and drop time zone to second line
const xOffset = 30;
2022-06-30 08:15:01 +00:00
g.setFont(font, secondaryTimeFontSize).drawString(`${hours}:${minutes}`, xyCenter, yposTime2, true);
g.setFont(font, secondaryTimeZoneFontSize).drawString(offset[OFFSET_TIME_ZONE], xyCenter, yposTime2 + 30, true);
2022-06-11 13:16:18 +00:00
// draw Day, name of month, Date
2022-06-30 08:15:01 +00:00
g.setFont(font, secondaryTimeZoneFontSize).drawString(date, xyCenter, yposDate, true);
2022-06-11 13:16:18 +00:00
} else if (index < 3) {
// For > 1 extra timezones, render as columns / rows
2022-07-01 16:30:26 +00:00
g.setFont(font, secondaryRowColFontSize).setFontAlign(-1, 0);
2022-06-11 13:16:18 +00:00
g.drawString(
offset[OFFSET_TIME_ZONE],
xcol1,
yposWorld + index * 15,
true
);
2022-07-01 16:30:26 +00:00
g.setFontAlign(1, 0).drawString(`${hours}:${minutes}`, xcol2, yposWorld + index * 15, true);
2022-06-11 13:16:18 +00:00
}
});
2022-06-16 15:43:30 +00:00
if (showSunInfo) {
2022-07-01 17:12:53 +00:00
if (rise != null){
2022-07-01 17:25:54 +00:00
g.setFontAlign(-1, 0).setFont("Vector",12).drawString(`${rise}`, 10, 3 + yposWorld + 3 * 15, true); // draw rise
g.setFontAlign(1, 0).drawString(`${set}`, xcol2, 3 + yposWorld + 3 * 15, true); // draw set
2022-07-01 17:12:53 +00:00
} else {
2022-12-12 16:14:27 +00:00
g.setFontAlign(-1, 0).setFont("Vector",11).drawString("set city in \'my location\' app!", 10, 3 + yposWorld + 3 * 15, true);
2022-07-01 17:25:54 +00:00
}
2022-06-16 15:43:30 +00:00
}
//debug settings
//g.setFontAlign(1, 0);
//g.drawString(secondsMode, xcol2, 3 + yposWorld + 3 * 15, true);
//g.drawString(showSunInfo, xcol2, 3 + yposWorld + 3 * 15, true);
//g.drawString(colorWhenDark, xcol2, 3 + yposWorld + 3 * 15, true);
2022-06-11 13:16:18 +00:00
queueDraw();
2022-12-12 16:14:27 +00:00
2022-06-16 15:43:30 +00:00
if (secondsMode != "none") queueDrawSeconds();
2022-06-11 13:16:18 +00:00
}
2022-12-12 16:14:27 +00:00
//if (BANGLEJS2) {
let onDrag = e => {
if (!drag) { // start dragging
drag = {x: e.x, y: e.y};
} else if (!e.b) { // released
const dx = e.x-drag.x, dy = e.y-drag.y;
drag = null;
if (Math.abs(dx)>Math.abs(dy)+10) {
// horizontal
if (dx < dy) {
// for later purpose
} else {
// for later purpose
}
} else if (Math.abs(dy)>Math.abs(dx)+10) {
// vertical
if (dx < dy) { //down
//g.clear().setRotation(defaultRotation);
//currentRotation = defaultRotation;
//draw();
//Bangle.drawWidgets();
2022-12-12 16:14:27 +00:00
} else {
if (currentRotation == rotationTarget) {
g.clear().setRotation(defaultRotation);
currentRotation = defaultRotation;
} else {
g.clear().setRotation(rotationTarget);
currentRotation = rotationTarget;
}
2022-12-12 16:14:27 +00:00
draw();
Bangle.drawWidgets();
}
} else {
//console.log("tap " + e.x + " " + e.y);
if (e.x > 145 && e.y > 145) {
// for later purpose
}
}
}
}; //);
Bangle.on("drag", onDrag);
//} <-- BJS2 only } else {
2022-12-12 16:14:27 +00:00
//setWatch(xxx, BTN1, { repeat: true, debounce:50 }); // maybe adding this later
//setWatch(xxx, BTN3, { repeat: true, debounce:50 });
//setWatch(xxx, BTN4, { repeat: true, debounce:50 });
//setWatch(xxx, BTN5, { repeat: true, debounce:50 });
// }
if (!Bangle.isLocked()) { // Initial state
2022-06-16 15:43:30 +00:00
if (showSunInfo) {
2022-11-16 07:23:11 +00:00
if (PosInterval != 0 && typeof PosInterval != 'undefined') clearInterval(PosInterval);
2022-06-16 15:43:30 +00:00
PosInterval = setInterval(updatePos, 60*10E3); // refesh every 10 mins
2022-07-01 16:30:26 +00:00
updatePos();
2022-06-16 15:43:30 +00:00
}
2022-06-16 15:43:30 +00:00
secondsTimeout = 1000;
if (secondsMode != "none") {
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = undefined;
2022-12-12 16:14:27 +00:00
}
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
draw(); // draw immediately, queue redraw
2022-12-12 16:14:27 +00:00
}else{
2022-06-16 15:43:30 +00:00
if (secondsMode == "always") secondsTimeout = 1000;
if (secondsMode == "when unlocked") secondsTimeout = 10 * 1000;
2022-12-12 16:14:27 +00:00
2022-06-16 15:43:30 +00:00
if (secondsMode != "none") {
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = undefined;
}
2022-06-12 17:42:48 +00:00
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
2022-06-12 17:42:48 +00:00
2022-06-16 15:43:30 +00:00
if (showSunInfo) {
2022-11-16 07:23:11 +00:00
if (PosInterval != 0 && typeof PosInterval != 'undefined') clearInterval(PosInterval);
2022-06-16 15:43:30 +00:00
PosInterval = setInterval(updatePos, 60*60E3); // refesh every 60 mins
2022-07-01 16:30:26 +00:00
updatePos();
2022-06-16 15:43:30 +00:00
}
draw(); // draw immediately, queue redraw
}
2022-12-12 16:14:27 +00:00
2022-12-12 16:14:27 +00:00
let onLock = on => {
if (!on) { // UNlocked
2022-06-16 15:43:30 +00:00
if (showSunInfo) {
if (PosInterval != 0) clearInterval(PosInterval);
PosInterval = setInterval(updatePos, 60*10E3); // refesh every 10 mins
2022-07-01 16:30:26 +00:00
updatePos();
2022-06-16 15:43:30 +00:00
}
2022-07-01 16:30:26 +00:00
secondsTimeout = 1000;
2022-06-16 15:43:30 +00:00
if (secondsMode != "none") {
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = undefined;
2022-12-12 16:14:27 +00:00
}
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
draw(); // draw immediately, queue redraw
}else{ // locked
2022-06-12 17:42:48 +00:00
2022-06-16 15:43:30 +00:00
if (secondsMode == "always") secondsTimeout = 1000;
if (secondsMode == "when unlocked") secondsTimeout = 10 * 1000;
2022-12-12 16:14:27 +00:00
2022-06-16 15:43:30 +00:00
if (secondsMode != "none") {
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = undefined;
}
2022-06-12 17:42:48 +00:00
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
2022-06-30 08:15:01 +00:00
if (showSunInfo) {
if (PosInterval != 0) clearInterval(PosInterval);
PosInterval = setInterval(updatePos, 60*60E3); // refesh every 60 mins
2022-07-01 16:30:26 +00:00
updatePos();
2022-06-30 08:15:01 +00:00
}
2022-12-12 16:14:27 +00:00
draw(); // draw immediately, queue redraw
}
2022-12-12 16:14:27 +00:00
};
Bangle.on('lock', onLock);
2022-12-12 16:14:27 +00:00
// Show launcher when middle button pressed
Bangle.setUI({
mode : "custom",clock:true,
remove : function() {
// Called to unload all of the clock app
g.setRotation(defaultRotation); // bring back default rotation
2022-12-12 16:14:27 +00:00
if (typeof PosInterval === "undefined") {
console.log("PosInterval is undefined");
} else {
if (PosInterval) clearInterval(PosInterval);
}
PosInterval = undefined;
if (drawTimeoutSeconds) clearTimeout(drawTimeoutSeconds);
drawTimeoutSeconds = undefined;
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
//if (BANGLEJS2)
Bangle.removeListener("drag",onDrag);
2022-12-12 16:14:27 +00:00
Bangle.removeListener("onLock",onLock);
}});
g.clear().setRotation(defaultRotation); // clean app screen and make sure the default rotation is set
draw(); // draw immediately at first, queue update
2022-12-12 16:14:27 +00:00
Bangle.loadWidgets();
Bangle.drawWidgets();
// );
}