1
0
Fork 0

Merge branch 'master' of github.com:espruino/BangleApps

master
Gordon Williams 2022-05-16 14:35:35 +01:00
commit 22a7de9a87
14 changed files with 331 additions and 115 deletions

View File

@ -2,3 +2,4 @@
0.02: Fix the settings bug and some tweaking
0.03: Do not alarm while charging
0.04: Obey system quiet mode
0.05: Battery optimisation, add the pause option, bug fixes

View File

@ -7,8 +7,8 @@ Different settings can be personalized:
- Enable : Enable/Disable the app
- Start hour: Hour to start the reminder
- End hour: Hour to end the reminder
- Max inactivity: Maximum inactivity time to allow before the alert. From 15 to 60 min
- Max inactivity: Maximum inactivity time to allow before the alert. From 15 to 120 min
- Dismiss delay: Delay added before the next alert if the alert is dismissed. From 5 to 60 min
Notice: If Dissmiss delay > Max inactivity then it will be equal Max inactivity
- Pause delay: Same as Dismiss delay but longer (usefull for meetings and such). From 30 to 240 min
- Min steps: Minimal amount of steps to count as an activity

View File

@ -1,40 +1,42 @@
function drawAlert(){
E.showPrompt("Inactivity detected",{
title:"Activity reminder",
buttons : {"Ok": true,"Dismiss": false}
}).then(function(v) {
if(v == true){
stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3);
require("activityreminder").saveStepsArray(stepsArray);
}
if(v == false){
stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin);
require("activityreminder").saveStepsArray(stepsArray);
}
function drawAlert() {
E.showPrompt("Inactivity detected", {
title: "Activity reminder",
buttons: { "Ok": 1, "Dismiss": 2, "Pause": 3 }
}).then(function (v) {
if (v == 1) {
activityreminder_data.okDate = new Date();
}
if (v == 2) {
activityreminder_data.dismissDate = new Date();
}
if (v == 3) {
activityreminder_data.pauseDate = new Date();
}
activityreminder.saveData(activityreminder_data);
load();
});
// Obey system quiet mode:
if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) {
if (!(storage.readJSON('setting.json', 1) || {}).quiet) {
Bangle.buzz(400);
}
setTimeout(load, 20000);
}
function run(){
if(stepsArray.length == activityreminder.maxInnactivityMin){
if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps){
drawAlert();
}
}else{
eval(require("Storage").read("activityreminder.settings.js"))(()=>load());
}
function run() {
if (activityreminder.mustAlert(activityreminder_data, activityreminder_settings)) {
drawAlert();
} else {
eval(storage.read("activityreminder.settings.js"))(() => load());
}
}
const activityreminder = require("activityreminder");
const storage = require("Storage");
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
activityreminder = require("activityreminder").loadSettings();
stepsArray = require("activityreminder").loadStepsArray();
const activityreminder_settings = activityreminder.loadSettings();
const activityreminder_data = activityreminder.loadData();
run();

View File

@ -1,30 +1,45 @@
function run(){
if (Bangle.isCharging()) return;
var now = new Date();
var h = now.getHours();
if(h >= activityreminder.startHour && h < activityreminder.endHour){
var health = Bangle.getHealthStatus("day");
stepsArray.unshift(health.steps);
stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin);
require("activityreminder").saveStepsArray(stepsArray);
}
else{
if(stepsArray != []){
stepsArray = [];
require("activityreminder").saveStepsArray(stepsArray);
function run() {
if (isNotWorn()) return;
let now = new Date();
let h = now.getHours();
let health = Bangle.getHealthStatus("day");
if (h >= activityreminder_settings.startHour && h < activityreminder_settings.endHour) {
if (health.steps - activityreminder_data.stepsOnDate >= activityreminder_settings.minSteps // more steps made than needed
|| health.steps < activityreminder_data.stepsOnDate) { // new day or reboot of the watch
activityreminder_data.stepsOnDate = health.steps;
activityreminder_data.stepsDate = now;
activityreminder.saveData(activityreminder_data);
/* todo in a futur release
add settimer to trigger like 10 secs after the stepsDate + minSteps
cancel all other timers of this app
*/
}
}
if(stepsArray.length >= activityreminder.maxInnactivityMin){
if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps){
if(activityreminder.mustAlert(activityreminder_data, activityreminder_settings)){
load('activityreminder.app.js');
}
}
}
function isNotWorn() {
// todo in a futur release check temperature and mouvement in a futur release
return Bangle.isCharging();
}
activityreminder = require("activityreminder").loadSettings();
if(activityreminder.enabled) {
stepsArray = require("activityreminder").loadStepsArray();
const activityreminder = require("activityreminder");
const activityreminder_settings = activityreminder.loadSettings();
if (activityreminder_settings.enabled) {
const activityreminder_data = activityreminder.loadData();
if(activityreminder_data.firstLoad){
activityreminder_data.firstLoad =false;
activityreminder.saveData(activityreminder_data);
}
setInterval(run, 60000);
/* todo in a futur release
increase setInterval time to something that is still sensible (5 mins ?)
add settimer to trigger like 10 secs after the stepsDate + minSteps
cancel all other timers of this app
*/
}

View File

@ -1,22 +1,57 @@
exports.loadSettings = function() {
const storage = require("Storage");
exports.loadSettings = function () {
return Object.assign({
enabled: true,
startHour: 9,
endHour: 20,
maxInnactivityMin: 30,
dismissDelayMin: 15,
pauseDelayMin: 120,
minSteps: 50
}, require("Storage").readJSON("activityreminder.s.json", true) || {});
}, storage.readJSON("activityreminder.s.json", true) || {});
};
exports.writeSettings = function(settings){
require("Storage").writeJSON("activityreminder.s.json", settings);
exports.writeSettings = function (settings) {
storage.writeJSON("activityreminder.s.json", settings);
};
exports.saveStepsArray = function(stepsArray) {
require("Storage").writeJSON("activityreminder.sa.json", stepsArray);
exports.saveData = function (data) {
storage.writeJSON("activityreminder.data.json", data);
};
exports.loadStepsArray = function(){
return require("Storage").readJSON("activityreminder.sa.json") || [];
};
exports.loadData = function () {
let health = Bangle.getHealthStatus("day");
const data = Object.assign({
firstLoad: true,
stepsDate: new Date(),
stepsOnDate: health.steps,
okDate: new Date(1970),
dismissDate: new Date(1970),
pauseDate: new Date(1970),
},
storage.readJSON("activityreminder.data.json") || {});
if(typeof(data.stepsDate) == "string")
data.stepsDate = new Date(data.stepsDate);
if(typeof(data.okDate) == "string")
data.okDate = new Date(data.okDate);
if(typeof(data.dismissDate) == "string")
data.dismissDate = new Date(data.dismissDate);
if(typeof(data.pauseDate) == "string")
data.pauseDate = new Date(data.pauseDate);
return data;
};
exports.mustAlert = function(activityreminder_data, activityreminder_settings) {
let now = new Date();
if ((now - activityreminder_data.stepsDate) / 60000 > activityreminder_settings.maxInnactivityMin) { // inactivity detected
if ((now - activityreminder_data.okDate) / 60000 > 3 && // last alert anwsered with ok was more than 3 min ago
(now - activityreminder_data.dismissDate) / 60000 > activityreminder_settings.dismissDelayMin && // last alert was more than dismissDelayMin ago
(now - activityreminder_data.pauseDate) / 60000 > activityreminder_settings.pauseDelayMin) { // last alert was more than pauseDelayMin ago
return true;
}
}
return false;
}

View File

@ -3,7 +3,7 @@
"name": "Activity Reminder",
"shortName":"Activity Reminder",
"description": "A reminder to take short walks for the ones with a sedentary lifestyle",
"version":"0.04",
"version":"0.05",
"icon": "app.png",
"type": "app",
"tags": "tool,activity",
@ -18,6 +18,6 @@
],
"data": [
{"name": "activityreminder.s.json"},
{"name": "activityreminder.sa.json"}
{"name": "activityreminder.data.json"}
]
}

View File

@ -1,64 +1,76 @@
(function(back) {
(function (back) {
// Load settings
var settings = require("activityreminder").loadSettings();
const activityreminder = require("activityreminder");
const settings = activityreminder.loadSettings();
// Show the menu
E.showMenu({
"" : { "title" : "Activity Reminder" },
"< Back" : () => back(),
'Enable': {
value: settings.enabled,
format: v => v?"Yes":"No",
onchange: v => {
settings.enabled = v;
require("activityreminder").writeSettings(settings);
}
"": { "title": "Activity Reminder" },
"< Back": () => back(),
'Enable': {
value: settings.enabled,
format: v => v ? "Yes" : "No",
onchange: v => {
settings.enabled = v;
activityreminder.writeSettings(settings);
}
},
'Start hour': {
value: settings.startHour,
min: 0, max: 24,
onchange: v => {
settings.startHour = v;
activityreminder.writeSettings(settings);
}
},
'End hour': {
value: settings.endHour,
min: 0, max: 24,
onchange: v => {
settings.endHour = v;
activityreminder.writeSettings(settings);
}
},
'Max inactivity': {
value: settings.maxInnactivityMin,
min: 15, max: 120,
onchange: v => {
settings.maxInnactivityMin = v;
activityreminder.writeSettings(settings);
},
'Start hour': {
value: settings.startHour,
min: 0, max: 24,
onchange: v => {
settings.startHour = v;
require("activityreminder").writeSettings(settings);
}
},
'End hour': {
value: settings.endHour,
min: 0, max: 24,
onchange: v => {
settings.endHour = v;
require("activityreminder").writeSettings(settings);
}
},
'Max inactivity': {
value: settings.maxInnactivityMin,
min: 15, max: 120,
onchange: v => {
settings.maxInnactivityMin = v;
require("activityreminder").writeSettings(settings);
},
format: x => {
return x + " min";
}
},
'Dismiss delay': {
value: settings.dismissDelayMin,
min: 5, max: 60,
onchange: v => {
settings.dismissDelayMin = v;
require("activityreminder").writeSettings(settings);
},
format: x => {
return x + " min";
}
},
'Min steps': {
value: settings.minSteps,
min: 10, max: 500,
onchange: v => {
settings.minSteps = v;
require("activityreminder").writeSettings(settings);
}
}
format: x => {
return x + " min";
}
},
'Dismiss delay': {
value: settings.dismissDelayMin,
min: 5, max: 60,
onchange: v => {
settings.dismissDelayMin = v;
activityreminder.writeSettings(settings);
},
format: x => {
return x + " min";
}
},
'Pause delay': {
value: settings.pauseDelayMin,
min: 30, max: 240,
onchange: v => {
settings.pauseDelayMin = v;
activityreminder.writeSettings(settings);
},
format: x => {
return x + " min";
}
},
'Min steps': {
value: settings.minSteps,
min: 10, max: 500,
onchange: v => {
settings.minSteps = v;
activityreminder.writeSettings(settings);
}
}
});
})

View File

@ -0,0 +1,11 @@
# Banglejs - Touchscreen calibration
A simple calibration app for the touchscreen
## Usage
Once lauched touch the cross that appear on the screen to make
another spawn elsewhere.
each new touch on the screen will help to calibrate the offset
of your finger on the screen. After five or more input, press
the button to save the calibration and close the application.

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkB/4AJ+EPBhQXg+BBDCyJaGGR5zIDBoQEL4QYOLYR3GBIouJR5AYBGBILBU5QMGFwgiFX4wwIEI4XGGBAgHd44+HD44XHNw4XWM5IIHCIoXWV5IXICQgXvLxAAKCYYXh5nMC6n8C4PPC5MAAA8PC4ZxBACAXOI653hU5zvJABASEC5PwHI4XcMBIXICIoXXJBAXHCAwXXJBAXHB5AfGC4ygJEAwXGQ5BoIQxoiDBYgXECwIuIBgb5ECIQJFGBQmCC4QHEDBwAFCxoYICx5ZELZoZJFiIXpA="))

85
apps/calibration/app.js Normal file
View File

@ -0,0 +1,85 @@
class BanglejsApp {
constructor() {
this.x = 0;
this.y = 0;
this.settings = {
xoffset: 0,
yoffset: 0,
};
}
load_settings() {
let settings = require('Storage').readJSON('calibration.json', true) || {active: false};
// do nothing if the calibration is deactivated
if (settings.active === true) {
// cancel the calibration offset
Bangle.on('touch', function(button, xy) {
xy.x += settings.xoffset;
xy.y += settings.yoffset;
});
}
if (!settings.xoffset) settings.xoffset = 0;
if (!settings.yoffset) settings.yoffset = 0;
console.log('loaded settings:');
console.log(settings);
return settings;
}
save_settings() {
this.settings.active = true;
this.settings.reload = false;
require('Storage').writeJSON('calibration.json', this.settings);
console.log('saved settings:');
console.log(this.settings);
}
explain() {
/*
* TODO:
* Present how to use the application
*
*/
}
drawTarget() {
this.x = 16 + Math.floor(Math.random() * (g.getWidth() - 32));
this.y = 40 + Math.floor(Math.random() * (g.getHeight() - 80));
g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24);
g.drawLine(this.x, this.y - 5, this.x, this.y + 5);
g.drawLine(this.x - 5, this.y, this.x + 5, this.y);
g.setFont('Vector', 10);
g.drawString('current offset: ' + this.settings.xoffset + ', ' + this.settings.yoffset, 0, 24);
}
setOffset(xy) {
this.settings.xoffset = Math.round((this.settings.xoffset + (this.x - Math.floor((this.x + xy.x)/2)))/2);
this.settings.yoffset = Math.round((this.settings.yoffset + (this.y - Math.floor((this.y + xy.y)/2)))/2);
}
}
E.srand(Date.now());
Bangle.loadWidgets();
Bangle.drawWidgets();
calibration = new BanglejsApp();
calibration.load_settings();
let modes = {
mode : 'custom',
btn : function(n) {
calibration.save_settings(this.settings);
load();
},
touch : function(btn, xy) {
calibration.setOffset(xy);
calibration.drawTarget();
},
};
Bangle.setUI(modes);
calibration.drawTarget();

14
apps/calibration/boot.js Normal file
View File

@ -0,0 +1,14 @@
let cal_settings = require('Storage').readJSON("calibration.json", true) || {active: false};
Bangle.on('touch', function(button, xy) {
// do nothing if the calibration is deactivated
if (cal_settings.active === false) return;
// reload the calibration offset at each touch event /!\ bad for the flash memory
if (cal_settings.reload === true) {
cal_settings = require('Storage').readJSON("calibration.json", true);
}
// apply the calibration offset
xy.x += cal_settings.xoffset;
xy.y += cal_settings.yoffset;
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

View File

@ -0,0 +1,17 @@
{ "id": "calibration",
"name": "Touchscreen Calibration",
"shortName":"Calibration",
"icon": "calibration.png",
"version":"1.00",
"description": "A simple calibration app for the touchscreen",
"supports": ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"tags": "tool",
"storage": [
{"name":"calibration.app.js","url":"app.js"},
{"name":"calibration.boot.js","url":"boot.js"},
{"name":"calibration.settings.js","url":"settings.js"},
{"name":"calibration.img","url":"app-icon.js","evaluate":true}
],
"data": [{"name":"calibration.json"}]
}

View File

@ -0,0 +1,23 @@
(function(back) {
var FILE = "calibration.json";
var settings = Object.assign({
active: true,
}, require('Storage').readJSON(FILE, true) || {});
function writeSettings() {
require('Storage').writeJSON(FILE, settings);
}
E.showMenu({
"" : { "title" : "Calibration" },
"< Back" : () => back(),
'Active': {
value: !!settings.active,
format: v => v? "On":"Off",
onchange: v => {
settings.active = v;
writeSettings();
}
},
});
})