Merge branch 'master' into deprecate-currency

master
Anton 2024-03-20 10:40:44 +01:00 committed by GitHub
commit 5684832970
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 65 additions and 61 deletions

View File

@ -2,4 +2,5 @@
0.02: Remove un-needed fonts to improve memory usage 0.02: Remove un-needed fonts to improve memory usage
0.03: Tell clock widgets to hide. 0.03: Tell clock widgets to hide.
0.04: Swipe down to see widgets, step counter now just uses getHealthStatus 0.04: Swipe down to see widgets, step counter now just uses getHealthStatus
0.05: Report latest HRM rather than HRM 10 minutes ago (fix #2395) 0.05: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
0.06: Use watch temperature

View File

@ -3,8 +3,7 @@
<img src="https://user-images.githubusercontent.com/2981891/175355586-1dfc0d66-6555-4385-b124-1605fdb71a11.jpg" width="250" /> <img src="https://user-images.githubusercontent.com/2981891/175355586-1dfc0d66-6555-4385-b124-1605fdb71a11.jpg" width="250" />
An over-engineered clock inspired by Casio watches.<br/> An over-engineered clock inspired by Casio watches.<br/>
It has a dedicated timer, a scratchpad and can display the weather condition 4 days ahead.<br/> It has a dedicated timer, a scratchpad and displays the current temperature.<br/>
It uses a <a target="_blank" href="https://dotgreg.github.io/advCasioBangleClock/">custom web app</a> to update its content.<br/>
Forked from the awesome Cassio Watch.<br/> Forked from the awesome Cassio Watch.<br/>
## Todo ## Todo
@ -21,7 +20,7 @@ Forked from the awesome Cassio Watch.<br/>
- Footsteps - Footsteps
- Battery - Battery
- Simple Timer embedded - Simple Timer embedded
- Weather forecast (7 days) - Current temperature
- Scratchpad - Scratchpad
## Screenshots ## Screenshots
@ -36,14 +35,6 @@ Web interface to update weather & scratchpad <br/>
<img src="https://user-images.githubusercontent.com/2981891/175519121-851bb209-7192-40db-a014-490c344f7597.jpg" width="250" /> <img src="https://user-images.githubusercontent.com/2981891/175519121-851bb209-7192-40db-a014-490c344f7597.jpg" width="250" />
## Usage ## Usage
### How to update the tasks list / weather
- you will need a <a target="_blank" href="https://openweathermap.org/price#weather">free openweathermap.org api key</a>.
- go to https://dotgreg.github.io/advCasioBangleClock/
- Alternatively you can install it on your own server/heroku/service/github pages, the web-app code is <a target="_blank" href="https://github.com/dotgreg/advCasioBangleClock/tree/master/web-app">here</a>
- fill the location and the api key (it will be saved on your browser, no need to do it each time)
- edit the scratchpad with what you want
- click on sync
- reload your clock!
### How to start/stop the timer ### How to start/stop the timer
- swipe up : add time (+5min) - swipe up : add time (+5min)

View File

@ -88,9 +88,9 @@ function drawRocket() {
function getTemperature(){ function getTemperature(){
try { try {
var weatherJson = storage.readJSON('weather.json'); var temperature = E.getTemperature()
var weather = weatherJson.weather; var formatted = require("locale").temp(temperature).replace(/[^\d-]/g, '');
return Math.round(weather.temp-273.15); return formatted;
} catch(ex) { } catch(ex) {
print(ex) print(ex)

View File

@ -1,8 +1,8 @@
{ "id": "advcasio", { "id": "advcasio",
"name": "Advanced Casio Clock", "name": "Advanced Casio Clock",
"shortName":"advcasio", "shortName":"advcasio",
"version":"0.05", "version":"0.06",
"description": "An over-engineered clock inspired by Casio watches. It has a 4 days weather, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.", "description": "An over-engineered clock inspired by Casio watches. It has current temperature, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.",
"icon": "app.png", "icon": "app.png",
"tags": "clock", "tags": "clock",
"type": "clock", "type": "clock",
@ -18,8 +18,5 @@
"storage": [ "storage": [
{"name":"advcasio.app.js","url":"app.js"}, {"name":"advcasio.app.js","url":"app.js"},
{"name":"advcasio.img","url":"app-icon.js","evaluate":true} {"name":"advcasio.img","url":"app-icon.js","evaluate":true}
],
"data": [
{ "name": "advcasio.data.json", "url": "data.json", "storageFile": true }
] ]
} }

View File

@ -44,6 +44,10 @@ The boot code also provides some useful functions:
* `id` - a custom (string) ID * `id` - a custom (string) ID
* `timeout` - a timeout for the request in milliseconds (default 30000ms) * `timeout` - a timeout for the request in milliseconds (default 30000ms)
* `xpath` an xPath query to run on the request (but right now the URL requested must be XML - HTML is rarely XML compliant) * `xpath` an xPath query to run on the request (but right now the URL requested must be XML - HTML is rarely XML compliant)
* `return` for xpath, if not specified, one result is returned. If `return:"array"` an array of results is returned.
* `method` HTTP method (default is `get`) - `get/post/head/put/patch/delete`
* `body` the body of the HTTP request
* `headers` an object of headers, eg `{HeaderOne : "headercontents"}`
eg: eg:

View File

@ -15,4 +15,5 @@
Allow negative/positive actions to pass through to message GUI Allow negative/positive actions to pass through to message GUI
0.15: Enable calendar and weather updates via custom notifications (via shortcuts app) 0.15: Enable calendar and weather updates via custom notifications (via shortcuts app)
0.16: Always request Current Time service from iOS 0.16: Always request Current Time service from iOS
0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font) 0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font)
0.18: Fix UTF8 conversion (check for `font` library, not `fonts`)

View File

@ -298,7 +298,7 @@ E.emit("ANCS", {
NRF.ctsGetTime().then(ctsUpdate, function(){ /* */ }) NRF.ctsGetTime().then(ctsUpdate, function(){ /* */ })
E.on('CTS',ctsUpdate); E.on('CTS',ctsUpdate);
} }
if (settings.no_utf8 || !require("Storage").read("fonts")) { if (settings.no_utf8 || !require("Storage").read("font")) {
// if UTF8 disabled or there is no fonts lib, convert UTF8 to ISO8859-1 // if UTF8 disabled or there is no fonts lib, convert UTF8 to ISO8859-1
let unicodeRemap = { let unicodeRemap = {
'2019':"'", '2019':"'",

View File

@ -1,7 +1,7 @@
{ {
"id": "ios", "id": "ios",
"name": "iOS Integration", "name": "iOS Integration",
"version": "0.17", "version": "0.18",
"description": "Display notifications/music/etc from iOS devices", "description": "Display notifications/music/etc from iOS devices",
"icon": "app.png", "icon": "app.png",
"tags": "tool,system,ios,apple,messages,notifications", "tags": "tool,system,ios,apple,messages,notifications",

View File

@ -59,13 +59,6 @@ module.exports = {
"no-unused-vars" "no-unused-vars"
] ]
}, },
"sleepphasealarm/app.js": {
"hash": "d234fea5d711ae5a149879e53b28bc9002860c6b6a75285e1fc04093fe400a88",
"rules": [
"no-unused-vars",
"no-undef"
]
},
"sleeplog/settings.js": { "sleeplog/settings.js": {
"hash": "bd5e3e1382321df6682ef1cb718b0e15ab355422bef77278eb086f213f643021", "hash": "bd5e3e1382321df6682ef1cb718b0e15ab355422bef77278eb086f213f643021",
"rules": [ "rules": [
@ -582,12 +575,6 @@ module.exports = {
"no-undef" "no-undef"
] ]
}, },
"locale/locales.js": {
"hash": "bf2fd659e673b34a1ffa98c7ae7ca89de86a4ff9f823244d028e85bc465ed3c7",
"rules": [
"no-unused-vars"
]
},
"sleeplog/lib.js": { "sleeplog/lib.js": {
"hash": "755e0d4c02b92181281fd6990df39c9446c73ff896b50b64d7e14cb1c0188556", "hash": "755e0d4c02b92181281fd6990df39c9446c73ff896b50b64d7e14cb1c0188556",
"rules": [ "rules": [

View File

@ -19,4 +19,5 @@
0.16: Remove global variables that used RAM 0.16: Remove global variables that used RAM
Add second 'dp' argument for decimal places in distance/speed/temp (fix #1523) Add second 'dp' argument for decimal places in distance/speed/temp (fix #1523)
0.17: Fix regression where long month names were 'undefined' (fix #1641) 0.17: Fix regression where long month names were 'undefined' (fix #1641)
0.18: Fix lint warnings, change anv->janv for fr_BE and fr_CH
: Deprecate currency information : Deprecate currency information

View File

@ -1,4 +1,8 @@
/* jshint esversion: 6 */ /* jshint esversion: 6 */
/* exported distanceUnits */
/* exported speedUnits */
/* exported codePages */
/* exported locales */
const distanceUnits = { // how many meters per X? const distanceUnits = { // how many meters per X?
"m": 1, "m": 1,
"ft": 0.3048, "ft": 0.3048,
@ -59,6 +63,14 @@ timePattern / datePattern:
%S second (00..60) %S second (00..60)
%p locale's equivalent of either AM or PM; blank if not known %p locale's equivalent of either AM or PM; blank if not known
%P like %p, but lower case %P like %p, but lower case
in locales:
abmonth: short months (must be <5 chars, ideally 3)
month: normal month names
abday: short days (must be <5 chars, ideally 3)
day: normal day names
*/ */
var locales = { var locales = {
@ -413,7 +425,7 @@ var locales = {
ampm: { 0: "", 1: "" }, ampm: { 0: "", 1: "" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
abday: "dim,lun,mar,mer,jeu,ven,sam", abday: "dim,lun,mar,mer,jeu,ven,sam",
day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi",
@ -461,7 +473,7 @@ var locales = {
ampm: { 0: "AM", 1: "PM" }, ampm: { 0: "AM", 1: "PM" },
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
abday: "dim,lun,mar,mer,jeu,ven,sam", abday: "dim,lun,mar,mer,jeu,ven,sam",
day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi",
@ -719,7 +731,7 @@ var locales = {
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" }, datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" },
abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.", abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.",
month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octobre,novembre,desembre", month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octubre,novembre,desembre",
abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.", abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.",
day: "diumenge,dilluns,dimarts,dimecres,dijous,divendres,dissabte", day: "diumenge,dilluns,dimarts,dimecres,dijous,divendres,dissabte",
trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "d'acord", on: "on", off: "off", trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "d'acord", on: "on", off: "off",

View File

@ -1,7 +1,7 @@
{ {
"id": "locale", "id": "locale",
"name": "Languages", "name": "Languages",
"version": "0.17", "version": "0.18",
"description": "Translations for different countries", "description": "Translations for different countries",
"icon": "locale.png", "icon": "locale.png",
"type": "locale", "type": "locale",

View File

@ -196,7 +196,7 @@ const layout = new L({
] ]
} }
] ]
}, {lazy: true}); } as const, {lazy: true});
class State { class State {
paused: boolean = true; paused: boolean = true;
@ -248,7 +248,7 @@ class State {
} }
} }
const repToLabel = (i: number, id: string) => { const repToLabel = (i: number, id: "cur" | "next") => {
const rep = reps[i]; const rep = reps[i];
if(rep) if(rep)
layout[`${id}_name`]!.label = `${rep.label} / ${msToMinSec(rep.dur)}`; layout[`${id}_name`]!.label = `${rep.label} / ${msToMinSec(rep.dur)}`;
@ -256,7 +256,7 @@ const repToLabel = (i: number, id: string) => {
emptyLabel(id); emptyLabel(id);
}; };
const emptyLabel = (id: string) => { const emptyLabel = (id: "cur" | "next") => {
layout[`${id}_name`]!.label = "<none> / 0m"; layout[`${id}_name`]!.label = "<none> / 0m";
}; };

View File

@ -19,3 +19,5 @@
Add plot logged data to settings Add plot logged data to settings
0.15: Convert Yes/No On/Off in settings to checkboxes 0.15: Convert Yes/No On/Off in settings to checkboxes
0.16: Fix Keep alarm enabled inverted settings 0.16: Fix Keep alarm enabled inverted settings
0.17: Fix handle dates saved as object with milliseconds
0.18: Fix lint warnings

View File

@ -105,8 +105,8 @@ function drawApp() {
} }
const period = drawSeconds ? 1000 : 60000; const period = drawSeconds ? 1000 : 60000;
if (this.drawTimeTimeout !== undefined) { if (drawTimeTimeout !== undefined) {
clearTimeout(this.drawTimeTimeout); clearTimeout(drawTimeTimeout);
} }
drawTimeTimeout = setTimeout(()=>{ drawTimeTimeout = setTimeout(()=>{
drawTimeTimeout = undefined; drawTimeTimeout = undefined;
@ -136,7 +136,7 @@ function buzz() {
} }
function addLog(time, type) { function addLog(time, type) {
logs.push({time: time, type: type}); logs.push({time: time.toISOString(), type: type});
if (logs.length > 1) { // Do not write if there is only one state if (logs.length > 1) { // Do not write if there is only one state
require("Storage").writeJSON(CONFIGFILE, config); require("Storage").writeJSON(CONFIGFILE, config);
} }
@ -156,7 +156,7 @@ if (nextAlarmDate !== undefined) {
// minimum alert 30 minutes early // minimum alert 30 minutes early
minAlarm.setTime(nextAlarmDate.getTime() - (30*60*1000)); minAlarm.setTime(nextAlarmDate.getTime() - (30*60*1000));
run = () => { let run = () => {
layout.state.label = /*LANG*/"Start"; layout.state.label = /*LANG*/"Start";
layout.render(); layout.render();
Bangle.setOptions({powerSave: false}); // do not dynamically change accelerometer poll interval Bangle.setOptions({powerSave: false}); // do not dynamically change accelerometer poll interval

View File

@ -35,7 +35,7 @@ function getData() {
logs.forEach((log, i) => { logs.forEach((log, i) => {
const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time; const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time;
if (timeStr) { if (timeStr) {
const date = new Date(timeStr); const date = new Date(typeof timeStr === 'string' ? timeStr : timeStr.ms);
let option = document.createElement("option"); let option = document.createElement("option");
option.text = date.toLocaleDateString(); option.text = date.toLocaleDateString();
option.value = i; option.value = i;
@ -89,10 +89,10 @@ function getData() {
select.onchange = () => { select.onchange = () => {
const log = logs[select.value]; const log = logs[select.value];
chart.data.labels = log.map(entry => new Date(entry.time)); chart.data.labels = log.map(entry => new Date(typeof entry.time === 'string' ? entry.time : entry.time.ms));
chart.data.datasets[0].data = log.map(entry => yTicks.indexOf(entry.type)); chart.data.datasets[0].data = log.map(entry => yTicks.indexOf(entry.type));
const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time; const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time;
chart.data.datasets[0].label = new Date(timeStr).toLocaleDateString(); chart.data.datasets[0].label = new Date(typeof timeStr === 'string' ? timeStr : timeStr.ms).toLocaleDateString();
chart.update(); chart.update();
} }
}); });

View File

@ -2,7 +2,7 @@
"id": "sleepphasealarm", "id": "sleepphasealarm",
"name": "SleepPhaseAlarm", "name": "SleepPhaseAlarm",
"shortName": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm",
"version": "0.16", "version": "0.18",
"description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.",
"icon": "app.png", "icon": "app.png",
"tags": "tool,alarm", "tags": "tool,alarm",

View File

@ -16,8 +16,8 @@
function draw(log) { function draw(log) {
const step = 10*60*1000; // resolution 10min const step = 10*60*1000; // resolution 10min
const yTicks = ["sleep", "awake", "alarm"]; const yTicks = ["sleep", "awake", "alarm"];
const starttime = new Date(log[0].time); const starttime = dateFromJson(log[0].time);
const endtime = new Date(log[log.length-1].time); const endtime = dateFromJson(log[log.length-1].time);
let logidx = 0; let logidx = 0;
let curtime = starttime; let curtime = starttime;
@ -29,7 +29,7 @@
if (logtime === undefined || curtime > logtime) { if (logtime === undefined || curtime > logtime) {
curval = yTicks.indexOf(log[logidx].type); curval = yTicks.indexOf(log[logidx].type);
logidx++; logidx++;
logtime = new Date(log[logidx].time); logtime = dateFromJson(log[logidx].time);
} }
data[i++] = curval; data[i++] = curval;
@ -70,8 +70,8 @@
const logs = config.logs.filter(log => log != null && log.filter(entry => entry.type === "alarm").length > 0); const logs = config.logs.filter(log => log != null && log.filter(entry => entry.type === "alarm").length > 0);
logs.sort(function(a, b) { // sort by alarm date desc logs.sort(function(a, b) { // sort by alarm date desc
const adate = new Date(a.filter(entry => entry.type === "alarm")[0].time); const adate = dateFromJson(a.filter(entry => entry.type === "alarm")[0].time);
const bdate = new Date(b.filter(entry => entry.type === "alarm")[0].time); const bdate = dateFromJson(b.filter(entry => entry.type === "alarm")[0].time);
return bdate - adate; return bdate - adate;
}); });
@ -79,12 +79,16 @@
menu[""] = { title: /*LANG*/"Select day" }; menu[""] = { title: /*LANG*/"Select day" };
menu["< Back"] = () => settingsmenu(); menu["< Back"] = () => settingsmenu();
logs.forEach((log, i) => { logs.forEach((log, i) => {
const date = new Date(log.filter(entry => entry.type === "alarm")[0].time); const date = dateFromJson(log.filter(entry => entry.type === "alarm")[0].time);
menu[require("locale").date(date, 1)] = () => { E.showMenu(); draw(log); }; menu[require("locale").date(date, 1)] = () => { E.showMenu(); draw(log); };
}); });
E.showMenu(menu); E.showMenu(menu);
} }
function dateFromJson(o) {
return new Date(typeof o === 'string' ? o : o.ms);
}
function settingsmenu() { function settingsmenu() {
// Show the menu // Show the menu
E.showMenu({ E.showMenu({

2
core

@ -1 +1 @@
Subproject commit 0222d3c5ac608a1b842ffc1f1f79e19276d648fe Subproject commit 2603ca6fff12cefc2d0c0e7665a669b032a78e4e

View File

@ -1,10 +1,13 @@
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never
type ExtractIds<T extends Layout.Hierarchy, Depth extends Prev[number] = 9> = type ExtractIds<T extends Layout.Hierarchy, Depth extends Prev[number] = 9> =
[Depth] extends [never] [Depth] extends [never]
? never ? never
: (T extends { id: infer Id extends string } : (T extends { id?: infer Id extends string }
? { [k in Id]: T } ? { [k in Id]: { -readonly [P in keyof T]: T[P] extends string ? string : T[P] } }
: never) : never)
| |
( (
@ -15,7 +18,7 @@ type ExtractIds<T extends Layout.Hierarchy, Depth extends Prev[number] = 9> =
declare module Layout { declare module Layout {
type Layouter<T extends Hierarchy> = type Layouter<T extends Hierarchy> =
ExtractIds<T> UnionToIntersection<ExtractIds<T>>
& &
{ {
// these actually change T // these actually change T
@ -31,6 +34,7 @@ declare module Layout {
setUI(): void; setUI(): void;
}; };
// Note: you must use new Layout({...} as const) to have ids inferred
var Layout: { var Layout: {
new <T extends Hierarchy>( new <T extends Hierarchy>(
hier: T, hier: T,