mirror of https://github.com/espruino/BangleApps
Merge remote-tracking branch 'upstream/master'
commit
d260e7c507
43
apps.json
43
apps.json
|
@ -1351,6 +1351,22 @@
|
||||||
{"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true}
|
{"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "hralarm",
|
||||||
|
"name": "Heart rate alarm",
|
||||||
|
"shortName":"HR Alarm",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits",
|
||||||
|
"icon": "widget.png",
|
||||||
|
"type": "widget",
|
||||||
|
"tags": "widget",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"hralarm.wid.js","url":"widget.js"},
|
||||||
|
{"name":"hralarm.settings.js","url":"settings.js"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "hrings",
|
"id": "hrings",
|
||||||
"name": "Hypno Rings",
|
"name": "Hypno Rings",
|
||||||
|
@ -1504,7 +1520,7 @@
|
||||||
{
|
{
|
||||||
"id": "gpsinfo",
|
"id": "gpsinfo",
|
||||||
"name": "GPS Info",
|
"name": "GPS Info",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "An application that displays information about altitude, lat/lon, satellites and time",
|
"description": "An application that displays information about altitude, lat/lon, satellites and time",
|
||||||
"icon": "gps-info.png",
|
"icon": "gps-info.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
@ -4498,7 +4514,7 @@
|
||||||
"name": "LCARS Clock",
|
"name": "LCARS Clock",
|
||||||
"shortName":"LCARS",
|
"shortName":"LCARS",
|
||||||
"icon": "lcars.png",
|
"icon": "lcars.png",
|
||||||
"version":"0.10",
|
"version":"0.11",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
||||||
|
@ -5046,7 +5062,7 @@
|
||||||
{
|
{
|
||||||
"id": "lapcounter",
|
"id": "lapcounter",
|
||||||
"name": "Lap Counter",
|
"name": "Lap Counter",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).",
|
"description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot.png"}],
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
|
@ -5081,7 +5097,7 @@
|
||||||
{ "id": "circlesclock",
|
{ "id": "circlesclock",
|
||||||
"name": "Circles clock",
|
"name": "Circles clock",
|
||||||
"shortName":"Circles clock",
|
"shortName":"Circles clock",
|
||||||
"version":"0.04",
|
"version":"0.05",
|
||||||
"description": "A clock with circles for different data at the bottom in a probably familiar style",
|
"description": "A clock with circles for different data at the bottom in a probably familiar style",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}],
|
"screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}],
|
||||||
|
@ -5132,6 +5148,25 @@
|
||||||
{"name":"ltherm.img","url":"icon.js","evaluate":true}
|
{"name":"ltherm.img","url":"icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "ftclock",
|
||||||
|
"name": "Four Twenty Clock",
|
||||||
|
"version": "0.01",
|
||||||
|
"description": "A clock that tells when and where it's going to be 4:20 next",
|
||||||
|
"icon": "app.png",
|
||||||
|
"screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}],
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
|
"allow_emulator": true,
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"ftclock.app.js","url":"app.js"},
|
||||||
|
{"name":"fourTwenty","url":"fourTwenty.js"},
|
||||||
|
{"name":"fourTwentyTz","url":"fourTwentyTz.js"},
|
||||||
|
{"name":"ftclock.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "mmind",
|
"id": "mmind",
|
||||||
"name": "Classic Mind Game",
|
"name": "Classic Mind Game",
|
||||||
|
|
|
@ -40,7 +40,10 @@ 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** - Weeknumber (ISO-8601) is shown.
|
* **Show Weeknumber** - 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 "On" the weekday name is cut at 6th position and suffixed with ".#<week num>".
|
||||||
|
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.
|
||||||
Otherwise, a scaled version of the built-in 6x8 pixels font is used.
|
Otherwise, a scaled version of the built-in 6x8 pixels font is used.
|
||||||
|
|
|
@ -188,9 +188,8 @@ function draw() {
|
||||||
g.drawString(dateStr, x, y);
|
g.drawString(dateStr, x, y);
|
||||||
if (weekDay || calWeek) {
|
if (weekDay || calWeek) {
|
||||||
var dowwumStr = require("locale").dow(date);
|
var dowwumStr = require("locale").dow(date);
|
||||||
dowwumStr = "thursday";
|
|
||||||
if (calWeek)
|
if (calWeek)
|
||||||
dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date);
|
dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week"
|
||||||
if (upperCase)
|
if (upperCase)
|
||||||
dowwumStr = dowwumStr.toUpperCase();
|
dowwumStr = dowwumStr.toUpperCase();
|
||||||
g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16));
|
g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16));
|
||||||
|
|
|
@ -5,3 +5,5 @@
|
||||||
Add step distance and weather
|
Add step distance and weather
|
||||||
Allow switching visibility of widgets
|
Allow switching visibility of widgets
|
||||||
Make circles and text slightly bigger
|
Make circles and text slightly bigger
|
||||||
|
0.05: Show correct percentage values in circles
|
||||||
|
Show humidity as weather circle data
|
||||||
|
|
|
@ -10,6 +10,9 @@ It can show the following information (this can be configured):
|
||||||
* Heart rate (automatically updates when screen is on and unlocked)
|
* Heart rate (automatically updates when screen is on and unlocked)
|
||||||
* Battery (including charging status and battery low warning)
|
* Battery (including charging status and battery low warning)
|
||||||
* Weather (requires [weather app](https://banglejs.com/apps/#weather))
|
* Weather (requires [weather app](https://banglejs.com/apps/#weather))
|
||||||
|
* Humidity as circle progress
|
||||||
|
* Temperature inside circle
|
||||||
|
* Condition as icon below circle
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||

|

|
||||||
|
|
|
@ -283,6 +283,7 @@ function drawWeather(w) {
|
||||||
if (!w) w = getCirclePosition("weather");
|
if (!w) w = getCirclePosition("weather");
|
||||||
const weather = getWeather();
|
const weather = getWeather();
|
||||||
const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined;
|
const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined;
|
||||||
|
const humidity = weather ? weather.hum : undefined;
|
||||||
const code = weather ? weather.code : -1;
|
const code = weather ? weather.code : -1;
|
||||||
|
|
||||||
// Draw rectangle background:
|
// Draw rectangle background:
|
||||||
|
@ -292,6 +293,10 @@ function drawWeather(w) {
|
||||||
g.setColor(colorGrey);
|
g.setColor(colorGrey);
|
||||||
g.fillCircle(w, h3, radiusOuter);
|
g.fillCircle(w, h3, radiusOuter);
|
||||||
|
|
||||||
|
if (humidity >= 0) {
|
||||||
|
drawGauge(w, h3, humidity / 100, colorYellow);
|
||||||
|
}
|
||||||
|
|
||||||
g.setColor(colorBg);
|
g.setColor(colorBg);
|
||||||
g.fillCircle(w, h3, radiusInner);
|
g.fillCircle(w, h3, radiusInner);
|
||||||
|
|
||||||
|
@ -363,22 +368,21 @@ function radians(a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawGauge(cx, cy, percent, color) {
|
function drawGauge(cx, cy, percent, color) {
|
||||||
let offset = 30;
|
const offset = 15;
|
||||||
let end = 300;
|
const end = 345;
|
||||||
var i = 0;
|
const r = radiusInner + 3;
|
||||||
var r = radiusInner + 3;
|
|
||||||
|
|
||||||
if (percent <= 0) return;
|
if (percent <= 0) return;
|
||||||
if (percent > 1) percent = 1;
|
if (percent > 1) percent = 1;
|
||||||
|
|
||||||
var startrot = -offset;
|
const startrot = -offset;
|
||||||
var endrot = startrot - ((end - offset) * percent) - 35;
|
const endrot = startrot - ((end - offset) * percent);
|
||||||
|
|
||||||
g.setColor(color);
|
g.setColor(color);
|
||||||
|
|
||||||
const size = radiusOuter - radiusInner - 2;
|
const size = radiusOuter - radiusInner - 2;
|
||||||
// draw gauge
|
// draw gauge
|
||||||
for (i = startrot; i > endrot - size; i -= size) {
|
for (let i = startrot; i > endrot - size; i -= size) {
|
||||||
x = cx + r * Math.sin(radians(i));
|
x = cx + r * Math.sin(radians(i));
|
||||||
y = cy + r * Math.cos(radians(i));
|
y = cy + r * Math.cos(radians(i));
|
||||||
g.fillCircle(x, y, size);
|
g.fillCircle(x, y, size);
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
timezonedb.csv.zip
|
||||||
|
country.csv
|
||||||
|
zone.csv
|
||||||
|
timezone.csv
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: first release
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Four Twenty Clock
|
||||||
|
|
||||||
|
A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_%28cannabis_culture%29) next
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
## Generating `fourTwentyTz.js`
|
||||||
|
|
||||||
|
Once in a while we need to regenerate it for 2 reasons:
|
||||||
|
|
||||||
|
* One or more places got in or out of daylight saving time (DST) mode.
|
||||||
|
* The database saying _when_ places enter/exit DST mode got updated.
|
||||||
|
|
||||||
|
I'll do my best to release a new version every time this happens,
|
||||||
|
but if you ever need to do this yourself, here's how:
|
||||||
|
|
||||||
|
* `cd` to the `ftclock` folder
|
||||||
|
* If you haven't done so yet, run `npm install` there (this would create the `node_modules` folder).
|
||||||
|
* Get and unzip the latest `timezone.csv.zip` from https://timezonedb.com/download
|
||||||
|
* Run `npm run make`
|
||||||
|
|
||||||
|
## Creator
|
||||||
|
|
||||||
|
[Nimrod Kerrett](zzzen.com)
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwghC/AH4A/AH4A/AAMHu4ACuwHBs4HDsEGBIQLCsADBgwPDCAQGEuwXFBwI0GEAMHuAGCCoMHC4pMHEAIXEAgIGEBwI9BC4wSCC8IVCMAwIBs4XKUQJfITQgXCDwp8EHAqaECoLFEu4cDBIggBs6uFZozuGBAVmC4g+FMgZQEZQ5vGC4iRIC5IrDN4h5EC5J3BCoIKGgyaEC44VBC46yEDgoeDgxqLC5SCMAgoTFY47GFC4xFBdwwPBD4oWFAH4A/AH4A/AH4AjA=="))
|
|
@ -0,0 +1,52 @@
|
||||||
|
let getNextFourTwenty = require("fourTwenty").getNextFourTwenty;
|
||||||
|
require("FontTeletext10x18Ascii").add(Graphics);
|
||||||
|
let leaf_img = "\x17\x18\x81\x00\x00\x10\x00\x00 \x00\x00@\x00\x01\xc0\x00\x03\x80\x00\x0f\x80\x00\x1f\x00\x00>\x00\x00|\x00\xc0\xf8\x19\xe1\xf0\xf1\xe3\xe3\xc3\xf7\xdf\x83\xff\xfe\x03\xff\xf8\x03\xff\xe0\x03\xff\x80\x03\xfe\x00\x7f\xff\xc0\xff\xff\xc0\x06\xe0\x00\x18\xc0\x00 \x80\x00\x00\x00";
|
||||||
|
|
||||||
|
// timeout used to update every minute
|
||||||
|
let drawTimeout;
|
||||||
|
|
||||||
|
// schedule a draw for the next minute
|
||||||
|
function queueDraw() {
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = setTimeout(function() {
|
||||||
|
drawTimeout = undefined;
|
||||||
|
draw();
|
||||||
|
}, 60000 - (Date.now() % 60000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
g.reset();
|
||||||
|
g.setBgColor("#ffffff");
|
||||||
|
let date = new Date();
|
||||||
|
let timeStr = require("locale").time(date,1);
|
||||||
|
let next420 = getNextFourTwenty();
|
||||||
|
g.clearRect(0,26,g.getWidth(),g.getHeight());
|
||||||
|
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.setColor("#000000");
|
||||||
|
g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii");
|
||||||
|
g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60);
|
||||||
|
|
||||||
|
// queue draw in one minute
|
||||||
|
queueDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the screen once, at startup
|
||||||
|
g.clear();
|
||||||
|
// Load widgets
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
// draw immediately at first, queue update
|
||||||
|
draw();
|
||||||
|
// Stop updates when LCD is off, restart when on
|
||||||
|
Bangle.on('lcdPower',on=>{
|
||||||
|
if (on) {
|
||||||
|
draw(); // draw immediately, queue redraw
|
||||||
|
} else { // stop draw timer
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Show launcher when middle button pressed
|
||||||
|
Bangle.setUI("clock");
|
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
|
@ -0,0 +1,45 @@
|
||||||
|
let timezones = require("fourTwentyTz").timezones;
|
||||||
|
|
||||||
|
function get420offset() {
|
||||||
|
let current_time = Math.floor((Date.now()%(24*3600*1000))/60000);
|
||||||
|
let current_min = current_time%60;
|
||||||
|
if (current_min>20 && current_min<25) {
|
||||||
|
current_time -= current_min-20; // 5 minutes grace period
|
||||||
|
}
|
||||||
|
let offset = 16*60+20-current_time;
|
||||||
|
if (offset<0) {
|
||||||
|
offset += 24*60;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeFourTwentyText(minutes, places) {
|
||||||
|
//let plural = minutes==1? "": "s";
|
||||||
|
//let msgprefix = minutes? `${minutes} minute${plural} to`: "It is now";
|
||||||
|
let msgprefix = minutes? `${minutes}m to`: "It is now";
|
||||||
|
let msgsuffix = places.length>1? ", and other fine places": "";
|
||||||
|
let msgplace = places[Math.floor(Math.random()*places.length)];
|
||||||
|
return `${msgprefix} 4:20 at ${msgplace}${msgsuffix}.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNextFourTwenty() {
|
||||||
|
let offs = get420offset();
|
||||||
|
for (let i=0; i<timezones.length; i++) {
|
||||||
|
if (timezones[i][0]<=offs) {
|
||||||
|
let minutes = offs-timezones[i][0];
|
||||||
|
let places = timezones[i][1];
|
||||||
|
return {
|
||||||
|
minutes: minutes,
|
||||||
|
places: places,
|
||||||
|
text: makeFourTwentyText(minutes, places)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
minutes: 666,
|
||||||
|
places: ["Snafu (Yes. It's a bug)"],
|
||||||
|
text: "Snafu (Yes. It's a bug)"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getNextFourTwenty = getNextFourTwenty;
|
|
@ -0,0 +1,463 @@
|
||||||
|
// Generated by mkFourTwentyTz.js
|
||||||
|
// Data source: https://timezonedb.com/files/timezonedb.csv.zip
|
||||||
|
// Sun Jan 09 2022 13:21:47 GMT+0200 (Israel Standard Time)
|
||||||
|
exports.timezones = {
|
||||||
|
"0": [
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
let fs = require('fs');
|
||||||
|
let csv = require('csv');
|
||||||
|
|
||||||
|
let countries = {},
|
||||||
|
zones = {},
|
||||||
|
offsdict = {},
|
||||||
|
now = Date.now(); // we need this to find zone's current DST state
|
||||||
|
|
||||||
|
function handleWrite(err,bytes) {
|
||||||
|
if (err) {
|
||||||
|
console.log(`Error writing to file ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Generating fourTwentyTz.js...");
|
||||||
|
fs.createReadStream(__dirname+'/country.csv')
|
||||||
|
.pipe(csv.parse())
|
||||||
|
.on('data', (r) => {
|
||||||
|
countries[r[0]] = r[1];
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
fs.createReadStream(__dirname+'/zone.csv')
|
||||||
|
.pipe(csv.parse())
|
||||||
|
.on('data', (r) => {
|
||||||
|
let parts = r[2].replace('_',' ').split('/');
|
||||||
|
let city = parts[parts.length-1];
|
||||||
|
let country ='';
|
||||||
|
if (parts.length>2) { // e.g. America/North_Dakota/New_Salem
|
||||||
|
country = parts[1]; // e.g. North Dakota
|
||||||
|
} else {
|
||||||
|
country = countries[r[1]]; // e.g. United States
|
||||||
|
}
|
||||||
|
zones[parseInt(r[0])] = {"name": `${city}, ${country}`};
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
fs.createReadStream(__dirname+'/timezone.csv')
|
||||||
|
.pipe(csv.parse())
|
||||||
|
.on('data', (r) => {
|
||||||
|
code = parseInt(r[0]);
|
||||||
|
if (!(code in zones)) return;
|
||||||
|
starttime = parseInt(r[2] || "0"); // Bugger. They're feeding us blanks for UTC now
|
||||||
|
offs = parseInt(r[3]);
|
||||||
|
if (offs<0) {
|
||||||
|
offs += 60*60*24;
|
||||||
|
}
|
||||||
|
zone = zones[code];
|
||||||
|
if (starttime<now && (!("starttime" in zone) || zone.starttime<starttime)) {
|
||||||
|
zone.starttime = starttime;
|
||||||
|
zone.offs = Math.floor(offs/60);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
for (z in zones) {
|
||||||
|
zone = zones[z];
|
||||||
|
if (zone.offs%60) continue; // One a dem funky timezones. Ignore.
|
||||||
|
zonelist = offsdict[zone.offs] || [];
|
||||||
|
zonelist.push(zone.name);
|
||||||
|
offsdict[zone.offs] = zonelist;
|
||||||
|
}
|
||||||
|
fs.open("fourTwentyTz.js","w", (err, fd) => {
|
||||||
|
if (err) {
|
||||||
|
console.log("Can't open output file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs.write(fd, "// Generated by mkFourTwentyTz.js\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, "exports.timezones = ", handleWrite);
|
||||||
|
fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite);
|
||||||
|
console.log('Done.');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "mkfourtwentytz",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Convert timezonedb.com CSV to fourTwentyTz.js for BangleJS ftclock app",
|
||||||
|
"main": "mkFourTwentyTz.js",
|
||||||
|
"scripts": {
|
||||||
|
"make": "node mkFourTwentyTz.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"dependencies": {
|
||||||
|
"csv": "^6.0.5"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -5,3 +5,4 @@
|
||||||
0.06: Add number of satellites in view and fix crash with GPS time
|
0.06: Add number of satellites in view and fix crash with GPS time
|
||||||
0.07: Resolve one FIFO_FULL case and exit App with button press
|
0.07: Resolve one FIFO_FULL case and exit App with button press
|
||||||
0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway)
|
0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway)
|
||||||
|
0.09: Fix FIFO_FULL error
|
||||||
|
|
|
@ -4,7 +4,7 @@ function satelliteImage() {
|
||||||
|
|
||||||
var Layout = require("Layout");
|
var Layout = require("Layout");
|
||||||
var layout;
|
var layout;
|
||||||
Bangle.setGPSPower(1, "app");
|
//Bangle.setGPSPower(1, "app");
|
||||||
E.showMessage("Loading..."); // avoid showing rubbish on screen
|
E.showMessage("Loading..."); // avoid showing rubbish on screen
|
||||||
|
|
||||||
var lastFix = {
|
var lastFix = {
|
||||||
|
@ -19,7 +19,7 @@ var lastFix = {
|
||||||
var SATinView = 0;
|
var SATinView = 0;
|
||||||
var nofBD = 0;
|
var nofBD = 0;
|
||||||
var nofGP = 0;
|
var nofGP = 0;
|
||||||
var listenerGPSraw = 1;
|
var listenerGPSraw = 0;
|
||||||
|
|
||||||
function formatTime(now) {
|
function formatTime(now) {
|
||||||
if (now == undefined) {
|
if (now == undefined) {
|
||||||
|
@ -87,12 +87,12 @@ function onGPS(fix) {
|
||||||
{type:"txt", font:"6x8", pad:3, label:"Satellites used" }
|
{type:"txt", font:"6x8", pad:3, label:"Satellites used" }
|
||||||
]},
|
]},
|
||||||
{type:"txt", font:"6x8", label:"", fillx:true, id:"progress" }
|
{type:"txt", font:"6x8", label:"", fillx:true, id:"progress" }
|
||||||
]},{lazy:true});
|
]},{lazy:false});
|
||||||
}
|
}
|
||||||
g.clearRect(0,24,g.getWidth(),g.getHeight());
|
g.clearRect(0,24,g.getWidth(),g.getHeight());
|
||||||
layout.render();
|
layout.render();
|
||||||
}
|
}
|
||||||
lastFix = fix;
|
//lastFix = fix;
|
||||||
if (fix.fix) {
|
if (fix.fix) {
|
||||||
if (listenerGPSraw == 1) {
|
if (listenerGPSraw == 1) {
|
||||||
Bangle.removeListener('GPS-raw', onGPSraw);
|
Bangle.removeListener('GPS-raw', onGPSraw);
|
||||||
|
@ -108,15 +108,28 @@ function onGPS(fix) {
|
||||||
layout.time.label = "Time: "+formatTime(fix.time);
|
layout.time.label = "Time: "+formatTime(fix.time);
|
||||||
layout.sat.label = "Satellites: "+satellites;
|
layout.sat.label = "Satellites: "+satellites;
|
||||||
layout.maidenhead.label = "Maidenhead: "+maidenhead;
|
layout.maidenhead.label = "Maidenhead: "+maidenhead;
|
||||||
|
layout.render();
|
||||||
} else {
|
} else {
|
||||||
if (listenerGPSraw == 0) {
|
if (fix.satelites != lastFix.satelites) {
|
||||||
Bangle.on('GPS-raw', onGPSraw);
|
layout.clear(layout.sat);
|
||||||
listenerGPSraw = 1;
|
layout.sat.label = fix.satellites;
|
||||||
|
layout.render(layout.sat);
|
||||||
|
}
|
||||||
|
if (SATinView != lastFix.SATinView) {
|
||||||
|
layout.clear(layout.progress);
|
||||||
|
layout.progress.label = "in view: " + SATinView;
|
||||||
|
layout.render(layout.progress);
|
||||||
}
|
}
|
||||||
layout.sat.label = fix.satellites;
|
|
||||||
layout.progress.label = "in view: " + SATinView;
|
|
||||||
}
|
}
|
||||||
layout.render();
|
//layout.render();
|
||||||
|
|
||||||
|
if (listenerGPSraw == 0 && !fix.fix) {
|
||||||
|
setTimeout(() => Bangle.on('GPS-raw', onGPSraw), 10);
|
||||||
|
listenerGPSraw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFix = fix;
|
||||||
|
lastFix.SATinView = SATinView;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGPSraw(nmea) {
|
function onGPSraw(nmea) {
|
||||||
|
@ -129,7 +142,8 @@ function onGPSraw(nmea) {
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
Bangle.on('GPS', onGPS);
|
Bangle.on('GPS', onGPS);
|
||||||
Bangle.on('GPS-raw', onGPSraw);
|
//Bangle.on('GPS-raw', onGPSraw);
|
||||||
|
Bangle.setGPSPower(1, "app");
|
||||||
|
|
||||||
function exitApp() {
|
function exitApp() {
|
||||||
load();
|
load();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New Widget!
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Heart rate alarm
|
||||||
|
|
||||||
|
This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Configure the heart rate limits in the apps settings. This widget uses both 'HRM' and 'BTHRM' events.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Long vibration every 10 seconds on reaching upper limit, short vibrations between upper limit and warning threshold and an single vibration when reaching the lower limit again.
|
||||||
|
|
||||||
|
## Requests/Creator
|
||||||
|
|
||||||
|
https://github.com/halemmerich
|
|
@ -0,0 +1,57 @@
|
||||||
|
(function(back) {
|
||||||
|
var FILE = "hralarm.json";
|
||||||
|
|
||||||
|
var settings = Object.assign({
|
||||||
|
enabled: false,
|
||||||
|
upper: 180,
|
||||||
|
warning: 170,
|
||||||
|
lower: 150,
|
||||||
|
}, require('Storage').readJSON(FILE, true) || {});
|
||||||
|
|
||||||
|
function writeSettings() {
|
||||||
|
require('Storage').writeJSON(FILE, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
E.showMenu({
|
||||||
|
'': { 'title': 'HR Alarm' },
|
||||||
|
'< Back': back,
|
||||||
|
'Enabled': {
|
||||||
|
value: !!settings.enabled,
|
||||||
|
format: v => settings.enabled ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
settings.enabled = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Upper limit': {
|
||||||
|
value: settings.upper,
|
||||||
|
min: 0,
|
||||||
|
step:5,
|
||||||
|
max: 300,
|
||||||
|
onchange: v => {
|
||||||
|
settings.upper = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Lower limit': {
|
||||||
|
value: settings.lower,
|
||||||
|
min: 0,
|
||||||
|
step:5,
|
||||||
|
max: 300,
|
||||||
|
onchange: v => {
|
||||||
|
settings.lower = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Warning at': {
|
||||||
|
value: settings.warning,
|
||||||
|
min: 0,
|
||||||
|
step:5,
|
||||||
|
max: 300,
|
||||||
|
onchange: v => {
|
||||||
|
settings.warning = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
|
@ -0,0 +1,27 @@
|
||||||
|
(() => {
|
||||||
|
var settings = require('Storage').readJSON("hralarm.json", true) || {};
|
||||||
|
if (!settings.enabled){ Bangle.setHRMPower(0, 'hralarm'); return; }
|
||||||
|
Bangle.setHRMPower(1, 'hralarm');
|
||||||
|
var hitLimit = 0;
|
||||||
|
var checkHr = function(hr){
|
||||||
|
if (hr.bpm > settings.warning && hr.bpm <= settings.upper){
|
||||||
|
Bangle.buzz(100, 1);
|
||||||
|
}
|
||||||
|
if (hitLimit < getTime() && hr.bpm > settings.upper){
|
||||||
|
hitLimit = getTime() + 10;
|
||||||
|
Bangle.buzz(2000, 1);
|
||||||
|
}
|
||||||
|
if (hitLimit > 0 && hr.bpm < settings.lower){
|
||||||
|
hitLimit = 0;
|
||||||
|
Bangle.buzz(500, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Bangle.on("HRM", checkHr);
|
||||||
|
Bangle.on("BTHRM", checkHr);
|
||||||
|
|
||||||
|
WIDGETS["hralarm"]={
|
||||||
|
area:"tl",
|
||||||
|
width: 0,
|
||||||
|
draw: function(){}
|
||||||
|
};
|
||||||
|
})()
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
|
@ -1 +1,2 @@
|
||||||
0.01: first release
|
0.01: first release
|
||||||
|
0.02: Themeable app icon
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap"))
|
require("heatshrink").decompress(atob("mEwwI0xg+evPsAon+ApX8Aon4AonwAod78AFDv4FWvoFE/IFDz4FXvIFD3wFE/wFW7wFDh5xBAoUfAok/Aol/BZUXAogA6A="))
|
||||||
|
|
|
@ -7,4 +7,5 @@
|
||||||
0.07: Added settings to adjust data that is shown for each row.
|
0.07: Added settings to adjust data that is shown for each row.
|
||||||
0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode.
|
0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode.
|
||||||
0.09: Tab anywhere to open the launcher.
|
0.09: Tab anywhere to open the launcher.
|
||||||
0.10: Fix - Clock is unresponsive, if gadgetbridge connects.
|
0.10: Fix - Clock is unresponsive, if gadgetbridge connects.
|
||||||
|
0.11: Added getting the gadgetbridge weather
|
|
@ -1,5 +1,6 @@
|
||||||
const SETTINGS_FILE = "lcars.setting.json";
|
const SETTINGS_FILE = "lcars.setting.json";
|
||||||
const Storage = require("Storage");
|
const Storage = require("Storage");
|
||||||
|
const weather = require('weather');
|
||||||
|
|
||||||
|
|
||||||
// ...and overwrite them with any saved values
|
// ...and overwrite them with any saved values
|
||||||
|
@ -145,6 +146,14 @@ function printData(key, y, c){
|
||||||
text = "VREF";
|
text = "VREF";
|
||||||
value = E.getAnalogVRef().toFixed(2) + "V";
|
value = E.getAnalogVRef().toFixed(2) + "V";
|
||||||
|
|
||||||
|
} else if (key == "Weather"){
|
||||||
|
text = "TEMP";
|
||||||
|
const w = weather.get();
|
||||||
|
if (!w) {
|
||||||
|
value = "ERR";
|
||||||
|
} else {
|
||||||
|
value = require('locale').temp(w.temp-273.15); // applies conversion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g.setColor(c);
|
g.setColor(c);
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
storage.write(SETTINGS_FILE, settings)
|
storage.write(SETTINGS_FILE, settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF"];
|
var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF", "Weather"];
|
||||||
|
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
'': { 'title': 'LCARS Clock' },
|
'': { 'title': 'LCARS Clock' },
|
||||||
'< Back': back,
|
'< Back': back,
|
||||||
'Row 1': {
|
'Row 1': {
|
||||||
value: 0 | data_options.indexOf(settings.dataRow1),
|
value: 0 | data_options.indexOf(settings.dataRow1),
|
||||||
min: 0, max: 4,
|
min: 0, max: 5,
|
||||||
format: v => data_options[v],
|
format: v => data_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.dataRow1 = data_options[v];
|
settings.dataRow1 = data_options[v];
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
},
|
},
|
||||||
'Row 2': {
|
'Row 2': {
|
||||||
value: 0 | data_options.indexOf(settings.dataRow2),
|
value: 0 | data_options.indexOf(settings.dataRow2),
|
||||||
min: 0, max: 4,
|
min: 0, max: 5,
|
||||||
format: v => data_options[v],
|
format: v => data_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.dataRow2 = data_options[v];
|
settings.dataRow2 = data_options[v];
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
},
|
},
|
||||||
'Row 3': {
|
'Row 3': {
|
||||||
value: 0 | data_options.indexOf(settings.dataRow3),
|
value: 0 | data_options.indexOf(settings.dataRow3),
|
||||||
min: 0, max: 4,
|
min: 0, max: 5,
|
||||||
format: v => data_options[v],
|
format: v => data_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.dataRow3 = data_options[v];
|
settings.dataRow3 = data_options[v];
|
||||||
|
|
Loading…
Reference in New Issue