circlesclock: load circles from clkinfo
parent
11f63df3b1
commit
c435bc217d
|
|
@ -30,3 +30,4 @@
|
||||||
0.15: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16
|
0.15: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16
|
||||||
0.16: Fix const error
|
0.16: Fix const error
|
||||||
Use widget_utils if available
|
Use widget_utils if available
|
||||||
|
0.17: Load circles from clkinfo
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
let clock_info = require("clock_info");
|
||||||
let locale = require("locale");
|
let locale = require("locale");
|
||||||
let storage = require("Storage");
|
let storage = require("Storage");
|
||||||
Graphics.prototype.setFontRobotoRegular50NumericOnly = function(scale) {
|
Graphics.prototype.setFontRobotoRegular50NumericOnly = function(scale) {
|
||||||
|
|
@ -18,6 +19,7 @@ let settings = Object.assign(
|
||||||
storage.readJSON(SETTINGS_FILE, true) || {}
|
storage.readJSON(SETTINGS_FILE, true) || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//TODO deprecate this (and perhaps use in the clkinfo module)
|
||||||
// Load step goal from health app and pedometer widget as fallback
|
// Load step goal from health app and pedometer widget as fallback
|
||||||
if (settings.stepGoal == undefined) {
|
if (settings.stepGoal == undefined) {
|
||||||
let d = storage.readJSON("health.json", true) || {};
|
let d = storage.readJSON("health.json", true) || {};
|
||||||
|
|
@ -29,7 +31,7 @@ if (settings.stepGoal == undefined) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let timerHrm;
|
let timerHrm; //TODO deprecate this
|
||||||
let drawTimeout;
|
let drawTimeout;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -44,10 +46,9 @@ let showWidgets = settings.showWidgets || false;
|
||||||
let circleCount = settings.circleCount || 3;
|
let circleCount = settings.circleCount || 3;
|
||||||
let showBigWeather = settings.showBigWeather || false;
|
let showBigWeather = settings.showBigWeather || false;
|
||||||
|
|
||||||
let hrtValue;
|
let hrtValue; //TODO deprecate this
|
||||||
let now = Math.round(new Date().getTime() / 1000);
|
let now = Math.round(new Date().getTime() / 1000);
|
||||||
|
|
||||||
|
|
||||||
// layout values:
|
// layout values:
|
||||||
let colorFg = g.theme.dark ? '#fff' : '#000';
|
let colorFg = g.theme.dark ? '#fff' : '#000';
|
||||||
let colorBg = g.theme.dark ? '#000' : '#fff';
|
let colorBg = g.theme.dark ? '#000' : '#fff';
|
||||||
|
|
@ -91,8 +92,20 @@ let circleFontSmall = circleCount == 3 ? "Vector:14" : "Vector:10";
|
||||||
let circleFont = circleCount == 3 ? "Vector:15" : "Vector:11";
|
let circleFont = circleCount == 3 ? "Vector:15" : "Vector:11";
|
||||||
let circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12";
|
let circleFontBig = circleCount == 3 ? "Vector:16" : "Vector:12";
|
||||||
let iconOffset = circleCount == 3 ? 6 : 8;
|
let iconOffset = circleCount == 3 ? 6 : 8;
|
||||||
let defaultCircleTypes = ["steps", "hr", "battery", "weather"];
|
let defaultCircleTypes = ["Bangle/Steps", "Bangle/HRM", "Bangle/Battery", "weather"];
|
||||||
|
|
||||||
|
let circleInfoNum = [
|
||||||
|
0, // circle1
|
||||||
|
0, // circle2
|
||||||
|
0, // circle3
|
||||||
|
0, // circle4
|
||||||
|
];
|
||||||
|
let circleItemNum = [
|
||||||
|
0, // circle1
|
||||||
|
1, // circle2
|
||||||
|
2, // circle3
|
||||||
|
3, // circle4
|
||||||
|
];
|
||||||
|
|
||||||
function hideWidgets() {
|
function hideWidgets() {
|
||||||
/*
|
/*
|
||||||
|
|
@ -177,6 +190,15 @@ function drawCircle(index) {
|
||||||
let w = getCircleXPosition(type);
|
let w = getCircleXPosition(type);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "weather":
|
||||||
|
drawWeather(w);
|
||||||
|
break;
|
||||||
|
case "sunprogress":
|
||||||
|
case "sunProgress":
|
||||||
|
drawSunProgress(w);
|
||||||
|
break;
|
||||||
|
//TODO those are going to be deprecated, keep for backwards compatibility for now
|
||||||
|
//ideally all data should come from some clkinfo
|
||||||
case "steps":
|
case "steps":
|
||||||
drawSteps(w);
|
drawSteps(w);
|
||||||
break;
|
break;
|
||||||
|
|
@ -189,13 +211,6 @@ function drawCircle(index) {
|
||||||
case "battery":
|
case "battery":
|
||||||
drawBattery(w);
|
drawBattery(w);
|
||||||
break;
|
break;
|
||||||
case "weather":
|
|
||||||
drawWeather(w);
|
|
||||||
break;
|
|
||||||
case "sunprogress":
|
|
||||||
case "sunProgress":
|
|
||||||
drawSunProgress(w);
|
|
||||||
break;
|
|
||||||
case "temperature":
|
case "temperature":
|
||||||
drawTemperature(w);
|
drawTemperature(w);
|
||||||
break;
|
break;
|
||||||
|
|
@ -205,9 +220,12 @@ function drawCircle(index) {
|
||||||
case "altitude":
|
case "altitude":
|
||||||
drawAltitude(w);
|
drawAltitude(w);
|
||||||
break;
|
break;
|
||||||
|
//end deprecated
|
||||||
case "empty":
|
case "empty":
|
||||||
// we draw nothing here
|
// we draw nothing here
|
||||||
return;
|
return;
|
||||||
|
default:
|
||||||
|
drawClkInfo(index, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,6 +322,102 @@ function getImage(graphic, color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawWeather(w) {
|
||||||
|
if (!w) w = getCircleXPosition("weather");
|
||||||
|
let weather = getWeather();
|
||||||
|
let tempString = weather ? locale.temp(weather.temp - 273.15) : undefined;
|
||||||
|
let code = weather ? weather.code : -1;
|
||||||
|
|
||||||
|
drawCircleBackground(w);
|
||||||
|
|
||||||
|
let color = getCircleColor("weather");
|
||||||
|
let percent;
|
||||||
|
let data = settings.weatherCircleData;
|
||||||
|
switch (data) {
|
||||||
|
case "humidity":
|
||||||
|
let humidity = weather ? weather.hum : undefined;
|
||||||
|
if (humidity >= 0) {
|
||||||
|
percent = humidity / 100;
|
||||||
|
drawGauge(w, h3, percent, color);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "wind":
|
||||||
|
if (weather) {
|
||||||
|
let wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/);
|
||||||
|
if (wind[1] >= 0) {
|
||||||
|
if (wind[2] == "kmh") {
|
||||||
|
wind[1] = windAsBeaufort(wind[1]);
|
||||||
|
}
|
||||||
|
// wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale)
|
||||||
|
percent = wind[1] / 12;
|
||||||
|
drawGauge(w, h3, percent, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "empty":
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawInnerCircleAndTriangle(w);
|
||||||
|
|
||||||
|
writeCircleText(w, tempString ? tempString : "?");
|
||||||
|
|
||||||
|
if (code > 0) {
|
||||||
|
let icon = getWeatherIconByCode(code);
|
||||||
|
if (icon) g.drawImage(getImage(icon, getCircleIconColor("weather", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
||||||
|
} else {
|
||||||
|
g.drawString("?", w, h3 + radiusOuter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawSunProgress(w) {
|
||||||
|
if (!w) w = getCircleXPosition("sunprogress");
|
||||||
|
let percent = getSunProgress();
|
||||||
|
|
||||||
|
// sunset icons:
|
||||||
|
let sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA");
|
||||||
|
let sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA");
|
||||||
|
|
||||||
|
drawCircleBackground(w);
|
||||||
|
|
||||||
|
let color = getCircleColor("sunprogress");
|
||||||
|
|
||||||
|
drawGauge(w, h3, percent, color);
|
||||||
|
|
||||||
|
drawInnerCircleAndTriangle(w);
|
||||||
|
|
||||||
|
let icon = sunSetDown;
|
||||||
|
let text = "?";
|
||||||
|
let times = getSunData();
|
||||||
|
if (times != undefined) {
|
||||||
|
let sunRise = Math.round(times.sunrise.getTime() / 1000);
|
||||||
|
let sunSet = Math.round(times.sunset.getTime() / 1000);
|
||||||
|
if (!isDay()) {
|
||||||
|
// night
|
||||||
|
if (now > sunRise) {
|
||||||
|
// after sunRise
|
||||||
|
let upcomingSunRise = sunRise + 60 * 60 * 24;
|
||||||
|
text = formatSeconds(upcomingSunRise - now);
|
||||||
|
} else {
|
||||||
|
text = formatSeconds(sunRise - now);
|
||||||
|
}
|
||||||
|
icon = sunSetUp;
|
||||||
|
} else {
|
||||||
|
// day, approx sunrise tomorrow:
|
||||||
|
text = formatSeconds(sunSet - now);
|
||||||
|
icon = sunSetDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCircleText(w, text);
|
||||||
|
|
||||||
|
g.drawImage(getImage(icon, getCircleIconColor("sunprogress", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deprecated but nice as references for clkinfo
|
||||||
|
*/
|
||||||
|
|
||||||
function drawSteps(w) {
|
function drawSteps(w) {
|
||||||
if (!w) w = getCircleXPosition("steps");
|
if (!w) w = getCircleXPosition("steps");
|
||||||
let steps = getSteps();
|
let steps = getSteps();
|
||||||
|
|
@ -406,99 +520,6 @@ function drawBattery(w) {
|
||||||
|
|
||||||
g.drawImage(getImage(powerIcon, getCircleIconColor("battery", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
g.drawImage(getImage(powerIcon, getCircleIconColor("battery", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawWeather(w) {
|
|
||||||
if (!w) w = getCircleXPosition("weather");
|
|
||||||
let weather = getWeather();
|
|
||||||
let tempString = weather ? locale.temp(weather.temp - 273.15) : undefined;
|
|
||||||
let code = weather ? weather.code : -1;
|
|
||||||
|
|
||||||
drawCircleBackground(w);
|
|
||||||
|
|
||||||
let color = getCircleColor("weather");
|
|
||||||
let percent;
|
|
||||||
let data = settings.weatherCircleData;
|
|
||||||
switch (data) {
|
|
||||||
case "humidity":
|
|
||||||
let humidity = weather ? weather.hum : undefined;
|
|
||||||
if (humidity >= 0) {
|
|
||||||
percent = humidity / 100;
|
|
||||||
drawGauge(w, h3, percent, color);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "wind":
|
|
||||||
if (weather) {
|
|
||||||
let wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/);
|
|
||||||
if (wind[1] >= 0) {
|
|
||||||
if (wind[2] == "kmh") {
|
|
||||||
wind[1] = windAsBeaufort(wind[1]);
|
|
||||||
}
|
|
||||||
// wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale)
|
|
||||||
percent = wind[1] / 12;
|
|
||||||
drawGauge(w, h3, percent, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "empty":
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawInnerCircleAndTriangle(w);
|
|
||||||
|
|
||||||
writeCircleText(w, tempString ? tempString : "?");
|
|
||||||
|
|
||||||
if (code > 0) {
|
|
||||||
let icon = getWeatherIconByCode(code);
|
|
||||||
if (icon) g.drawImage(getImage(icon, getCircleIconColor("weather", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
|
||||||
} else {
|
|
||||||
g.drawString("?", w, h3 + radiusOuter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawSunProgress(w) {
|
|
||||||
if (!w) w = getCircleXPosition("sunprogress");
|
|
||||||
let percent = getSunProgress();
|
|
||||||
|
|
||||||
// sunset icons:
|
|
||||||
let sunSetDown = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAAGYAPAAYAAAAAA");
|
|
||||||
let sunSetUp = atob("EBCBAAAAAAABgAAAAAATyAZoBCB//gAAAAABgAPABmAAAAAA");
|
|
||||||
|
|
||||||
drawCircleBackground(w);
|
|
||||||
|
|
||||||
let color = getCircleColor("sunprogress");
|
|
||||||
|
|
||||||
drawGauge(w, h3, percent, color);
|
|
||||||
|
|
||||||
drawInnerCircleAndTriangle(w);
|
|
||||||
|
|
||||||
let icon = sunSetDown;
|
|
||||||
let text = "?";
|
|
||||||
let times = getSunData();
|
|
||||||
if (times != undefined) {
|
|
||||||
let sunRise = Math.round(times.sunrise.getTime() / 1000);
|
|
||||||
let sunSet = Math.round(times.sunset.getTime() / 1000);
|
|
||||||
if (!isDay()) {
|
|
||||||
// night
|
|
||||||
if (now > sunRise) {
|
|
||||||
// after sunRise
|
|
||||||
let upcomingSunRise = sunRise + 60 * 60 * 24;
|
|
||||||
text = formatSeconds(upcomingSunRise - now);
|
|
||||||
} else {
|
|
||||||
text = formatSeconds(sunRise - now);
|
|
||||||
}
|
|
||||||
icon = sunSetUp;
|
|
||||||
} else {
|
|
||||||
// day, approx sunrise tomorrow:
|
|
||||||
text = formatSeconds(sunSet - now);
|
|
||||||
icon = sunSetDown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeCircleText(w, text);
|
|
||||||
|
|
||||||
g.drawImage(getImage(icon, getCircleIconColor("sunprogress", color, percent)), w - iconOffset, h3 + radiusOuter - iconOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawTemperature(w) {
|
function drawTemperature(w) {
|
||||||
if (!w) w = getCircleXPosition("temperature");
|
if (!w) w = getCircleXPosition("temperature");
|
||||||
|
|
||||||
|
|
@ -577,6 +598,113 @@ function drawAltitude(w) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shortValue(v) {
|
||||||
|
if (isNaN(v)) return '-';
|
||||||
|
if (v <= 999) return v;
|
||||||
|
if (v >= 1000 && v < 10000) {
|
||||||
|
v = Math.floor(v / 100) * 100;
|
||||||
|
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
||||||
|
}
|
||||||
|
if (v >= 10000) {
|
||||||
|
v = Math.floor(v / 1000) * 1000;
|
||||||
|
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSteps() {
|
||||||
|
if (Bangle.getHealthStatus) {
|
||||||
|
return Bangle.getHealthStatus("day").steps;
|
||||||
|
}
|
||||||
|
if (WIDGETS && WIDGETS.wpedom !== undefined) {
|
||||||
|
return WIDGETS.wpedom.getSteps();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPressureValue(type) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (Bangle.getPressure) {
|
||||||
|
if (!pressureLocked) {
|
||||||
|
pressureLocked = true;
|
||||||
|
if (pressureCache && pressureCache[type]) {
|
||||||
|
resolve(pressureCache[type]);
|
||||||
|
}
|
||||||
|
Bangle.getPressure().then(function(d) {
|
||||||
|
pressureLocked = false;
|
||||||
|
if (d) {
|
||||||
|
pressureCache = d;
|
||||||
|
if (d[type]) {
|
||||||
|
resolve(d[type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(() => {});
|
||||||
|
} else {
|
||||||
|
if (pressureCache && pressureCache[type]) {
|
||||||
|
resolve(pressureCache[type]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* end deprecated
|
||||||
|
*/
|
||||||
|
|
||||||
|
var menu = null;
|
||||||
|
function reloadMenu() {
|
||||||
|
menu = clock_info.load();
|
||||||
|
for(var i=1; i<5; i++)
|
||||||
|
if(settings['circle'+i].includes("/")) {
|
||||||
|
let parts = settings['circle'+i].split("/");
|
||||||
|
let infoName = parts[0], itemName = parts[1];
|
||||||
|
let infoNum = menu.findIndex(e=>e.name==infoName);
|
||||||
|
let itemNum = 0;
|
||||||
|
//suppose unnamed are varying (like timers or events), pick the first
|
||||||
|
if(itemName)
|
||||||
|
itemNum = menu[infoNum].items.findIndex(it=>it.name==itemName);
|
||||||
|
circleInfoNum[i-1] = infoNum;
|
||||||
|
circleItemNum[i-1] = itemNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//reload periodically for changes?
|
||||||
|
reloadMenu();
|
||||||
|
|
||||||
|
function drawEmpty(img, w, color) {
|
||||||
|
drawGauge(w, h3, 0, color);
|
||||||
|
drawInnerCircleAndTriangle(w);
|
||||||
|
writeCircleText(w, "?");
|
||||||
|
if(img)
|
||||||
|
g.setColor(getGradientColor(color, 0))
|
||||||
|
.drawImage(img, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: 16/24});
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawClkInfo(index, w) {
|
||||||
|
var info = menu[circleInfoNum[index-1]];
|
||||||
|
var type = settings['circle'+index];
|
||||||
|
if (!w) w = getCircleXPosition(type);
|
||||||
|
drawCircleBackground(w);
|
||||||
|
const color = getCircleColor(type);
|
||||||
|
if(!info || !info.items.length) {
|
||||||
|
drawEmpty(info? info.img : null, w, color);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var item = info.items[circleItemNum[index-1]];
|
||||||
|
//TODO do hide()+get() here
|
||||||
|
item.show();
|
||||||
|
item.hide();
|
||||||
|
item=item.get();
|
||||||
|
var img = item.img;
|
||||||
|
if(!img) img = info.img;
|
||||||
|
let percent = (item.v-item.min) / item.max;
|
||||||
|
if(isNaN(percent)) percent = 1; //fill it up
|
||||||
|
drawGauge(w, h3, percent, color);
|
||||||
|
drawInnerCircleAndTriangle(w);
|
||||||
|
writeCircleText(w, item.text);
|
||||||
|
g.setColor(getCircleIconColor(type, color, percent))
|
||||||
|
.drawImage(img, w - iconOffset, h3 + radiusOuter - iconOffset, {scale: 16/24});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale)
|
* wind goes from 0 to 12 (see https://en.wikipedia.org/wiki/Beaufort_scale)
|
||||||
*/
|
*/
|
||||||
|
|
@ -770,125 +898,15 @@ function writeCircleText(w, content) {
|
||||||
g.drawString(content, w, h3);
|
g.drawString(content, w, h3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function shortValue(v) {
|
|
||||||
if (isNaN(v)) return '-';
|
|
||||||
if (v <= 999) return v;
|
|
||||||
if (v >= 1000 && v < 10000) {
|
|
||||||
v = Math.floor(v / 100) * 100;
|
|
||||||
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
|
||||||
}
|
|
||||||
if (v >= 10000) {
|
|
||||||
v = Math.floor(v / 1000) * 1000;
|
|
||||||
return (v / 1000).toFixed(1).replace(/\.0$/, '') + 'k';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSteps() {
|
|
||||||
if (Bangle.getHealthStatus) {
|
|
||||||
return Bangle.getHealthStatus("day").steps;
|
|
||||||
}
|
|
||||||
if (WIDGETS && WIDGETS.wpedom !== undefined) {
|
|
||||||
return WIDGETS.wpedom.getSteps();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWeather() {
|
function getWeather() {
|
||||||
let jsonWeather = storage.readJSON('weather.json');
|
let jsonWeather = storage.readJSON('weather.json');
|
||||||
return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined;
|
return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableHRMSensor() {
|
|
||||||
Bangle.setHRMPower(1, "circleclock");
|
|
||||||
if (hrtValue == undefined) {
|
|
||||||
hrtValue = '...';
|
|
||||||
drawHeartRate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let pressureLocked = false;
|
|
||||||
let pressureCache;
|
|
||||||
|
|
||||||
function getPressureValue(type) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (Bangle.getPressure) {
|
|
||||||
if (!pressureLocked) {
|
|
||||||
pressureLocked = true;
|
|
||||||
if (pressureCache && pressureCache[type]) {
|
|
||||||
resolve(pressureCache[type]);
|
|
||||||
}
|
|
||||||
Bangle.getPressure().then(function(d) {
|
|
||||||
pressureLocked = false;
|
|
||||||
if (d) {
|
|
||||||
pressureCache = d;
|
|
||||||
if (d[type]) {
|
|
||||||
resolve(d[type]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).catch(() => {});
|
|
||||||
} else {
|
|
||||||
if (pressureCache && pressureCache[type]) {
|
|
||||||
resolve(pressureCache[type]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLock(isLocked) {
|
|
||||||
if (!isLocked) {
|
|
||||||
draw();
|
|
||||||
if (isCircleEnabled("hr")) {
|
|
||||||
enableHRMSensor();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Bangle.setHRMPower(0, "circleclock");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bangle.on('lock', onLock);
|
|
||||||
|
|
||||||
function onHRM(hrm) {
|
|
||||||
if (isCircleEnabled("hr")) {
|
|
||||||
if (hrm.confidence >= (settings.confidence)) {
|
|
||||||
hrtValue = hrm.bpm;
|
|
||||||
if (Bangle.isLCDOn()) {
|
|
||||||
drawHeartRate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Let us wait before we overwrite "good" HRM values:
|
|
||||||
if (Bangle.isLCDOn()) {
|
|
||||||
if (timerHrm) clearTimeout(timerHrm);
|
|
||||||
timerHrm = setTimeout(() => {
|
|
||||||
hrtValue = '...';
|
|
||||||
drawHeartRate();
|
|
||||||
}, settings.hrmValidity * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Bangle.on('HRM', onHRM);
|
|
||||||
|
|
||||||
function onCharging(charging) {
|
|
||||||
if (isCircleEnabled("battery")) drawBattery();
|
|
||||||
}
|
|
||||||
Bangle.on('charging', onCharging);
|
|
||||||
|
|
||||||
|
|
||||||
if (isCircleEnabled("hr")) {
|
|
||||||
enableHRMSensor();
|
|
||||||
}
|
|
||||||
|
|
||||||
Bangle.setUI({
|
Bangle.setUI({
|
||||||
mode : "clock",
|
mode : "clock",
|
||||||
remove : function() {
|
remove : function() {
|
||||||
// Called to unload all of the clock app
|
// Called to unload all of the clock app
|
||||||
Bangle.removeListener('charging', onCharging);
|
|
||||||
Bangle.removeListener('lock', onLock);
|
|
||||||
Bangle.removeListener('HRM', onHRM);
|
|
||||||
|
|
||||||
Bangle.setHRMPower(0, "circleclock");
|
|
||||||
|
|
||||||
if (timerHrm) clearTimeout(timerHrm);
|
|
||||||
timerHrm = undefined;
|
|
||||||
if (drawTimeout) clearTimeout(drawTimeout);
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
drawTimeout = undefined;
|
drawTimeout = undefined;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
{
|
{
|
||||||
"minHR": 40,
|
|
||||||
"maxHR": 200,
|
|
||||||
"confidence": 0,
|
|
||||||
"stepGoal": 10000,
|
|
||||||
"stepDistanceGoal": 8000,
|
|
||||||
"stepLength": 0.8,
|
|
||||||
"batteryWarn": 30,
|
"batteryWarn": 30,
|
||||||
"showWidgets": false,
|
"showWidgets": false,
|
||||||
"weatherCircleData": "humidity",
|
"weatherCircleData": "humidity",
|
||||||
"circleCount": 3,
|
"circleCount": 3,
|
||||||
"circle1": "hr",
|
"circle1": "Bangle/HRM",
|
||||||
"circle2": "steps",
|
"circle2": "Bangle/Steps",
|
||||||
"circle3": "battery",
|
"circle3": "Bangle/Battery",
|
||||||
"circle4": "weather",
|
"circle4": "weather",
|
||||||
"circle1color": "green-red",
|
"circle1color": "green-red",
|
||||||
"circle2color": "#0000ff",
|
"circle2color": "#0000ff",
|
||||||
|
|
@ -21,7 +15,15 @@
|
||||||
"circle2colorizeIcon": true,
|
"circle2colorizeIcon": true,
|
||||||
"circle3colorizeIcon": true,
|
"circle3colorizeIcon": true,
|
||||||
"circle4colorizeIcon": false,
|
"circle4colorizeIcon": false,
|
||||||
"hrmValidity": 60,
|
|
||||||
"updateInterval": 60,
|
"updateInterval": 60,
|
||||||
"showBigWeather": false
|
"showBigWeather": false,
|
||||||
|
|
||||||
|
"minHR": 40,
|
||||||
|
"maxHR": 200,
|
||||||
|
"confidence": 0,
|
||||||
|
"stepGoal": 10000,
|
||||||
|
"stepDistanceGoal": 8000,
|
||||||
|
"stepLength": 0.8,
|
||||||
|
"hrmValidity": 60
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{ "id": "circlesclock",
|
{ "id": "circlesclock",
|
||||||
"name": "Circles clock",
|
"name": "Circles clock",
|
||||||
"shortName":"Circles clock",
|
"shortName":"Circles clock",
|
||||||
"version":"0.16",
|
"version":"0.17",
|
||||||
"description": "A clock with three or four circles for different data at the bottom in a probably familiar style",
|
"description": "A clock with three or four 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"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}],
|
"screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}],
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
(function(back) {
|
(function(back) {
|
||||||
const SETTINGS_FILE = "circlesclock.json";
|
const SETTINGS_FILE = "circlesclock.json";
|
||||||
const storage = require('Storage');
|
const storage = require('Storage');
|
||||||
|
const clock_info = require("clock_info");
|
||||||
let settings = Object.assign(
|
let settings = Object.assign(
|
||||||
storage.readJSON("circlesclock.default.json", true) || {},
|
storage.readJSON("circlesclock.default.json", true) || {},
|
||||||
storage.readJSON(SETTINGS_FILE, true) || {}
|
storage.readJSON(SETTINGS_FILE, true) || {}
|
||||||
|
|
@ -11,8 +12,25 @@
|
||||||
storage.write(SETTINGS_FILE, settings);
|
storage.write(SETTINGS_FILE, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
const valuesCircleTypes = ["empty", "steps", "stepsDist", "hr", "battery", "weather", "sunprogress", "temperature", "pressure", "altitude"];
|
//const valuesCircleTypes = ["empty", "steps", "stepsDist", "hr", "battery", "weather", "sunprogress", "temperature", "pressure", "altitude", "timer"];
|
||||||
const namesCircleTypes = ["empty", "steps", "distance", "heart", "battery", "weather", "sun", "temperature", "pressure", "altitude"];
|
//const namesCircleTypes = ["empty", "steps", "distance", "heart", "battery", "weather", "sun", "temperature", "pressure", "altitude", "timer"];
|
||||||
|
var valuesCircleTypes = ["empty","weather", "sunprogress"];
|
||||||
|
var namesCircleTypes = ["empty","weather", "sun"];
|
||||||
|
clock_info.load().forEach(e=>{
|
||||||
|
//TODO filter for hasRange and other
|
||||||
|
if(!e.items.length || !e.items[0].name) {
|
||||||
|
//suppose unnamed are varying (like timers or events), pick the first
|
||||||
|
item = e.items[0];
|
||||||
|
valuesCircleTypes = valuesCircleTypes.concat([e.name+"/"]);
|
||||||
|
namesCircleTypes = namesCircleTypes.concat([e.name]);
|
||||||
|
} else {
|
||||||
|
let values = e.items.map(i=>e.name+"/"+i.name);
|
||||||
|
let names =e.name=="Bangle" ? e.items.map(i=>i.name) : values;
|
||||||
|
valuesCircleTypes = valuesCircleTypes.concat(values);
|
||||||
|
namesCircleTypes = namesCircleTypes.concat(names);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const valuesColors = ["", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff",
|
const valuesColors = ["", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff",
|
||||||
"#00ffff", "#fff", "#000", "green-red", "red-green", "fg"];
|
"#00ffff", "#fff", "#000", "green-red", "red-green", "fg"];
|
||||||
|
|
@ -36,8 +54,6 @@
|
||||||
/*LANG*/'circle 2': ()=>showCircleMenu(2),
|
/*LANG*/'circle 2': ()=>showCircleMenu(2),
|
||||||
/*LANG*/'circle 3': ()=>showCircleMenu(3),
|
/*LANG*/'circle 3': ()=>showCircleMenu(3),
|
||||||
/*LANG*/'circle 4': ()=>showCircleMenu(4),
|
/*LANG*/'circle 4': ()=>showCircleMenu(4),
|
||||||
/*LANG*/'heartrate': ()=>showHRMenu(),
|
|
||||||
/*LANG*/'steps': ()=>showStepMenu(),
|
|
||||||
/*LANG*/'battery warn': {
|
/*LANG*/'battery warn': {
|
||||||
value: settings.batteryWarn,
|
value: settings.batteryWarn,
|
||||||
min: 10,
|
min: 10,
|
||||||
|
|
@ -78,91 +94,6 @@
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHRMenu() {
|
|
||||||
let menu = {
|
|
||||||
'': { 'title': /*LANG*/'Heartrate' },
|
|
||||||
/*LANG*/'< Back': ()=>showMainMenu(),
|
|
||||||
/*LANG*/'minimum': {
|
|
||||||
value: settings.minHR,
|
|
||||||
min: 0,
|
|
||||||
max : 250,
|
|
||||||
step: 5,
|
|
||||||
format: x => {
|
|
||||||
return x + " bpm";
|
|
||||||
},
|
|
||||||
onchange: x => save('minHR', x),
|
|
||||||
},
|
|
||||||
/*LANG*/'maximum': {
|
|
||||||
value: settings.maxHR,
|
|
||||||
min: 20,
|
|
||||||
max : 250,
|
|
||||||
step: 5,
|
|
||||||
format: x => {
|
|
||||||
return x + " bpm";
|
|
||||||
},
|
|
||||||
onchange: x => save('maxHR', x),
|
|
||||||
},
|
|
||||||
/*LANG*/'min. confidence': {
|
|
||||||
value: settings.confidence,
|
|
||||||
min: 0,
|
|
||||||
max : 100,
|
|
||||||
step: 10,
|
|
||||||
format: x => {
|
|
||||||
return x + "%";
|
|
||||||
},
|
|
||||||
onchange: x => save('confidence', x),
|
|
||||||
},
|
|
||||||
/*LANG*/'valid period': {
|
|
||||||
value: settings.hrmValidity,
|
|
||||||
min: 10,
|
|
||||||
max : 1800,
|
|
||||||
step: 10,
|
|
||||||
format: x => {
|
|
||||||
return x + "s";
|
|
||||||
},
|
|
||||||
onchange: x => save('hrmValidity', x),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
E.showMenu(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showStepMenu() {
|
|
||||||
let menu = {
|
|
||||||
'': { 'title': /*LANG*/'Steps' },
|
|
||||||
/*LANG*/'< Back': ()=>showMainMenu(),
|
|
||||||
/*LANG*/'goal': {
|
|
||||||
value: settings.stepGoal,
|
|
||||||
min: 1000,
|
|
||||||
max : 50000,
|
|
||||||
step: 500,
|
|
||||||
format: x => {
|
|
||||||
return x;
|
|
||||||
},
|
|
||||||
onchange: x => save('stepGoal', x),
|
|
||||||
},
|
|
||||||
/*LANG*/'distance goal': {
|
|
||||||
value: settings.stepDistanceGoal,
|
|
||||||
min: 1000,
|
|
||||||
max : 50000,
|
|
||||||
step: 500,
|
|
||||||
format: x => {
|
|
||||||
return x;
|
|
||||||
},
|
|
||||||
onchange: x => save('stepDistanceGoal', x),
|
|
||||||
},
|
|
||||||
/*LANG*/'step length': {
|
|
||||||
value: settings.stepLength,
|
|
||||||
min: 0.1,
|
|
||||||
max : 1.5,
|
|
||||||
step: 0.01,
|
|
||||||
format: x => {
|
|
||||||
return x;
|
|
||||||
},
|
|
||||||
onchange: x => save('stepLength', x),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
E.showMenu(menu);
|
|
||||||
}
|
|
||||||
function showCircleMenu(circleId) {
|
function showCircleMenu(circleId) {
|
||||||
const circleName = "circle" + circleId;
|
const circleName = "circle" + circleId;
|
||||||
const colorKey = circleName + "color";
|
const colorKey = circleName + "color";
|
||||||
|
|
@ -192,6 +123,5 @@
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
showMainMenu();
|
showMainMenu();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue