mirror of https://github.com/espruino/BangleApps
Merge branch 'espruino:master' into master
commit
94581314ef
67
apps.json
67
apps.json
|
@ -120,7 +120,7 @@
|
||||||
"version": "0.06",
|
"version": "0.06",
|
||||||
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
|
"description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,messages,notifications",
|
"tags": "tool,system,messages,notifications,gadgetbridge",
|
||||||
"dependencies": {"messages":"app"},
|
"dependencies": {"messages":"app"},
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
@ -327,7 +327,7 @@
|
||||||
"description": "(NOT RECOMMENDED) Displays Gadgetbridge notifications from Android. Please use the 'Android' Bangle.js app instead.",
|
"description": "(NOT RECOMMENDED) Displays Gadgetbridge notifications from Android. Please use the 'Android' Bangle.js app instead.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"tags": "tool,system,android,widget",
|
"tags": "tool,system,android,widget,gadgetbridge",
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
"dependencies": {"notify":"type"},
|
"dependencies": {"notify":"type"},
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
@ -344,7 +344,7 @@
|
||||||
"version":"0.01",
|
"version":"0.01",
|
||||||
"description": "Debug info for Gadgetbridge. Run this app and when Gadgetbridge messages arrive they are displayed on-screen.",
|
"description": "Debug info for Gadgetbridge. Run this app and when Gadgetbridge messages arrive they are displayed on-screen.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "",
|
"tags": "tool,debug,gadgetbridge",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
|
@ -1060,7 +1060,7 @@
|
||||||
"id": "bthrm",
|
"id": "bthrm",
|
||||||
"name": "Bluetooth Heart Rate Monitor",
|
"name": "Bluetooth Heart Rate Monitor",
|
||||||
"shortName": "BT HRM",
|
"shortName": "BT HRM",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.",
|
"description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
@ -1554,7 +1554,7 @@
|
||||||
{
|
{
|
||||||
"id": "assistedgps",
|
"id": "assistedgps",
|
||||||
"name": "Assisted GPS Update (AGPS)",
|
"name": "Assisted GPS Update (AGPS)",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.",
|
"description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "RAM",
|
"type": "RAM",
|
||||||
|
@ -3026,6 +3026,20 @@
|
||||||
],
|
],
|
||||||
"data": [{"wildcard":"accellog.?.csv"}]
|
"data": [{"wildcard":"accellog.?.csv"}]
|
||||||
},
|
},
|
||||||
|
{ "id": "accelgraph",
|
||||||
|
"name": "Accelerometer Graph",
|
||||||
|
"shortName":"Accel Graph",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "A simple app to draw a graph of data from the accelerometer on the screen",
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "tool,debug",
|
||||||
|
"supports" : ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
|
"storage": [
|
||||||
|
{"name":"accelgraph.app.js","url":"app.js"},
|
||||||
|
{"name":"accelgraph.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "cprassist",
|
"id": "cprassist",
|
||||||
"name": "CPR Assist",
|
"name": "CPR Assist",
|
||||||
|
@ -3955,8 +3969,8 @@
|
||||||
"id": "qmsched",
|
"id": "qmsched",
|
||||||
"name": "Quiet Mode Schedule and Widget",
|
"name": "Quiet Mode Schedule and Widget",
|
||||||
"shortName": "Quiet Mode",
|
"shortName": "Quiet Mode",
|
||||||
"version": "0.06",
|
"version": "0.07",
|
||||||
"description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.",
|
"description": "Automatically turn Quiet Mode on or off at set times, change theme and LCD options while Quiet Mode is active.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"},
|
"screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"},
|
||||||
{"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}],
|
{"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}],
|
||||||
|
@ -4297,7 +4311,7 @@
|
||||||
{
|
{
|
||||||
"id": "antonclk",
|
"id": "antonclk",
|
||||||
"name": "Anton Clock",
|
"name": "Anton Clock",
|
||||||
"version": "0.05",
|
"version": "0.06",
|
||||||
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
|
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
|
||||||
"readme":"README.md",
|
"readme":"README.md",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
@ -5187,14 +5201,13 @@
|
||||||
{
|
{
|
||||||
"id": "ftclock",
|
"id": "ftclock",
|
||||||
"name": "Four Twenty Clock",
|
"name": "Four Twenty Clock",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "A clock that tells when and where it's going to be 4:20 next",
|
"description": "A clock that tells when and where it's going to be 4:20 next",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}],
|
"screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}],
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"allow_emulator": true,
|
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"ftclock.app.js","url":"app.js"},
|
{"name":"ftclock.app.js","url":"app.js"},
|
||||||
|
@ -5595,5 +5608,37 @@
|
||||||
"data": [
|
"data": [
|
||||||
{"name":"banglexercise.json"}
|
{"name":"banglexercise.json"}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "widpa",
|
||||||
|
"name": "Simple Pedometer",
|
||||||
|
"shortName":"Simple Pedometer",
|
||||||
|
"icon": "screenshot_widpa.png",
|
||||||
|
"screenshots": [{"url":"screenshot_widpa.png"}],
|
||||||
|
"version":"0.01",
|
||||||
|
"type": "widget",
|
||||||
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in 12x16 font, requires firmware v2.11.21 or later",
|
||||||
|
"tags": "widget,battery",
|
||||||
|
"storage": [
|
||||||
|
{"name":"widpa.wid.js","url":"widpa.wid.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "widpb",
|
||||||
|
"name": "Lato Pedometer",
|
||||||
|
"shortName":"Lato Pedometer",
|
||||||
|
"icon": "screenshot_widpb.png",
|
||||||
|
"screenshots": [{"url":"screenshot_widpb.png"}],
|
||||||
|
"version":"0.01",
|
||||||
|
"type": "widget",
|
||||||
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in the Lato font, requires firmware v2.11.21 or later",
|
||||||
|
"tags": "widget,battery",
|
||||||
|
"storage": [
|
||||||
|
{"name":"widpb.wid.js","url":"widpb.wid.js"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEw4UA/4AB304ief85L/ABNVAAwKCgILHoALBgoLHqALOrVVr4BEBZIFBBYiaCAAPq2oLQEYlqF5VrBZWnBZWvBZNWz4LGBoQLHJ4O///6v/1BZHa/4LFLYOlr9pR49r1ILJ09qr4ZBBY2vrWdBY5PBq2uyoLIquqBY5bBKoZTFLYILJJ4STDBY77IJ4QLUJ4QLU1QAE0oLPqoAGBZ0BBY9ABYMABY4KCAH4AGA="))
|
|
@ -0,0 +1,24 @@
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
g.clear(1);
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
var R = Bangle.appRect;
|
||||||
|
|
||||||
|
var x = 0;
|
||||||
|
var last;
|
||||||
|
|
||||||
|
function getY(v) {
|
||||||
|
return (R.y+R.y2 + v*R.h/2)/2;
|
||||||
|
}
|
||||||
|
Bangle.on('accel', a => {
|
||||||
|
g.reset();
|
||||||
|
if (last) {
|
||||||
|
g.setColor("#f00").drawLine(x-1,getY(last.x),x,getY(a.x));
|
||||||
|
g.setColor("#0f0").drawLine(x-1,getY(last.y),x,getY(a.y));
|
||||||
|
g.setColor("#00f").drawLine(x-1,getY(last.z),x,getY(a.z));
|
||||||
|
}
|
||||||
|
last = a;x++;
|
||||||
|
if (x>=g.getWidth()) {
|
||||||
|
x = 1;
|
||||||
|
g.clearRect(R);
|
||||||
|
}
|
||||||
|
});
|
Binary file not shown.
After Width: | Height: | Size: 944 B |
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
|
@ -5,3 +5,6 @@
|
||||||
0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off)
|
0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off)
|
||||||
when weekday name "Off": week #:<num>
|
when weekday name "Off": week #:<num>
|
||||||
when weekday name "On": weekday name is cut at 6th position and .#<week num> is added
|
when weekday name "On": weekday name is cut at 6th position and .#<week num> is added
|
||||||
|
0.06: fixes #1271 - wrong settings name
|
||||||
|
when weekday name and calendar weeknumber are on then display is <weekday short> #<calweek>
|
||||||
|
week is buffered until date or timezone changes
|
|
@ -40,9 +40,9 @@ The main menu contains several settings covering Anton clock in general.
|
||||||
* **Show Weekday** - Weekday is shown in the time presentation without seconds.
|
* **Show Weekday** - Weekday is shown in the time presentation without seconds.
|
||||||
Weekday name depends on the current locale.
|
Weekday name depends on the current locale.
|
||||||
If seconds are shown, the weekday is never shown as there is not enough space on the watch face.
|
If seconds are shown, the weekday is never shown as there is not enough space on the watch face.
|
||||||
* **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off)
|
* **Show CalWeek** - Week-number (ISO-8601) is shown. (default: Off)
|
||||||
If "Show Weekday" is "Off" the week-number is displayed as "week #:<num>".
|
If "Show Weekday" is "Off" displays the week-number as "week #<num>".
|
||||||
If "Show Weekday" is "On" the weekday name is cut at 6th position and suffixed with ".#<week num>".
|
If "Show Weekday" is "On" displays "weekday name short" with " #<num>" .
|
||||||
If seconds are shown, the week number is never shown as there is not enough space on the watch face.
|
If seconds are shown, the week number is never shown as there is not enough space on the watch face.
|
||||||
* **Vector font** - Use the built-in vector font for dates and weekday.
|
* **Vector font** - Use the built-in vector font for dates and weekday.
|
||||||
This can improve readability.
|
This can improve readability.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Clock with large digits using the "Anton" bold font
|
// Clock with large digits using the "Anton" bold font
|
||||||
|
|
||||||
var SETTINGSFILE = "antonclk.json";
|
const SETTINGSFILE = "antonclk.json";
|
||||||
|
|
||||||
Graphics.prototype.setFontAnton = function(scale) {
|
Graphics.prototype.setFontAnton = function(scale) {
|
||||||
// Actual height 69 (68 - 0)
|
// Actual height 69 (68 - 0)
|
||||||
|
@ -28,7 +28,7 @@ var drawTimeout;
|
||||||
var queueMillis = 1000;
|
var queueMillis = 1000;
|
||||||
var secondsScreen = true;
|
var secondsScreen = true;
|
||||||
|
|
||||||
var isBangle1 = (g.getWidth() == 240);
|
var isBangle1 = (process.env.HWVERSION == 1);
|
||||||
|
|
||||||
//For development purposes
|
//For development purposes
|
||||||
/*
|
/*
|
||||||
|
@ -50,13 +50,11 @@ require('Storage').writeJSON(SETTINGSFILE, {
|
||||||
require('Storage').erase(SETTINGSFILE);
|
require('Storage').erase(SETTINGSFILE);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Helper method for loading the settings
|
|
||||||
function def(value, def) {
|
|
||||||
return (value !== undefined ? value : def);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
|
// Helper function default setting
|
||||||
|
function def (value, def) {return value !== undefined ? value : def;}
|
||||||
|
|
||||||
var settings = require('Storage').readJSON(SETTINGSFILE, true) || {};
|
var settings = require('Storage').readJSON(SETTINGSFILE, true) || {};
|
||||||
secondsMode = def(settings.secondsMode, "Never");
|
secondsMode = def(settings.secondsMode, "Never");
|
||||||
secondsColoured = def(settings.secondsColoured, true);
|
secondsColoured = def(settings.secondsColoured, true);
|
||||||
|
@ -104,7 +102,12 @@ function isoStr(date) {
|
||||||
return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2);
|
return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested)
|
||||||
function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
|
function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
|
||||||
|
dateNoTime = date; dateNoTime.setHours(0,0,0,0);
|
||||||
|
if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2];
|
||||||
|
calWeekBuffer[0] = date.getTimezoneOffset();
|
||||||
|
calWeekBuffer[1] = dateNoTime;
|
||||||
var tdt = new Date(date.valueOf());
|
var tdt = new Date(date.valueOf());
|
||||||
var dayn = (date.getDay() + 6) % 7;
|
var dayn = (date.getDay() + 6) % 7;
|
||||||
tdt.setDate(tdt.getDate() - dayn + 3);
|
tdt.setDate(tdt.getDate() - dayn + 3);
|
||||||
|
@ -113,7 +116,8 @@ function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu
|
||||||
if (tdt.getDay() !== 4) {
|
if (tdt.getDay() !== 4) {
|
||||||
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
|
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
|
||||||
}
|
}
|
||||||
return 1 + Math.ceil((firstThursday - tdt) / 604800000);
|
calWeekBuffer[2] = 1 + Math.ceil((firstThursday - tdt) / 604800000);
|
||||||
|
return calWeekBuffer[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
function doColor() {
|
function doColor() {
|
||||||
|
@ -186,13 +190,17 @@ function draw() {
|
||||||
else
|
else
|
||||||
g.setFont("6x8", 2);
|
g.setFont("6x8", 2);
|
||||||
g.drawString(dateStr, x, y);
|
g.drawString(dateStr, x, y);
|
||||||
if (weekDay || calWeek) {
|
if (calWeek || weekDay) {
|
||||||
var dowwumStr = require("locale").dow(date);
|
var dowcwStr = "";
|
||||||
if (calWeek)
|
if (calWeek)
|
||||||
dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week"
|
dowcwStr = " #" + ("0" + ISO8601calWeek(date)).substring(-2);
|
||||||
|
if (weekDay)
|
||||||
|
dowcwStr = require("locale").dow(date, calWeek ? 1 : 0) + dowcwStr; //weekDay e.g. Monday or weekDayShort #<calWeek> e.g. Mon #01
|
||||||
|
else //week #01
|
||||||
|
dowcwStr = /*LANG*/"week" + dowcwStr;
|
||||||
if (upperCase)
|
if (upperCase)
|
||||||
dowwumStr = dowwumStr.toUpperCase();
|
dowcwStr = dowcwStr.toUpperCase();
|
||||||
g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16));
|
g.drawString(dowcwStr, x, y + (vectorFont ? 26 : 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,11 @@
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Show Weeknumber": {
|
"Show CalWeek": {
|
||||||
value: (settings.weekNum !== undefined ? settings.weekNum : true),
|
value: (settings.calWeek !== undefined ? settings.calWeek : false),
|
||||||
format: v => v ? "On" : "Off",
|
format: v => v ? "On" : "Off",
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.weekNum = v;
|
settings.calWeek = v;
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Update to work with Bangle.js 2
|
0.02: Update to work with Bangle.js 2
|
||||||
|
0.03: Select GNSS systems to use for Bangle.js 2
|
||||||
|
|
|
@ -27,6 +27,31 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="banglejs2-info" style="display:none">
|
<div id="banglejs2-info" style="display:none">
|
||||||
|
<p>Using fewer GNSS systems may decrease the time to fix. (If unsure, select only GPS)</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">Select which GNSS system you want.</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="1" checked><i class="form-icon"></i> GPS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="2"><i class="form-icon"></i> BDS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="3"><i class="form-icon"></i> GPS+BDS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="4"><i class="form-icon"></i> GLONASS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="5"><i class="form-icon"></i> GPS+GLONASS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="6"><i class="form-icon"></i> BDS+GLONASS
|
||||||
|
</label>
|
||||||
|
<label class="form-radio">
|
||||||
|
<input type="radio" name="gnss_select" value="6"><i class="form-icon"></i> GPS+BDS+GLONASS
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p id="upload-wrap" style="display:none">Click <button id="upload" class="btn btn-primary">Upload</button></p>
|
<p id="upload-wrap" style="display:none">Click <button id="upload" class="btn btn-primary">Upload</button></p>
|
||||||
|
|
||||||
|
@ -116,8 +141,13 @@
|
||||||
}
|
}
|
||||||
if (isB2) { // CASIC
|
if (isB2) { // CASIC
|
||||||
|
|
||||||
// Disable BDS, use just GPS (supposedly improve lock time)
|
// Select what GNSS System to use for decreased fix time.
|
||||||
js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,1")}")\n`; // set GPS-only mode
|
var radios = document.getElementsByName('gnss_select');
|
||||||
|
var gnss_select="1";
|
||||||
|
for (var i=0; i<radios.length; i++)
|
||||||
|
if (radios[i].checked)
|
||||||
|
gnss_select=radios[i].value;
|
||||||
|
js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,"+gnss_select)}")\n`; // set GNSS mode
|
||||||
// What about:
|
// What about:
|
||||||
// NAV-TIMEUTC (0x01 0x10)
|
// NAV-TIMEUTC (0x01 0x10)
|
||||||
// NAV-PV (0x01 0x03)
|
// NAV-PV (0x01 0x03)
|
||||||
|
|
|
@ -2,3 +2,6 @@
|
||||||
0.02: Make overriding the HRM event optional
|
0.02: Make overriding the HRM event optional
|
||||||
Emit BTHRM event for external sensor
|
Emit BTHRM event for external sensor
|
||||||
Add recorder app plugin
|
Add recorder app plugin
|
||||||
|
0.03: Prevent readings from internal sensor mixing into BT values
|
||||||
|
Mark events with src property
|
||||||
|
Show actual source of event in app
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
Bangle.isHRMOn = function() {
|
Bangle.isHRMOn = function() {
|
||||||
var settings = require('Storage').readJSON("bthrm.json", true) || {};
|
var settings = require('Storage').readJSON("bthrm.json", true) || {};
|
||||||
|
|
||||||
print(settings);
|
|
||||||
if (settings.enabled && !settings.replace){
|
if (settings.enabled && !settings.replace){
|
||||||
return origIsHRMOn();
|
return origIsHRMOn();
|
||||||
} else if (settings.enabled && settings.replace){
|
} else if (settings.enabled && settings.replace){
|
||||||
|
@ -69,12 +68,10 @@
|
||||||
var interval = dv.getUint16(idx,1); // in milliseconds
|
var interval = dv.getUint16(idx,1); // in milliseconds
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
Bangle.emit(settings.replace?"HRM":"BTHRM", {
|
||||||
var eventName = settings.replace ? "HRM" : "BTHRM";
|
|
||||||
|
|
||||||
Bangle.emit(eventName, {
|
|
||||||
bpm:bpm,
|
bpm:bpm,
|
||||||
confidence:100
|
confidence:100,
|
||||||
|
src:settings.replace?"bthrm":undefined
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return characteristic.startNotifications();
|
return characteristic.startNotifications();
|
||||||
|
@ -107,8 +104,20 @@
|
||||||
if (settings.enabled || !isOn){
|
if (settings.enabled || !isOn){
|
||||||
Bangle.setBTHRMPower(isOn, app);
|
Bangle.setBTHRMPower(isOn, app);
|
||||||
}
|
}
|
||||||
if (settings.enabled && !settings.replace || !isOn){
|
if ((settings.enabled && !settings.replace) || !settings.enabled || !isOn){
|
||||||
origSetHRMPower(isOn, app);
|
origSetHRMPower(isOn, app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var settings = require('Storage').readJSON("bthrm.json", true) || {};
|
||||||
|
if (settings.enabled && settings.replace){
|
||||||
|
if (!(Bangle._PWR===undefined) && !(Bangle._PWR.HRM===undefined)){
|
||||||
|
for (var i = 0; i < Bangle._PWR.HRM.length; i++){
|
||||||
|
var app = Bangle._PWR.HRM[i];
|
||||||
|
origSetHRMPower(0, app);
|
||||||
|
Bangle.setBTHRMPower(1, app);
|
||||||
|
if (Bangle._PWR.HRM===undefined) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -9,13 +9,14 @@ function draw(y, event, type, counter) {
|
||||||
var px = g.getWidth()/2;
|
var px = g.getWidth()/2;
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setFontAlign(0,0);
|
g.setFontAlign(0,0);
|
||||||
g.clearRect(0,y,g.getWidth(),y+80);
|
g.clearRect(0,y,g.getWidth(),y+75);
|
||||||
if (type == null || event == null || counter == 0) return;
|
if (type == null || event == null || counter == 0) return;
|
||||||
var str = event.bpm + "";
|
var str = event.bpm + "";
|
||||||
g.setFontVector(40).drawString(str,px,y+20);
|
g.setFontVector(40).drawString(str,px,y+20);
|
||||||
str = "Confidence: " + event.confidence;
|
str = "Confidence: " + event.confidence;
|
||||||
g.setFontVector(12).drawString(str,px,y+50);
|
g.setFontVector(12).drawString(str,px,y+50);
|
||||||
str = "Event: " + type;
|
str = "Event: " + type;
|
||||||
|
if (type == "HRM") str += " Source: " + (event.src ? event.src : "internal");
|
||||||
g.setFontVector(12).drawString(str,px,y+60);
|
g.setFontVector(12).drawString(str,px,y+60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +36,6 @@ Bangle.on('BTHRM', onBtHrm);
|
||||||
Bangle.on('HRM', onHrm);
|
Bangle.on('HRM', onHrm);
|
||||||
|
|
||||||
Bangle.setHRMPower(1,'bthrm')
|
Bangle.setHRMPower(1,'bthrm')
|
||||||
Bangle.setBTHRMPower(1,'bthrm')
|
|
||||||
|
|
||||||
g.clear();
|
g.clear();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(function(recorders) {
|
(function(recorders) {
|
||||||
recorders.bthrm = function() {
|
recorders.bthrm = function() {
|
||||||
var bpm = 0;
|
var bpm = "";
|
||||||
function onHRM(h) {
|
function onHRM(h) {
|
||||||
bpm = h.bpm;
|
bpm = h.bpm;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
fields : ["BT Heartrate"],
|
fields : ["BT Heartrate"],
|
||||||
getValues : () => {
|
getValues : () => {
|
||||||
result = [bpm];
|
result = [bpm];
|
||||||
bpm = 0;
|
bpm = "";
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
start : () => {
|
start : () => {
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
0.01: first release
|
0.01: first release
|
||||||
|
0.02: RAM efficient version of `fourTwentyTz.js` (as suggested by @gfwilliams).
|
||||||
|
|
|
@ -17,14 +17,13 @@ function queueDraw() {
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setBgColor("#ffffff");
|
|
||||||
let date = new Date();
|
let date = new Date();
|
||||||
let timeStr = require("locale").time(date,1);
|
let timeStr = require("locale").time(date,1);
|
||||||
let next420 = getNextFourTwenty();
|
let next420 = getNextFourTwenty();
|
||||||
g.clearRect(0,26,g.getWidth(),g.getHeight());
|
g.clearRect(0,26,g.getWidth(),g.getHeight());
|
||||||
g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2);
|
g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2);
|
||||||
g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28);
|
g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28);
|
||||||
g.setColor("#000000");
|
g.setColor(g.theme.fg);
|
||||||
g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii");
|
g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii");
|
||||||
g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60);
|
g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
let timezones = require("fourTwentyTz").timezones;
|
let ftz = require("fourTwentyTz"),
|
||||||
|
offsets = ftz.offsets,
|
||||||
|
timezones = ftz.timezones;
|
||||||
|
|
||||||
function get420offset() {
|
function get420offset() {
|
||||||
let current_time = Math.floor((Date.now()%(24*3600*1000))/60000);
|
let current_time = Math.floor((Date.now()%(24*3600*1000))/60000);
|
||||||
|
@ -24,10 +26,10 @@ function makeFourTwentyText(minutes, places) {
|
||||||
|
|
||||||
function getNextFourTwenty() {
|
function getNextFourTwenty() {
|
||||||
let offs = get420offset();
|
let offs = get420offset();
|
||||||
for (let i=0; i<timezones.length; i++) {
|
for (let i=0; i<offsets.length; i++) {
|
||||||
if (timezones[i][0]<=offs) {
|
if (offsets[i]<=offs) {
|
||||||
let minutes = offs-timezones[i][0];
|
let minutes = offs-offsets[i];
|
||||||
let places = timezones[i][1];
|
let places = timezones(offsets[i]);
|
||||||
return {
|
return {
|
||||||
minutes: minutes,
|
minutes: minutes,
|
||||||
places: places,
|
places: places,
|
||||||
|
|
|
@ -1,463 +1,33 @@
|
||||||
// Generated by mkFourTwentyTz.js
|
// Generated by mkFourTwentyTz.js
|
||||||
|
// Wed Jan 12 2022 19:35:36 GMT+0200 (Israel Standard Time)
|
||||||
// Data source: https://timezonedb.com/files/timezonedb.csv.zip
|
// Data source: https://timezonedb.com/files/timezonedb.csv.zip
|
||||||
// Sun Jan 09 2022 13:21:47 GMT+0200 (Israel Standard Time)
|
exports.offsets = [1380,1320,1260,1200,1140,1080,1020,960,900,840,780,720,660,600,540,480,420,360,300,240,180,120,60,0];
|
||||||
exports.timezones = {
|
exports.timezones = function(offs) {
|
||||||
"0": [
|
switch (offs) {
|
||||||
"Troll, Antarctica",
|
case 1380: return ["Cape Verde, Cabo Verde","Scoresbysund, Greenland","Azores, Portugal"];
|
||||||
"Ouagadougou, Burkina Faso",
|
case 1320: return ["Noronha, Brazil","South Georgia, South Georgia and the South Sandwich Islands"];
|
||||||
"Abidjan, Côte d'Ivoire",
|
case 1260: return ["Palmer, Antarctica","Rothera, Antarctica","Buenos Aires, Argentina","Cordoba, Argentina","Salta, Argentina","Jujuy, Argentina","Tucuman, Argentina","Catamarca, Argentina","La Rioja, Argentina","San Juan, Argentina","Mendoza, Argentina","San Luis, Argentina","Rio Gallegos, Argentina","Ushuaia, Argentina","Belem, Brazil","Fortaleza, Brazil","Recife, Brazil","Araguaina, Brazil","Maceio, Brazil","Bahia, Brazil","Sao Paulo, Brazil","Santarem, Brazil","Santiago, Chile","Punta Arenas, Chile","Stanley, Falkland Islands (Malvinas)","Cayenne, French Guiana","Nuuk, Greenland","Miquelon, Saint Pierre and Miquelon","Asuncion, Paraguay","Paramaribo, Suriname","Montevideo, Uruguay"];
|
||||||
"Canary, Spain",
|
case 1200: return ["Antigua, Antigua and Barbuda","Anguilla, Anguilla","Aruba, Aruba","Barbados, Barbados","St Barthelemy, Saint Barthélemy","Bermuda, Bermuda","La Paz, Bolivia (Plurinational State of)","Kralendijk, Bonaire, Sint Eustatius and Saba","Campo Grande, Brazil","Cuiaba, Brazil","Porto Velho, Brazil","Boa Vista, Brazil","Manaus, Brazil","Halifax, Canada","Glace Bay, Canada","Moncton, Canada","Goose Bay, Canada","Blanc-Sablon, Canada","Curacao, Curaçao","Dominica, Dominica","Santo Domingo, Dominican Republic","Grenada, Grenada","Thule, Greenland","Guadeloupe, Guadeloupe","Guyana, Guyana","St Kitts, Saint Kitts and Nevis","St Lucia, Saint Lucia","Marigot, Saint Martin (French part)","Martinique, Martinique","Montserrat, Montserrat","Puerto Rico, Puerto Rico","Lower Princes, Sint Maarten (Dutch part)","Port of_Spain, Trinidad and Tobago","St Vincent, Saint Vincent and the Grenadines","Caracas, Venezuela (Bolivarian Republic of)","Tortola, Virgin Islands (British)","St Thomas, Virgin Islands (U.S.)"];
|
||||||
"Faroe, Faroe Islands",
|
case 1140: return ["Eirunepe, Brazil","Rio Branco, Brazil","Nassau, Bahamas","Toronto, Canada","Nipigon, Canada","Thunder Bay, Canada","Iqaluit, Canada","Pangnirtung, Canada","Atikokan, Canada","Easter, Chile","Bogota, Colombia","Havana, Cuba","Guayaquil, Ecuador","Port-au-Prince, Haiti","Jamaica, Jamaica","Cayman, Cayman Islands","Cancun, Mexico","Panama, Panama","Lima, Peru","Grand Turk, Turks and Caicos Islands","New York, United States of America","Detroit, United States of America","Louisville, Kentucky","Monticello, Kentucky","Indianapolis, Indiana","Vincennes, Indiana","Winamac, Indiana","Marengo, Indiana","Petersburg, Indiana","Vevay, Indiana"];
|
||||||
"London, United Kingdom of Great Britain and Northern Ireland",
|
case 1080: return ["Belize, Belize","Winnipeg, Canada","Rainy River, Canada","Resolute, Canada","Rankin Inlet, Canada","Regina, Canada","Swift Current, Canada","Costa Rica, Costa Rica","Galapagos, Ecuador","Guatemala, Guatemala","Tegucigalpa, Honduras","Mexico City, Mexico","Merida, Mexico","Monterrey, Mexico","Matamoros, Mexico","Bahia Banderas, Mexico","Managua, Nicaragua","El Salvador, El Salvador","Chicago, United States of America","Tell City, Indiana","Knox, Indiana","Menominee, United States of America","Center, North Dakota","New_Salem, North Dakota","Beulah, North Dakota"];
|
||||||
"Guernsey, Guernsey",
|
case 1020: return ["Edmonton, Canada","Cambridge Bay, Canada","Yellowknife, Canada","Inuvik, Canada","Creston, Canada","Dawson Creek, Canada","Fort Nelson, Canada","Whitehorse, Canada","Dawson, Canada","Mazatlan, Mexico","Chihuahua, Mexico","Ojinaga, Mexico","Hermosillo, Mexico","Denver, United States of America","Boise, United States of America","Phoenix, United States of America"];
|
||||||
"Accra, Ghana",
|
case 960: return ["Vancouver, Canada","Tijuana, Mexico","Pitcairn, Pitcairn","Los Angeles, United States of America"];
|
||||||
"Danmarkshavn, Greenland",
|
case 900: return ["Gambier, French Polynesia","Anchorage, United States of America","Juneau, United States of America","Sitka, United States of America","Metlakatla, United States of America","Yakutat, United States of America","Nome, United States of America"];
|
||||||
"Banjul, Gambia",
|
case 840: return ["Rarotonga, Cook Islands","Kiritimati, Kiribati","Tahiti, French Polynesia","Adak, United States of America","Honolulu, United States of America"];
|
||||||
"Conakry, Guinea",
|
case 780: return ["McMurdo, Antarctica","Pago Pago, American Samoa","Fiji, Fiji","Kanton, Kiribati","Niue, Niue","Auckland, New Zealand","Fakaofo, Tokelau","Tongatapu, Tonga","Midway, United States Minor Outlying Islands","Apia, Samoa"];
|
||||||
"Bissau, Guinea-Bissau",
|
case 720: return ["Tarawa, Kiribati","Majuro, Marshall Islands","Kwajalein, Marshall Islands","Norfolk, Norfolk Island","Nauru, Nauru","Kamchatka, Russian Federation","Anadyr, Russian Federation","Funafuti, Tuvalu","Wake, United States Minor Outlying Islands","Wallis, Wallis and Futuna"];
|
||||||
"Dublin, Ireland",
|
case 660: return ["Casey, Antarctica","Lord Howe, Australia","Macquarie, Australia","Hobart, Australia","Melbourne, Australia","Sydney, Australia","Pohnpei, Micronesia (Federated States of)","Kosrae, Micronesia (Federated States of)","Noumea, New Caledonia","Bougainville, Papua New Guinea","Magadan, Russian Federation","Sakhalin, Russian Federation","Srednekolymsk, Russian Federation","Guadalcanal, Solomon Islands","Efate, Vanuatu"];
|
||||||
"Isle of_Man, Isle of Man",
|
case 600: return ["DumontDUrville, Antarctica","Brisbane, Australia","Lindeman, Australia","Chuuk, Micronesia (Federated States of)","Guam, Guam","Saipan, Northern Mariana Islands","Port Moresby, Papua New Guinea","Vladivostok, Russian Federation","Ust-Nera, Russian Federation"];
|
||||||
"Reykjavik, Iceland",
|
case 540: return ["Jayapura, Indonesia","Tokyo, Japan","Pyongyang, Korea (Democratic People's Republic of)","Seoul, Korea, Republic of","Palau, Palau","Chita, Russian Federation","Yakutsk, Russian Federation","Khandyga, Russian Federation","Dili, Timor-Leste"];
|
||||||
"Jersey, Jersey",
|
case 480: return ["Perth, Australia","Brunei, Brunei Darussalam","Shanghai, China","Hong Kong, Hong Kong","Makassar, Indonesia","Ulaanbaatar, Mongolia","Choibalsan, Mongolia","Macau, Macao","Kuala Lumpur, Malaysia","Kuching, Malaysia","Manila, Philippines","Irkutsk, Russian Federation","Singapore, Singapore","Taipei, Taiwan, Province of China"];
|
||||||
"Monrovia, Liberia",
|
case 420: return ["Davis, Antarctica","Christmas, Christmas Island","Jakarta, Indonesia","Pontianak, Indonesia","Phnom Penh, Cambodia","Vientiane, Lao People's Democratic Republic","Hovd, Mongolia","Novosibirsk, Russian Federation","Barnaul, Russian Federation","Tomsk, Russian Federation","Novokuznetsk, Russian Federation","Krasnoyarsk, Russian Federation","Bangkok, Thailand","Ho Chi_Minh, Viet Nam"];
|
||||||
"Bamako, Mali",
|
case 360: return ["Vostok, Antarctica","Dhaka, Bangladesh","Thimphu, Bhutan","Urumqi, China","Chagos, British Indian Ocean Territory","Bishkek, Kyrgyzstan","Almaty, Kazakhstan","Qostanay, Kazakhstan","Omsk, Russian Federation"];
|
||||||
"Nouakchott, Mauritania",
|
case 300: return ["Mawson, Antarctica","Qyzylorda, Kazakhstan","Aqtobe, Kazakhstan","Aqtau, Kazakhstan","Atyrau, Kazakhstan","Oral, Kazakhstan","Maldives, Maldives","Karachi, Pakistan","Yekaterinburg, Russian Federation","Kerguelen, French Southern Territories","Dushanbe, Tajikistan","Ashgabat, Turkmenistan","Samarkand, Uzbekistan","Tashkent, Uzbekistan"];
|
||||||
"Lisbon, Portugal",
|
case 240: return ["Dubai, United Arab Emirates","Yerevan, Armenia","Baku, Azerbaijan","Tbilisi, Georgia","Mauritius, Mauritius","Muscat, Oman","Reunion, Réunion","Astrakhan, Russian Federation","Saratov, Russian Federation","Ulyanovsk, Russian Federation","Samara, Russian Federation","Mahe, Seychelles"];
|
||||||
"Madeira, Portugal",
|
case 180: return ["Syowa, Antarctica","Bahrain, Bahrain","Minsk, Belarus","Djibouti, Djibouti","Asmara, Eritrea","Addis Ababa, Ethiopia","Baghdad, Iraq","Nairobi, Kenya","Comoro, Comoros","Kuwait, Kuwait","Antananarivo, Madagascar","Qatar, Qatar","Moscow, Russian Federation","Simferopol, Ukraine","Kirov, Russian Federation","Volgograd, Russian Federation","Riyadh, Saudi Arabia","Mogadishu, Somalia","Istanbul, Turkey","Dar es_Salaam, Tanzania, United Republic of","Kampala, Uganda","Aden, Yemen","Mayotte, Mayotte"];
|
||||||
"St Helena, Saint Helena, Ascension and Tristan da Cunha",
|
case 120: return ["Mariehamn, Åland Islands","Sofia, Bulgaria","Bujumbura, Burundi","Gaborone, Botswana","Lubumbashi, Congo, Democratic Republic of the","Nicosia, Cyprus","Famagusta, Cyprus","Tallinn, Estonia","Cairo, Egypt","Helsinki, Finland","Athens, Greece","Jerusalem, Israel","Amman, Jordan","Beirut, Lebanon","Maseru, Lesotho","Vilnius, Lithuania","Riga, Latvia","Tripoli, Libya","Chisinau, Moldova, Republic of","Blantyre, Malawi","Maputo, Mozambique","Windhoek, Namibia","Gaza, Palestine, State of","Hebron, Palestine, State of","Bucharest, Romania","Kaliningrad, Russian Federation","Kigali, Rwanda","Khartoum, Sudan","Juba, South Sudan","Damascus, Syrian Arab Republic","Mbabane, Eswatini","Kiev, Ukraine","Uzhgorod, Ukraine","Zaporozhye, Ukraine","Johannesburg, South Africa","Lusaka, Zambia","Harare, Zimbabwe"];
|
||||||
"Freetown, Sierra Leone",
|
case 60: return ["Andorra, Andorra","Tirane, Albania","Luanda, Angola","Vienna, Austria","Sarajevo, Bosnia and Herzegovina","Brussels, Belgium","Porto-Novo, Benin","Kinshasa, Congo, Democratic Republic of the","Bangui, Central African Republic","Brazzaville, Congo","Zurich, Switzerland","Douala, Cameroon","Prague, Czechia","Berlin, Germany","Busingen, Germany","Copenhagen, Denmark","Algiers, Algeria","El Aaiun, Western Sahara","Madrid, Spain","Ceuta, Spain","Paris, France","Libreville, Gabon","Gibraltar, Gibraltar","Malabo, Equatorial Guinea","Zagreb, Croatia","Budapest, Hungary","Rome, Italy","Vaduz, Liechtenstein","Luxembourg, Luxembourg","Casablanca, Morocco","Monaco, Monaco","Podgorica, Montenegro","Skopje, North Macedonia","Malta, Malta","Niamey, Niger","Lagos, Nigeria","Amsterdam, Netherlands","Oslo, Norway","Warsaw, Poland","Belgrade, Serbia","Stockholm, Sweden","Ljubljana, Slovenia","Longyearbyen, Svalbard and Jan Mayen","Bratislava, Slovakia","San Marino, San Marino","Ndjamena, Chad","Tunis, Tunisia","Vatican, Holy See"];
|
||||||
"Dakar, Senegal",
|
case 0: return ["Troll, Antarctica","Ouagadougou, Burkina Faso","Abidjan, Côte d'Ivoire","Canary, Spain","Faroe, Faroe Islands","London, United Kingdom of Great Britain and Northern Ireland","Guernsey, Guernsey","Accra, Ghana","Danmarkshavn, Greenland","Banjul, Gambia","Conakry, Guinea","Bissau, Guinea-Bissau","Dublin, Ireland","Isle of_Man, Isle of Man","Reykjavik, Iceland","Jersey, Jersey","Monrovia, Liberia","Bamako, Mali","Nouakchott, Mauritania","Lisbon, Portugal","Madeira, Portugal","St Helena, Saint Helena, Ascension and Tristan da Cunha","Freetown, Sierra Leone","Dakar, Senegal","Sao Tome, Sao Tome and Principe","Lome, Togo"];
|
||||||
"Sao Tome, Sao Tome and Principe",
|
default: return ["Houston, we have a bug."];
|
||||||
"Lome, Togo"
|
|
||||||
],
|
|
||||||
"60": [
|
|
||||||
"Andorra, Andorra",
|
|
||||||
"Tirane, Albania",
|
|
||||||
"Luanda, Angola",
|
|
||||||
"Vienna, Austria",
|
|
||||||
"Sarajevo, Bosnia and Herzegovina",
|
|
||||||
"Brussels, Belgium",
|
|
||||||
"Porto-Novo, Benin",
|
|
||||||
"Kinshasa, Congo, Democratic Republic of the",
|
|
||||||
"Bangui, Central African Republic",
|
|
||||||
"Brazzaville, Congo",
|
|
||||||
"Zurich, Switzerland",
|
|
||||||
"Douala, Cameroon",
|
|
||||||
"Prague, Czechia",
|
|
||||||
"Berlin, Germany",
|
|
||||||
"Busingen, Germany",
|
|
||||||
"Copenhagen, Denmark",
|
|
||||||
"Algiers, Algeria",
|
|
||||||
"El Aaiun, Western Sahara",
|
|
||||||
"Madrid, Spain",
|
|
||||||
"Ceuta, Spain",
|
|
||||||
"Paris, France",
|
|
||||||
"Libreville, Gabon",
|
|
||||||
"Gibraltar, Gibraltar",
|
|
||||||
"Malabo, Equatorial Guinea",
|
|
||||||
"Zagreb, Croatia",
|
|
||||||
"Budapest, Hungary",
|
|
||||||
"Rome, Italy",
|
|
||||||
"Vaduz, Liechtenstein",
|
|
||||||
"Luxembourg, Luxembourg",
|
|
||||||
"Casablanca, Morocco",
|
|
||||||
"Monaco, Monaco",
|
|
||||||
"Podgorica, Montenegro",
|
|
||||||
"Skopje, North Macedonia",
|
|
||||||
"Malta, Malta",
|
|
||||||
"Niamey, Niger",
|
|
||||||
"Lagos, Nigeria",
|
|
||||||
"Amsterdam, Netherlands",
|
|
||||||
"Oslo, Norway",
|
|
||||||
"Warsaw, Poland",
|
|
||||||
"Belgrade, Serbia",
|
|
||||||
"Stockholm, Sweden",
|
|
||||||
"Ljubljana, Slovenia",
|
|
||||||
"Longyearbyen, Svalbard and Jan Mayen",
|
|
||||||
"Bratislava, Slovakia",
|
|
||||||
"San Marino, San Marino",
|
|
||||||
"Ndjamena, Chad",
|
|
||||||
"Tunis, Tunisia",
|
|
||||||
"Vatican, Holy See"
|
|
||||||
],
|
|
||||||
"120": [
|
|
||||||
"Mariehamn, Åland Islands",
|
|
||||||
"Sofia, Bulgaria",
|
|
||||||
"Bujumbura, Burundi",
|
|
||||||
"Gaborone, Botswana",
|
|
||||||
"Lubumbashi, Congo, Democratic Republic of the",
|
|
||||||
"Nicosia, Cyprus",
|
|
||||||
"Famagusta, Cyprus",
|
|
||||||
"Tallinn, Estonia",
|
|
||||||
"Cairo, Egypt",
|
|
||||||
"Helsinki, Finland",
|
|
||||||
"Athens, Greece",
|
|
||||||
"Jerusalem, Israel",
|
|
||||||
"Amman, Jordan",
|
|
||||||
"Beirut, Lebanon",
|
|
||||||
"Maseru, Lesotho",
|
|
||||||
"Vilnius, Lithuania",
|
|
||||||
"Riga, Latvia",
|
|
||||||
"Tripoli, Libya",
|
|
||||||
"Chisinau, Moldova, Republic of",
|
|
||||||
"Blantyre, Malawi",
|
|
||||||
"Maputo, Mozambique",
|
|
||||||
"Windhoek, Namibia",
|
|
||||||
"Gaza, Palestine, State of",
|
|
||||||
"Hebron, Palestine, State of",
|
|
||||||
"Bucharest, Romania",
|
|
||||||
"Kaliningrad, Russian Federation",
|
|
||||||
"Kigali, Rwanda",
|
|
||||||
"Khartoum, Sudan",
|
|
||||||
"Juba, South Sudan",
|
|
||||||
"Damascus, Syrian Arab Republic",
|
|
||||||
"Mbabane, Eswatini",
|
|
||||||
"Kiev, Ukraine",
|
|
||||||
"Uzhgorod, Ukraine",
|
|
||||||
"Zaporozhye, Ukraine",
|
|
||||||
"Johannesburg, South Africa",
|
|
||||||
"Lusaka, Zambia",
|
|
||||||
"Harare, Zimbabwe"
|
|
||||||
],
|
|
||||||
"180": [
|
|
||||||
"Syowa, Antarctica",
|
|
||||||
"Bahrain, Bahrain",
|
|
||||||
"Minsk, Belarus",
|
|
||||||
"Djibouti, Djibouti",
|
|
||||||
"Asmara, Eritrea",
|
|
||||||
"Addis Ababa, Ethiopia",
|
|
||||||
"Baghdad, Iraq",
|
|
||||||
"Nairobi, Kenya",
|
|
||||||
"Comoro, Comoros",
|
|
||||||
"Kuwait, Kuwait",
|
|
||||||
"Antananarivo, Madagascar",
|
|
||||||
"Qatar, Qatar",
|
|
||||||
"Moscow, Russian Federation",
|
|
||||||
"Simferopol, Ukraine",
|
|
||||||
"Kirov, Russian Federation",
|
|
||||||
"Volgograd, Russian Federation",
|
|
||||||
"Riyadh, Saudi Arabia",
|
|
||||||
"Mogadishu, Somalia",
|
|
||||||
"Istanbul, Turkey",
|
|
||||||
"Dar es_Salaam, Tanzania, United Republic of",
|
|
||||||
"Kampala, Uganda",
|
|
||||||
"Aden, Yemen",
|
|
||||||
"Mayotte, Mayotte"
|
|
||||||
],
|
|
||||||
"240": [
|
|
||||||
"Dubai, United Arab Emirates",
|
|
||||||
"Yerevan, Armenia",
|
|
||||||
"Baku, Azerbaijan",
|
|
||||||
"Tbilisi, Georgia",
|
|
||||||
"Mauritius, Mauritius",
|
|
||||||
"Muscat, Oman",
|
|
||||||
"Reunion, Réunion",
|
|
||||||
"Astrakhan, Russian Federation",
|
|
||||||
"Saratov, Russian Federation",
|
|
||||||
"Ulyanovsk, Russian Federation",
|
|
||||||
"Samara, Russian Federation",
|
|
||||||
"Mahe, Seychelles"
|
|
||||||
],
|
|
||||||
"300": [
|
|
||||||
"Mawson, Antarctica",
|
|
||||||
"Qyzylorda, Kazakhstan",
|
|
||||||
"Aqtobe, Kazakhstan",
|
|
||||||
"Aqtau, Kazakhstan",
|
|
||||||
"Atyrau, Kazakhstan",
|
|
||||||
"Oral, Kazakhstan",
|
|
||||||
"Maldives, Maldives",
|
|
||||||
"Karachi, Pakistan",
|
|
||||||
"Yekaterinburg, Russian Federation",
|
|
||||||
"Kerguelen, French Southern Territories",
|
|
||||||
"Dushanbe, Tajikistan",
|
|
||||||
"Ashgabat, Turkmenistan",
|
|
||||||
"Samarkand, Uzbekistan",
|
|
||||||
"Tashkent, Uzbekistan"
|
|
||||||
],
|
|
||||||
"360": [
|
|
||||||
"Vostok, Antarctica",
|
|
||||||
"Dhaka, Bangladesh",
|
|
||||||
"Thimphu, Bhutan",
|
|
||||||
"Urumqi, China",
|
|
||||||
"Chagos, British Indian Ocean Territory",
|
|
||||||
"Bishkek, Kyrgyzstan",
|
|
||||||
"Almaty, Kazakhstan",
|
|
||||||
"Qostanay, Kazakhstan",
|
|
||||||
"Omsk, Russian Federation"
|
|
||||||
],
|
|
||||||
"420": [
|
|
||||||
"Davis, Antarctica",
|
|
||||||
"Christmas, Christmas Island",
|
|
||||||
"Jakarta, Indonesia",
|
|
||||||
"Pontianak, Indonesia",
|
|
||||||
"Phnom Penh, Cambodia",
|
|
||||||
"Vientiane, Lao People's Democratic Republic",
|
|
||||||
"Hovd, Mongolia",
|
|
||||||
"Novosibirsk, Russian Federation",
|
|
||||||
"Barnaul, Russian Federation",
|
|
||||||
"Tomsk, Russian Federation",
|
|
||||||
"Novokuznetsk, Russian Federation",
|
|
||||||
"Krasnoyarsk, Russian Federation",
|
|
||||||
"Bangkok, Thailand",
|
|
||||||
"Ho Chi_Minh, Viet Nam"
|
|
||||||
],
|
|
||||||
"480": [
|
|
||||||
"Perth, Australia",
|
|
||||||
"Brunei, Brunei Darussalam",
|
|
||||||
"Shanghai, China",
|
|
||||||
"Hong Kong, Hong Kong",
|
|
||||||
"Makassar, Indonesia",
|
|
||||||
"Ulaanbaatar, Mongolia",
|
|
||||||
"Choibalsan, Mongolia",
|
|
||||||
"Macau, Macao",
|
|
||||||
"Kuala Lumpur, Malaysia",
|
|
||||||
"Kuching, Malaysia",
|
|
||||||
"Manila, Philippines",
|
|
||||||
"Irkutsk, Russian Federation",
|
|
||||||
"Singapore, Singapore",
|
|
||||||
"Taipei, Taiwan, Province of China"
|
|
||||||
],
|
|
||||||
"540": [
|
|
||||||
"Jayapura, Indonesia",
|
|
||||||
"Tokyo, Japan",
|
|
||||||
"Pyongyang, Korea (Democratic People's Republic of)",
|
|
||||||
"Seoul, Korea, Republic of",
|
|
||||||
"Palau, Palau",
|
|
||||||
"Chita, Russian Federation",
|
|
||||||
"Yakutsk, Russian Federation",
|
|
||||||
"Khandyga, Russian Federation",
|
|
||||||
"Dili, Timor-Leste"
|
|
||||||
],
|
|
||||||
"600": [
|
|
||||||
"DumontDUrville, Antarctica",
|
|
||||||
"Brisbane, Australia",
|
|
||||||
"Lindeman, Australia",
|
|
||||||
"Chuuk, Micronesia (Federated States of)",
|
|
||||||
"Guam, Guam",
|
|
||||||
"Saipan, Northern Mariana Islands",
|
|
||||||
"Port Moresby, Papua New Guinea",
|
|
||||||
"Vladivostok, Russian Federation",
|
|
||||||
"Ust-Nera, Russian Federation"
|
|
||||||
],
|
|
||||||
"660": [
|
|
||||||
"Casey, Antarctica",
|
|
||||||
"Lord Howe, Australia",
|
|
||||||
"Macquarie, Australia",
|
|
||||||
"Hobart, Australia",
|
|
||||||
"Melbourne, Australia",
|
|
||||||
"Sydney, Australia",
|
|
||||||
"Pohnpei, Micronesia (Federated States of)",
|
|
||||||
"Kosrae, Micronesia (Federated States of)",
|
|
||||||
"Noumea, New Caledonia",
|
|
||||||
"Bougainville, Papua New Guinea",
|
|
||||||
"Magadan, Russian Federation",
|
|
||||||
"Sakhalin, Russian Federation",
|
|
||||||
"Srednekolymsk, Russian Federation",
|
|
||||||
"Guadalcanal, Solomon Islands",
|
|
||||||
"Efate, Vanuatu"
|
|
||||||
],
|
|
||||||
"720": [
|
|
||||||
"Tarawa, Kiribati",
|
|
||||||
"Majuro, Marshall Islands",
|
|
||||||
"Kwajalein, Marshall Islands",
|
|
||||||
"Norfolk, Norfolk Island",
|
|
||||||
"Nauru, Nauru",
|
|
||||||
"Kamchatka, Russian Federation",
|
|
||||||
"Anadyr, Russian Federation",
|
|
||||||
"Funafuti, Tuvalu",
|
|
||||||
"Wake, United States Minor Outlying Islands",
|
|
||||||
"Wallis, Wallis and Futuna"
|
|
||||||
],
|
|
||||||
"780": [
|
|
||||||
"McMurdo, Antarctica",
|
|
||||||
"Pago Pago, American Samoa",
|
|
||||||
"Fiji, Fiji",
|
|
||||||
"Kanton, Kiribati",
|
|
||||||
"Niue, Niue",
|
|
||||||
"Auckland, New Zealand",
|
|
||||||
"Fakaofo, Tokelau",
|
|
||||||
"Tongatapu, Tonga",
|
|
||||||
"Midway, United States Minor Outlying Islands",
|
|
||||||
"Apia, Samoa"
|
|
||||||
],
|
|
||||||
"840": [
|
|
||||||
"Rarotonga, Cook Islands",
|
|
||||||
"Kiritimati, Kiribati",
|
|
||||||
"Tahiti, French Polynesia",
|
|
||||||
"Adak, United States of America",
|
|
||||||
"Honolulu, United States of America"
|
|
||||||
],
|
|
||||||
"900": [
|
|
||||||
"Gambier, French Polynesia",
|
|
||||||
"Anchorage, United States of America",
|
|
||||||
"Juneau, United States of America",
|
|
||||||
"Sitka, United States of America",
|
|
||||||
"Metlakatla, United States of America",
|
|
||||||
"Yakutat, United States of America",
|
|
||||||
"Nome, United States of America"
|
|
||||||
],
|
|
||||||
"960": [
|
|
||||||
"Vancouver, Canada",
|
|
||||||
"Tijuana, Mexico",
|
|
||||||
"Pitcairn, Pitcairn",
|
|
||||||
"Los Angeles, United States of America"
|
|
||||||
],
|
|
||||||
"1020": [
|
|
||||||
"Edmonton, Canada",
|
|
||||||
"Cambridge Bay, Canada",
|
|
||||||
"Yellowknife, Canada",
|
|
||||||
"Inuvik, Canada",
|
|
||||||
"Creston, Canada",
|
|
||||||
"Dawson Creek, Canada",
|
|
||||||
"Fort Nelson, Canada",
|
|
||||||
"Whitehorse, Canada",
|
|
||||||
"Dawson, Canada",
|
|
||||||
"Mazatlan, Mexico",
|
|
||||||
"Chihuahua, Mexico",
|
|
||||||
"Ojinaga, Mexico",
|
|
||||||
"Hermosillo, Mexico",
|
|
||||||
"Denver, United States of America",
|
|
||||||
"Boise, United States of America",
|
|
||||||
"Phoenix, United States of America"
|
|
||||||
],
|
|
||||||
"1080": [
|
|
||||||
"Belize, Belize",
|
|
||||||
"Winnipeg, Canada",
|
|
||||||
"Rainy River, Canada",
|
|
||||||
"Resolute, Canada",
|
|
||||||
"Rankin Inlet, Canada",
|
|
||||||
"Regina, Canada",
|
|
||||||
"Swift Current, Canada",
|
|
||||||
"Costa Rica, Costa Rica",
|
|
||||||
"Galapagos, Ecuador",
|
|
||||||
"Guatemala, Guatemala",
|
|
||||||
"Tegucigalpa, Honduras",
|
|
||||||
"Mexico City, Mexico",
|
|
||||||
"Merida, Mexico",
|
|
||||||
"Monterrey, Mexico",
|
|
||||||
"Matamoros, Mexico",
|
|
||||||
"Bahia Banderas, Mexico",
|
|
||||||
"Managua, Nicaragua",
|
|
||||||
"El Salvador, El Salvador",
|
|
||||||
"Chicago, United States of America",
|
|
||||||
"Tell City, Indiana",
|
|
||||||
"Knox, Indiana",
|
|
||||||
"Menominee, United States of America",
|
|
||||||
"Center, North Dakota",
|
|
||||||
"New_Salem, North Dakota",
|
|
||||||
"Beulah, North Dakota"
|
|
||||||
],
|
|
||||||
"1140": [
|
|
||||||
"Eirunepe, Brazil",
|
|
||||||
"Rio Branco, Brazil",
|
|
||||||
"Nassau, Bahamas",
|
|
||||||
"Toronto, Canada",
|
|
||||||
"Nipigon, Canada",
|
|
||||||
"Thunder Bay, Canada",
|
|
||||||
"Iqaluit, Canada",
|
|
||||||
"Pangnirtung, Canada",
|
|
||||||
"Atikokan, Canada",
|
|
||||||
"Easter, Chile",
|
|
||||||
"Bogota, Colombia",
|
|
||||||
"Havana, Cuba",
|
|
||||||
"Guayaquil, Ecuador",
|
|
||||||
"Port-au-Prince, Haiti",
|
|
||||||
"Jamaica, Jamaica",
|
|
||||||
"Cayman, Cayman Islands",
|
|
||||||
"Cancun, Mexico",
|
|
||||||
"Panama, Panama",
|
|
||||||
"Lima, Peru",
|
|
||||||
"Grand Turk, Turks and Caicos Islands",
|
|
||||||
"New York, United States of America",
|
|
||||||
"Detroit, United States of America",
|
|
||||||
"Louisville, Kentucky",
|
|
||||||
"Monticello, Kentucky",
|
|
||||||
"Indianapolis, Indiana",
|
|
||||||
"Vincennes, Indiana",
|
|
||||||
"Winamac, Indiana",
|
|
||||||
"Marengo, Indiana",
|
|
||||||
"Petersburg, Indiana",
|
|
||||||
"Vevay, Indiana"
|
|
||||||
],
|
|
||||||
"1200": [
|
|
||||||
"Antigua, Antigua and Barbuda",
|
|
||||||
"Anguilla, Anguilla",
|
|
||||||
"Aruba, Aruba",
|
|
||||||
"Barbados, Barbados",
|
|
||||||
"St Barthelemy, Saint Barthélemy",
|
|
||||||
"Bermuda, Bermuda",
|
|
||||||
"La Paz, Bolivia (Plurinational State of)",
|
|
||||||
"Kralendijk, Bonaire, Sint Eustatius and Saba",
|
|
||||||
"Campo Grande, Brazil",
|
|
||||||
"Cuiaba, Brazil",
|
|
||||||
"Porto Velho, Brazil",
|
|
||||||
"Boa Vista, Brazil",
|
|
||||||
"Manaus, Brazil",
|
|
||||||
"Halifax, Canada",
|
|
||||||
"Glace Bay, Canada",
|
|
||||||
"Moncton, Canada",
|
|
||||||
"Goose Bay, Canada",
|
|
||||||
"Blanc-Sablon, Canada",
|
|
||||||
"Curacao, Curaçao",
|
|
||||||
"Dominica, Dominica",
|
|
||||||
"Santo Domingo, Dominican Republic",
|
|
||||||
"Grenada, Grenada",
|
|
||||||
"Thule, Greenland",
|
|
||||||
"Guadeloupe, Guadeloupe",
|
|
||||||
"Guyana, Guyana",
|
|
||||||
"St Kitts, Saint Kitts and Nevis",
|
|
||||||
"St Lucia, Saint Lucia",
|
|
||||||
"Marigot, Saint Martin (French part)",
|
|
||||||
"Martinique, Martinique",
|
|
||||||
"Montserrat, Montserrat",
|
|
||||||
"Puerto Rico, Puerto Rico",
|
|
||||||
"Lower Princes, Sint Maarten (Dutch part)",
|
|
||||||
"Port of_Spain, Trinidad and Tobago",
|
|
||||||
"St Vincent, Saint Vincent and the Grenadines",
|
|
||||||
"Caracas, Venezuela (Bolivarian Republic of)",
|
|
||||||
"Tortola, Virgin Islands (British)",
|
|
||||||
"St Thomas, Virgin Islands (U.S.)"
|
|
||||||
],
|
|
||||||
"1260": [
|
|
||||||
"Palmer, Antarctica",
|
|
||||||
"Rothera, Antarctica",
|
|
||||||
"Buenos Aires, Argentina",
|
|
||||||
"Cordoba, Argentina",
|
|
||||||
"Salta, Argentina",
|
|
||||||
"Jujuy, Argentina",
|
|
||||||
"Tucuman, Argentina",
|
|
||||||
"Catamarca, Argentina",
|
|
||||||
"La Rioja, Argentina",
|
|
||||||
"San Juan, Argentina",
|
|
||||||
"Mendoza, Argentina",
|
|
||||||
"San Luis, Argentina",
|
|
||||||
"Rio Gallegos, Argentina",
|
|
||||||
"Ushuaia, Argentina",
|
|
||||||
"Belem, Brazil",
|
|
||||||
"Fortaleza, Brazil",
|
|
||||||
"Recife, Brazil",
|
|
||||||
"Araguaina, Brazil",
|
|
||||||
"Maceio, Brazil",
|
|
||||||
"Bahia, Brazil",
|
|
||||||
"Sao Paulo, Brazil",
|
|
||||||
"Santarem, Brazil",
|
|
||||||
"Santiago, Chile",
|
|
||||||
"Punta Arenas, Chile",
|
|
||||||
"Stanley, Falkland Islands (Malvinas)",
|
|
||||||
"Cayenne, French Guiana",
|
|
||||||
"Nuuk, Greenland",
|
|
||||||
"Miquelon, Saint Pierre and Miquelon",
|
|
||||||
"Asuncion, Paraguay",
|
|
||||||
"Paramaribo, Suriname",
|
|
||||||
"Montevideo, Uruguay"
|
|
||||||
],
|
|
||||||
"1320": [
|
|
||||||
"Noronha, Brazil",
|
|
||||||
"South Georgia, South Georgia and the South Sandwich Islands"
|
|
||||||
],
|
|
||||||
"1380": [
|
|
||||||
"Cape Verde, Cabo Verde",
|
|
||||||
"Scoresbysund, Greenland",
|
|
||||||
"Azores, Portugal"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -57,6 +57,10 @@ fs.createReadStream(__dirname+'/country.csv')
|
||||||
zonelist.push(zone.name);
|
zonelist.push(zone.name);
|
||||||
offsdict[zone.offs] = zonelist;
|
offsdict[zone.offs] = zonelist;
|
||||||
}
|
}
|
||||||
|
offsets = [];
|
||||||
|
for (o in offsdict) {
|
||||||
|
offsets.unshift(parseInt(o));
|
||||||
|
}
|
||||||
fs.open("fourTwentyTz.js","w", (err, fd) => {
|
fs.open("fourTwentyTz.js","w", (err, fd) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log("Can't open output file");
|
console.log("Can't open output file");
|
||||||
|
@ -65,8 +69,18 @@ fs.createReadStream(__dirname+'/country.csv')
|
||||||
fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite);
|
fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite);
|
||||||
fs.write(fd, `// ${Date()}\n`, handleWrite);
|
fs.write(fd, `// ${Date()}\n`, handleWrite);
|
||||||
fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite);
|
fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite);
|
||||||
fs.write(fd, "exports.timezones = ", handleWrite);
|
fs.write(fd, "exports.offsets = ", handleWrite);
|
||||||
fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite);
|
fs.write(fd, JSON.stringify(offsets), handleWrite);
|
||||||
|
fs.write(fd, ";\n", handleWrite);
|
||||||
|
fs.write(fd, "exports.timezones = function(offs) {\n", handleWrite);
|
||||||
|
fs.write(fd, " switch (offs) {\n", handleWrite);
|
||||||
|
for (i=0; i<offsets.length; i++) {
|
||||||
|
let o = offsets[i].toString();
|
||||||
|
fs.write(fd, ` case ${o}: return ${JSON.stringify(offsdict[o])};\n`, handleWrite);
|
||||||
|
}
|
||||||
|
fs.write(fd, " default: return [\"Houston, we have a bug.\"];\n", handleWrite);
|
||||||
|
fs.write(fd, " }\n", handleWrite);
|
||||||
|
fs.write(fd, "};\n", handleWrite);
|
||||||
console.log('Done.');
|
console.log('Done.');
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,3 +4,5 @@
|
||||||
0.04: Move Quiet Mode LCD options from global settings to this app
|
0.04: Move Quiet Mode LCD options from global settings to this app
|
||||||
0.05: Avoid immediately redrawing widgets on load
|
0.05: Avoid immediately redrawing widgets on load
|
||||||
0.06: Fix: don't try to redraw widget when widgets not loaded
|
0.06: Fix: don't try to redraw widget when widgets not loaded
|
||||||
|
0.07: Option to switch theme
|
||||||
|
Changed time selection to 5-minute intervals
|
|
@ -9,6 +9,11 @@ Automatically turn Quiet Mode on or off at set times, and display a widget when
|
||||||
|  |  |
|
|  |  |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
|
### Switch Theme:
|
||||||
|
|
||||||
|
Switch to dark theme during Quiet Mode.
|
||||||
|
* **NOTE**: This switches between the default "Dark BW" and "Light BW" themes, so custom theme settings will be lost.
|
||||||
|
|
||||||
### LCD Settings:
|
### LCD Settings:
|
||||||
|
|
||||||
If set, these override the default LCD settings while Quiet Mode is active.
|
If set, these override the default LCD settings while Quiet Mode is active.
|
|
@ -3,7 +3,7 @@ Bangle.drawWidgets();
|
||||||
|
|
||||||
const modeNames = ["Off", "Alarms", "Silent"];
|
const modeNames = ["Off", "Alarms", "Silent"];
|
||||||
|
|
||||||
// load global brightness setting
|
// load global settings
|
||||||
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
||||||
let current = 0|bSettings.quiet;
|
let current = 0|bSettings.quiet;
|
||||||
delete bSettings; // we don't need any other global settings
|
delete bSettings; // we don't need any other global settings
|
||||||
|
@ -18,6 +18,7 @@ delete bSettings; // we don't need any other global settings
|
||||||
*/
|
*/
|
||||||
function save() {
|
function save() {
|
||||||
require('Storage').writeJSON('qmsched.json', settings);
|
require('Storage').writeJSON('qmsched.json', settings);
|
||||||
|
eval(require('Storage').read('qmsched.boot.js')); // apply new schedules right away
|
||||||
}
|
}
|
||||||
function get(key, def) {
|
function get(key, def) {
|
||||||
return (key in settings) ? settings[key] : def;
|
return (key in settings) ? settings[key] : def;
|
||||||
|
@ -77,37 +78,66 @@ function formatTime(t) {
|
||||||
const mins = Math.round((t-hrs)*60);
|
const mins = Math.round((t-hrs)*60);
|
||||||
return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2);
|
return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Apply theme
|
||||||
|
*/
|
||||||
|
function applyTheme() {
|
||||||
|
const theme = (require("Storage").readJSON("setting.json", 1) || {}).theme;
|
||||||
|
if (theme && theme.dark===g.theme.dark) return; // already correct
|
||||||
|
g.theme = theme;
|
||||||
|
delete g.reset;
|
||||||
|
g._reset = g.reset;
|
||||||
|
g.reset = function(n) { return g._reset().setColor(g.theme.fg).setBgColor(g.theme.bg); };
|
||||||
|
g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); };
|
||||||
|
g.clear(1);
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
delete m.lastIdx; // force redraw
|
||||||
|
m.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Library uses this to make the app update itself
|
||||||
|
* @param {int} mode New Quite Mode
|
||||||
|
*/
|
||||||
|
function setAppMode(mode) {
|
||||||
|
if (mode === current) return;
|
||||||
|
current = mode;
|
||||||
|
delete m.lastIdx; // force redraw
|
||||||
|
applyTheme();
|
||||||
|
if (m.lastIdx===undefined) m.draw(); // applyTheme didn't redraw menu, but we need to show updated mode
|
||||||
|
}
|
||||||
|
|
||||||
|
let m;
|
||||||
function showMainMenu() {
|
function showMainMenu() {
|
||||||
let _m, menu = {
|
let menu = {
|
||||||
"": {"title": "Quiet Mode"},
|
"": {"title": "Quiet Mode"},
|
||||||
"< Exit": () => load()
|
"< Exit": () => load()
|
||||||
};
|
};
|
||||||
// "Current Mode""Silent" won't fit on Bangle.js 2
|
// "Current Mode""Silent" won't fit on Bangle.js 2
|
||||||
menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = {
|
menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = {
|
||||||
value: current,
|
value: current,
|
||||||
format: v => modeNames[v],
|
min:0, max:2, wrap: true,
|
||||||
onchange: function(v) {
|
format: () => modeNames[current],
|
||||||
if (v<0) {v = 2;}
|
onchange: require("qmsched").setMode, // library calls setAppMode(), which updates `current`
|
||||||
if (v>2) {v = 0;}
|
|
||||||
require("qmsched").setMode(v);
|
|
||||||
current = v;
|
|
||||||
this.value = v;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
scheds.sort((a, b) => (a.hr-b.hr));
|
scheds.sort((a, b) => (a.hr-b.hr));
|
||||||
scheds.forEach((sched, idx) => {
|
scheds.forEach((sched, idx) => {
|
||||||
menu[formatTime(sched.hr)] = {
|
menu[formatTime(sched.hr)] = {
|
||||||
format: () => modeNames[sched.mode], // abuse format to right-align text
|
format: () => modeNames[sched.mode], // abuse format to right-align text
|
||||||
onchange: function() {
|
onchange: () => {
|
||||||
_m.draw = ()=> {}; // prevent redraw of main menu over edit menu
|
m.draw = ()=> {}; // prevent redraw of main menu over edit menu (needed because we abuse format/onchange)
|
||||||
showEditMenu(idx);
|
showEditMenu(idx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
menu["Add Schedule"] = () => showEditMenu(-1);
|
menu["Add Schedule"] = () => showEditMenu(-1);
|
||||||
|
menu["Switch Theme"] = {
|
||||||
|
value: !!get("switchTheme"),
|
||||||
|
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||||
|
onchange: v => v ? set("switchTheme", v) : unset("switchTheme"),
|
||||||
|
};
|
||||||
menu["LCD Settings"] = () => showOptionsMenu();
|
menu["LCD Settings"] = () => showOptionsMenu();
|
||||||
_m = E.showMenu(menu);
|
m = E.showMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showEditMenu(index) {
|
function showEditMenu(index) {
|
||||||
|
@ -125,31 +155,19 @@ function showEditMenu(index) {
|
||||||
"< Cancel": () => showMainMenu(),
|
"< Cancel": () => showMainMenu(),
|
||||||
"Hours": {
|
"Hours": {
|
||||||
value: hrs,
|
value: hrs,
|
||||||
onchange: function(v) {
|
min:0, max:23, wrap:true,
|
||||||
if (v<0) {v = 23;}
|
onchange: v => {hrs = v;},
|
||||||
if (v>23) {v = 0;}
|
|
||||||
hrs = v;
|
|
||||||
this.value = v;
|
|
||||||
}, // no arrow fn -> preserve 'this'
|
|
||||||
},
|
},
|
||||||
"Minutes": {
|
"Minutes": {
|
||||||
value: mins,
|
value: mins,
|
||||||
onchange: function(v) {
|
min:0, max:55, step:5, wrap:true,
|
||||||
if (v<0) {v = 59;}
|
onchange: v => {mins = v;},
|
||||||
if (v>59) {v = 0;}
|
|
||||||
mins = v;
|
|
||||||
this.value = v;
|
|
||||||
}, // no arrow fn -> preserve 'this'
|
|
||||||
},
|
},
|
||||||
"Switch to": {
|
"Switch to": {
|
||||||
value: mode,
|
value: mode,
|
||||||
|
min:0, max:2, wrap:true,
|
||||||
format: v => modeNames[v],
|
format: v => modeNames[v],
|
||||||
onchange: function(v) {
|
onchange: v => {mode = v;},
|
||||||
if (v<0) {v = 2;}
|
|
||||||
if (v>2) {v = 0;}
|
|
||||||
mode = v;
|
|
||||||
this.value = v;
|
|
||||||
}, // no arrow fn -> preserve 'this'
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
function getSched() {
|
function getSched() {
|
||||||
|
@ -174,7 +192,7 @@ function showEditMenu(index) {
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return E.showMenu(menu);
|
m = E.showMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showOptionsMenu() {
|
function showOptionsMenu() {
|
||||||
|
@ -244,7 +262,7 @@ function showOptionsMenu() {
|
||||||
onchange: () => {toggle("wakeOnTwist");},
|
onchange: () => {toggle("wakeOnTwist");},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return E.showMenu(oMenu);
|
m = E.showMenu(oMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// apply Quiet Mode schedules
|
// apply Quiet Mode schedules
|
||||||
(function qm() {
|
(function qm() {
|
||||||
|
if (Bangle.qmTimeout) clearTimeout(Bangle.qmTimeout); // so the app can eval() this file to apply changes right away
|
||||||
|
delete Bangle.qmTimeout;
|
||||||
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
let bSettings = require('Storage').readJSON('setting.json',true)||{};
|
||||||
const curr = 0|bSettings.quiet;
|
const curr = 0|bSettings.quiet;
|
||||||
delete bSettings;
|
delete bSettings;
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
let t = 3600000*(next.hr-hr); // timeout in milliseconds
|
let t = 3600000*(next.hr-hr); // timeout in milliseconds
|
||||||
if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day
|
if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day
|
||||||
/* update quiet mode at the correct time. */
|
/* update quiet mode at the correct time. */
|
||||||
setTimeout(() => {
|
Bangle.qmTimeout=setTimeout(() => {
|
||||||
require("qmsched").setMode(mode);
|
require("qmsched").setMode(mode);
|
||||||
qm(); // schedule next update
|
qm(); // schedule next update
|
||||||
}, t);
|
}, t);
|
||||||
|
|
|
@ -1,5 +1,37 @@
|
||||||
/**
|
/**
|
||||||
* Apply LCD options for given mode
|
* Apply appropriate theme for given mode
|
||||||
|
* @param {int} mode Quiet Mode
|
||||||
|
*/
|
||||||
|
function switchTheme(mode) {
|
||||||
|
if (!!mode === g.theme.dark) return; // nothing to do
|
||||||
|
let s = require("Storage").readJSON("setting.json", 1) || {};
|
||||||
|
// default themes, copied from settings.js:showThemeMenu()
|
||||||
|
function cl(x) { return g.setColor(x).getColor(); }
|
||||||
|
s.theme = mode ? {
|
||||||
|
// 'Dark BW'
|
||||||
|
fg: cl("#fff"), bg: cl("#000"),
|
||||||
|
fg2: cl("#0ff"), bg2: cl("#000"),
|
||||||
|
fgH: cl("#fff"), bgH: cl("#00f"),
|
||||||
|
dark: true
|
||||||
|
} : {
|
||||||
|
// 'Light BW'
|
||||||
|
fg: cl("#000"), bg: cl("#fff"),
|
||||||
|
fg2: cl("#000"), bg2: cl("#cff"),
|
||||||
|
fgH: cl("#000"), bgH: cl("#0ff"),
|
||||||
|
dark: false
|
||||||
|
};
|
||||||
|
require("Storage").writeJSON("setting.json", s);
|
||||||
|
if (typeof __FILE__ === 'string') { // undefined means it loaded the default clock
|
||||||
|
const info = require("Storage").readJSON(__FILE__.split(".")[0]+".info", 1);
|
||||||
|
if (info && info.type!=="clock") { // info can have no type (but then it isn't a clock)
|
||||||
|
return; // not a clock: wait for user to switch apps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// current app is a clock: reload it with new theme
|
||||||
|
load(global.__FILE__);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Apply LCD options and theme for given mode
|
||||||
* @param {int} mode Quiet Mode
|
* @param {int} mode Quiet Mode
|
||||||
*/
|
*/
|
||||||
exports.applyOptions = function(mode) {
|
exports.applyOptions = function(mode) {
|
||||||
|
@ -8,6 +40,7 @@ exports.applyOptions = function(mode) {
|
||||||
Bangle.setOptions(get("options", {}));
|
Bangle.setOptions(get("options", {}));
|
||||||
Bangle.setLCDBrightness(get("brightness", 1));
|
Bangle.setLCDBrightness(get("brightness", 1));
|
||||||
Bangle.setLCDTimeout(get("timeout", 10));
|
Bangle.setLCDTimeout(get("timeout", 10));
|
||||||
|
if ((require("Storage").readJSON("qmsched.json", 1) || {}).switchTheme) switchTheme(mode);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Set new Quiet Mode and apply Bangle options
|
* Set new Quiet Mode and apply Bangle options
|
||||||
|
@ -20,4 +53,5 @@ exports.setMode = function(mode) {
|
||||||
));
|
));
|
||||||
exports.applyOptions(mode);
|
exports.applyOptions(mode);
|
||||||
if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
|
if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw();
|
||||||
|
if (global.__FILE__ === "qmsched.app.js") setAppMode(mode);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
return; // drawWidgets will call draw again
|
return; // drawWidgets will call draw again
|
||||||
}
|
}
|
||||||
let x = this.x, y = this.y;
|
let x = this.x, y = this.y;
|
||||||
g.clearRect(x, y, x+23, y+23);
|
g.reset().clearRect(x, y, x+23, y+23);
|
||||||
// quiet mode: draw red one-way-street sign (dim red on Bangle.js 1)
|
// quiet mode: draw red one-way-street sign (dim red on Bangle.js 1)
|
||||||
x = this.x+11;y = this.y+11; // center of widget
|
x = this.x+11;y = this.y+11; // center of widget
|
||||||
g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8);
|
g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Run App
|
# Run App
|
||||||
|
|
||||||
This app allows you to display the status of your run.
|
This app allows you to display the status of your run, it
|
||||||
|
shows distance, time, steps, cadence, pace and more.
|
||||||
|
|
||||||
To use it, start the app and press the middle button so that
|
To use it, start the app and press the middle button so that
|
||||||
the red `STOP` in the bottom right turns to a green `RUN`.
|
the red `STOP` in the bottom right turns to a green `RUN`.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: First release
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Simple Pedometer Widget
|
||||||
|
|
||||||
|
*Displays the current step count from `Bangle.getHealthStatus("day").steps` in (6x8,2) font, Requires firmware v2.11.21 or later*
|
||||||
|
|
||||||
|
* Designed to be small, minimal, does one thing well, no settings
|
||||||
|
* Supports Bangle 1 and Bangle 2
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* Requires firmware v2.11.21 or later
|
||||||
|
* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press
|
||||||
|
* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)
|
Binary file not shown.
After Width: | Height: | Size: 246 B |
|
@ -0,0 +1,17 @@
|
||||||
|
Bangle.on('step', function(s) { WIDGETS["widpa"].draw(); });
|
||||||
|
Bangle.on('lcdPower', function(on) {
|
||||||
|
if (on) WIDGETS["widpa"].draw();
|
||||||
|
});
|
||||||
|
WIDGETS["widpa"]={area:"tl",width:13,draw:function() {
|
||||||
|
if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off
|
||||||
|
var steps = Bangle.getHealthStatus("day").steps;
|
||||||
|
var w = 1 + (steps.toString().length)*12;
|
||||||
|
if (w > this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;}
|
||||||
|
g.reset();
|
||||||
|
g.setColor(g.theme.bg);
|
||||||
|
g.fillRect(this.x, this.y, this.x + this.width, this.y + 23);
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.setFont('6x8',2);
|
||||||
|
g.setFontAlign(-1, 0);
|
||||||
|
g.drawString(steps, this.x, this.y + 12);
|
||||||
|
}};
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: First release
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Lato Pedometer Widget
|
||||||
|
|
||||||
|
*Displays the current step count from `Bangle.getHealthStatus("day").steps` in the Lato font, Requires firmware v2.11.21 or later*
|
||||||
|
|
||||||
|
* Designed to be minimal, does one thing well, no settings
|
||||||
|
* Supports Bangle 1 and Bangle 2
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* Requires firmware v2.11.21 or later
|
||||||
|
* Uses the Lato custom font, so memory footprint is 500 bytes larger than 'Simple Pedometer Widget'
|
||||||
|
* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press
|
||||||
|
* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)
|
Binary file not shown.
After Width: | Height: | Size: 338 B |
|
@ -0,0 +1,20 @@
|
||||||
|
// on.step version
|
||||||
|
Bangle.on('step', function(s) { WIDGETS["bata"].draw(); });
|
||||||
|
Bangle.on('lcdPower', function(on) {
|
||||||
|
if (on) WIDGETS["bata"].draw();
|
||||||
|
});
|
||||||
|
WIDGETS["bata"]={area:"tl",width:13,draw:function() {
|
||||||
|
if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off
|
||||||
|
var steps = Bangle.getHealthStatus("day").steps;
|
||||||
|
var w = 1 + (steps.toString().length)*12;
|
||||||
|
if (w > this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;}
|
||||||
|
g.reset();
|
||||||
|
g.setColor(g.theme.bg);
|
||||||
|
g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
// Lato from fonts.google.com, Actual height 17 (17 - 1), Numeric only
|
||||||
|
const scale = 1;
|
||||||
|
g.setFontCustom(atob("AAAAABwAAOAAAgAAHAADwAD4AB8AB8AA+AAeAADAAAAOAAP+AH/8B4DwMAGBgAwMAGBgAwOAOA//gD/4AD4AAAAAAAABgAAcAwDAGAwAwP/+B//wAAGAAAwAAGAAAAAAAAIAwHgOA4DwMA+BgOwMDmBg4wOeGA/gwDwGAAAAAAAAAGAHA8A4DwMAGBhAwMMGBjgwOcOA+/gDj4AAAAABgAAcAAHgADsAA5gAOMAHBgBwMAP/+B//wABgAAMAAAAAAAgD4OB/AwOYGBjAwMYGBjBwMe8Bh/AIHwAAAAAAAAAfAAP8AHxwB8GAdgwPMGBxgwMOOAB/gAH4AAAAAAABgAAMAABgAwMAeBgPgMHwBj4AN8AB+AAPAABAAAAAAAMfAH38B/xwMcGBhgwMMGBjgwP+OA+/gDj4AAAAAAAAOAAH4AA/gQMMGBgzwME8BhvAOPgA/4AD8AAEAAAAAAGAwA4OAHBwAAA="), 46, atob("BAgMDAwMDAwMDAwMBQ=="), 21+(scale<<8)+(1<<16));
|
||||||
|
g.setFontAlign(-1, 0);
|
||||||
|
g.drawString(steps, this.x, this.y + 12);
|
||||||
|
}};
|
Loading…
Reference in New Issue