Merge branch 'espruino:master' into master
35
apps.json
|
|
@ -2857,10 +2857,10 @@
|
||||||
"name": "Test User Input",
|
"name": "Test User Input",
|
||||||
"shortName":"Test User Input",
|
"shortName":"Test User Input",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.05",
|
"version":"0.06",
|
||||||
"description": "Basic app to test the bangle.js input interface. It displays the user action in text, an option round element or an on/off switch image for swipe movements.",
|
"description": "App to test the bangle.js input interface. It displays the user action in text, circle buttons or on/off switch UI elements.",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"tags": "input,interface,buttons,touch",
|
"tags": "input,interface,buttons,touch,UI",
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"testuserinput.app.js","url":"app.js"},
|
{"name":"testuserinput.app.js","url":"app.js"},
|
||||||
{"name":"testuserinput.img","url":"app-icon.js","evaluate":true}
|
{"name":"testuserinput.img","url":"app-icon.js","evaluate":true}
|
||||||
|
|
@ -3044,7 +3044,7 @@
|
||||||
"name": "Gadgetbridge Music Controls",
|
"name": "Gadgetbridge Music Controls",
|
||||||
"shortName":"Music Controls",
|
"shortName":"Music Controls",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"version":"0.03",
|
"version":"0.05",
|
||||||
"description": "Control the music on your Gadgetbridge-connected phone",
|
"description": "Control the music on your Gadgetbridge-connected phone",
|
||||||
"tags": "tools,bluetooth,gadgetbridge,music",
|
"tags": "tools,bluetooth,gadgetbridge,music",
|
||||||
"type":"app",
|
"type":"app",
|
||||||
|
|
@ -3085,8 +3085,8 @@
|
||||||
{ "id": "kitchen",
|
{ "id": "kitchen",
|
||||||
"name": "Kitchen Combo",
|
"name": "Kitchen Combo",
|
||||||
"icon": "kitchen.png",
|
"icon": "kitchen.png",
|
||||||
"version":"0.06",
|
"version":"0.10",
|
||||||
"description": "Combination of the stepo, walkersclock, arrow and waypointer apps into a multiclock format. 'Everything but the kitchen sink'. Requires firmware v2.08.167 or later",
|
"description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'. Requires firmware v2.08.167 or later",
|
||||||
"tags": "tool,outdoors,gps",
|
"tags": "tool,outdoors,gps",
|
||||||
"type":"clock",
|
"type":"clock",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
|
@ -3096,10 +3096,13 @@
|
||||||
{"name":"stepo.kit.js","url":"stepo.kit.js"},
|
{"name":"stepo.kit.js","url":"stepo.kit.js"},
|
||||||
{"name":"gps.kit.js","url":"gps.kit.js"},
|
{"name":"gps.kit.js","url":"gps.kit.js"},
|
||||||
{"name":"digi.kit.js","url":"digi.kit.js"},
|
{"name":"digi.kit.js","url":"digi.kit.js"},
|
||||||
|
{"name":"heart.kit.js","url":"heart.kit.js"},
|
||||||
{"name":"swatch.kit.js","url":"swatch.kit.js"},
|
{"name":"swatch.kit.js","url":"swatch.kit.js"},
|
||||||
{"name":"compass.kit.js","url":"compass.kit.js"},
|
{"name":"compass.kit.js","url":"compass.kit.js"},
|
||||||
{"name":"waypoints.json","url":"waypoints.json","evaluate":false},
|
|
||||||
{"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true}
|
{"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"waypoints.json","url":"waypoints.json"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{ "id": "qmsched",
|
{ "id": "qmsched",
|
||||||
|
|
@ -3152,7 +3155,7 @@
|
||||||
"id": "omnitrix",
|
"id": "omnitrix",
|
||||||
"name":"Omnitrix",
|
"name":"Omnitrix",
|
||||||
"icon":"omnitrix.png",
|
"icon":"omnitrix.png",
|
||||||
"version": "1.0",
|
"version": "0.01",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"description": "An Omnitrix Showpiece",
|
"description": "An Omnitrix Showpiece",
|
||||||
"tags": "game",
|
"tags": "game",
|
||||||
|
|
@ -3166,7 +3169,7 @@
|
||||||
"name": "Bat Clock",
|
"name": "Bat Clock",
|
||||||
"shortName":"Bat Clock",
|
"shortName":"Bat Clock",
|
||||||
"icon": "bat-clock.png",
|
"icon": "bat-clock.png",
|
||||||
"version":"1.0",
|
"version":"0.01",
|
||||||
"description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.",
|
"description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.",
|
||||||
"tags": "clock",
|
"tags": "clock",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
|
|
@ -3175,5 +3178,19 @@
|
||||||
{"name":"batclock.app.js","url":"bat-clock.app.js"},
|
{"name":"batclock.app.js","url":"bat-clock.app.js"},
|
||||||
{"name":"batclock.img","url":"bat-clock.icon.js","evaluate":true}
|
{"name":"batclock.img","url":"bat-clock.icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{ "id":"doztime",
|
||||||
|
"name":"Dozenal Time",
|
||||||
|
"shortName":"Dozenal Time",
|
||||||
|
"icon":"app.png",
|
||||||
|
"version":"0.01",
|
||||||
|
"description":"A dozenal Holocene calendar and dozenal diurnal clock",
|
||||||
|
"tags":"clock",
|
||||||
|
"type":"clock",
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"doztime.app.js","url":"app.js"},
|
||||||
|
{"name":"doztime.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New App!
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
Dozenal Time
|
||||||
|
============
|
||||||
|
|
||||||
|
A dozenal Holocene calendar and a dozenal diurnal clock. For information about them, go to https://dozenal.ae-web.ca/pdf/dozenal-calendar.pdf and https://dozenal.ae-web.ca/pdf/about-short.pdf. They've been in use for some years.
|
||||||
|
|
||||||
|
In the dozenal number base, ten and eleven are single digits, and 10 is a dozen. The clock simply divides the day by successive powers of a dozen. The day or parts of it may be divided easily into halves, thirds, quarters, sixths, or twelfths (dozenths). There is no conglomeration of bases two, ten, twelve, and sixty, as in the current system of time measurement.
|
||||||
|
|
||||||
|
The annual calendar has a dozen months of 5 weeks each, each week having 6 days. The 5 or 6 days beyond 360 (dozenal 260) are added where they keep the season beginnings the most accurate.
|
||||||
|
|
||||||
|
The year itself begins on the December solstice. Because that always happens, there is no need of a leap-year rule to keep the seasons from drifting.
|
||||||
|
|
||||||
|
The epoch (year numbering) begins in the last year when the perihelion coincided with the June solstice, near the beginning of the Holocene era. That astronomical basis makes the calendar free from politics, religion, or geography.
|
||||||
|
|
||||||
|
While the year number remains cardinal, BTN5 toggles between cardinal and ordinal for the rest of the calendar segments. BTN4 adds or removes a quickly changing digit to or from the clock.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("lEowggdkUiCKIADCJcCkUjmYACmUikAlKB4ImDAoQSJkYhBFAQECAQI5HBQU//4AC+YUCHowzBCQfzAYYKCEw8vEgYqD+QoGgQbBHAYADCwIoBCYkiEwhPEBAIoBHgY6BExHyHwQhBFAQ6BkYTHDgcyHgcCHRZlDCYQsBTYg6GDAJQDPoI6LAAIPBCYRiHHQhkDCYRiHHQhkCCYKKBCYzzBA4yMBCYTVEGYITEBYITZHY5PHUAJjITIJjHRZINBIYoTDWZAoFWYbbJFALbHgUyX4oPDXIcjMQITBmZkHFYszCYZkJMQoTCKAQ8IHQZOCHgYoKkQ6DHgYoEcIgmBHQg8CFAIPCCYfzBQQSEFAbrFCQImHFAQUCkczmYECAQISGHoYzBAAQFCCRA9BEwYoDHI4pFAAgRLCooRPABg="))
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
// Positioning values for graphics buffers
|
||||||
|
const g_height = 80; // total graphics height
|
||||||
|
const g_x_off = 16; // position from left
|
||||||
|
const g_y_off = (240 - g_height)/2; // vertical center for graphics region
|
||||||
|
const g_width = 240 - 2 * g_x_off; // total graphics width
|
||||||
|
const g_height_d = 32; // height of date region
|
||||||
|
const g_y_off_d = 0; // y position of date region within graphics region
|
||||||
|
const spacing = 0; // space between date and time in graphics region
|
||||||
|
const g_y_off_t = g_y_off_d + g_height_d + spacing; // y position of time within graphics region
|
||||||
|
const g_height_t = 48; // height of time region
|
||||||
|
|
||||||
|
// Other vars
|
||||||
|
const A1 = [30,30,30,30,31,31,31,31,31,31,30,30];
|
||||||
|
const B1 = [30,30,30,30,30,31,31,31,31,31,30,30];
|
||||||
|
const B2 = [30,30,30,30,31,31,31,31,31,30,30,30];
|
||||||
|
const timeColour = "#f2f2f2";
|
||||||
|
const dateColours = ["#ff0000","#ffa500","#ffff00","#00b800","#0000ff","#ff00ff","#ff0080"];
|
||||||
|
const calen10 = {"size":32,"pt0":[32-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for usual calendar line
|
||||||
|
const calen7 = {"size":32,"pt0":[62-g_x_off,16],"step":[20,0],"dx":-4.5,"dy":-4.5}; // positioning for S-day calendar line
|
||||||
|
const time5 = {"size":48,"pt0":[64-g_x_off,24],"step":[30,0],"dx":-6.5,"dy":-6.5}; // positioning for lull time line; was 64
|
||||||
|
const time6 = {"size":48,"pt0":[48-g_x_off,24],"step":[30,0],"dx":-6.5,"dy":-6.5}; // positioning for twinkling time line
|
||||||
|
const baseYear = 11584;
|
||||||
|
const baseDate = Date(2020,11,21); // month values run from 0 to 11
|
||||||
|
let accum = new Date(baseDate.getTime());
|
||||||
|
let sequence = [];
|
||||||
|
let timeActiveUntil;
|
||||||
|
let addTimeDigit = false;
|
||||||
|
let dateFormat = false;
|
||||||
|
let lastX = 999999999;
|
||||||
|
let res = {};
|
||||||
|
//var last_time_log = 0;
|
||||||
|
|
||||||
|
// Date and time graphics buffers
|
||||||
|
var dateColour = "#ffffff"; // override later
|
||||||
|
var g_d = Graphics.createArrayBuffer(g_width,g_height_d,1,{'msb':true});
|
||||||
|
var g_t = Graphics.createArrayBuffer(g_width,g_height_t,1,{'msb':true});
|
||||||
|
// Set screen mode and function to write graphics buffers
|
||||||
|
Bangle.setLCDMode();
|
||||||
|
g.clear(); // start with blank screen
|
||||||
|
g.flip = function()
|
||||||
|
{
|
||||||
|
g.setColor(dateColour);
|
||||||
|
g.drawImage(
|
||||||
|
{
|
||||||
|
width:g_width,
|
||||||
|
height:g_height_d,
|
||||||
|
buffer:g_d.buffer
|
||||||
|
}, g_x_off, g_y_off + g_y_off_d);
|
||||||
|
g.setColor(timeColour);
|
||||||
|
g.drawImage(
|
||||||
|
{
|
||||||
|
width:g_width,
|
||||||
|
height:g_height_t,
|
||||||
|
buffer:g_t.buffer
|
||||||
|
}, g_x_off, g_y_off + g_y_off_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
setWatch(function(){ modeTime(); }, BTN1, {repeat:true} );
|
||||||
|
setWatch(function(){ Bangle.showLauncher(); }, BTN2, { repeat: false, edge: "falling" });
|
||||||
|
setWatch(function(){ modeWeather(); }, BTN3, {repeat:true});
|
||||||
|
setWatch(function(){ toggleTimeDigits(); }, BTN4, {repeat:true});
|
||||||
|
setWatch(function(){ toggleDateFormat(); }, BTN5, {repeat:true});
|
||||||
|
|
||||||
|
function buildSequence(targ){
|
||||||
|
for(let i=0;i<targ.length;++i){
|
||||||
|
sequence.push(new Date(accum.getTime()));
|
||||||
|
accum.setDate(accum.getDate()+targ[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(A1);
|
||||||
|
buildSequence(B1);
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(A1);
|
||||||
|
buildSequence(B1);
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(B2);
|
||||||
|
buildSequence(A1);
|
||||||
|
buildSequence(B1);
|
||||||
|
buildSequence(B2);
|
||||||
|
|
||||||
|
function getDate(dt){
|
||||||
|
let index = sequence.findIndex(n => n > dt)-1;
|
||||||
|
let year = baseYear+parseInt(index/12);
|
||||||
|
let month = index % 12;
|
||||||
|
let day = parseInt((dt-sequence[index])/86400000);
|
||||||
|
let colour = dateColours[day % 6];
|
||||||
|
if(day==30){ colour=dateColours[6]; }
|
||||||
|
return({"year":year,"month":month,"day":day,"colour":colour});
|
||||||
|
}
|
||||||
|
function toggleTimeDigits(){
|
||||||
|
addTimeDigit = !addTimeDigit;
|
||||||
|
modeTime();
|
||||||
|
}
|
||||||
|
function toggleDateFormat(){
|
||||||
|
dateFormat = !dateFormat;
|
||||||
|
modeTime();
|
||||||
|
}
|
||||||
|
function formatDate(res,dateFormat){
|
||||||
|
let yyyy = res.year.toString(12);
|
||||||
|
calenDef = calen10;
|
||||||
|
if(!dateFormat){ //ordinal format
|
||||||
|
let mm = ("0"+(res.month+1).toString(12)).substr(-2);
|
||||||
|
let dd = ("0"+(res.day+1).toString(12)).substr(-2);
|
||||||
|
if(res.day==30){
|
||||||
|
calenDef = calen7;
|
||||||
|
let m = ((res.month+1).toString(12)).substr(-2);
|
||||||
|
return(yyyy+"-"+"S"+m); // ordinal format
|
||||||
|
}
|
||||||
|
return(yyyy+"-"+mm+"-"+dd);
|
||||||
|
}
|
||||||
|
let m = res.month.toString(12); // cardinal format
|
||||||
|
let w = parseInt(res.day/6);
|
||||||
|
let d = res.day%6;
|
||||||
|
//return(yyyy+"-"+res.month+"-"+w+"-"+d);
|
||||||
|
return(yyyy+"-"+m+"-"+w+"-"+d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeDozTime(text,def,colour){
|
||||||
|
let pts = def.pts;
|
||||||
|
let x=def.pt0[0];
|
||||||
|
let y=def.pt0[1];
|
||||||
|
g_t.clear();
|
||||||
|
g_t.setFont("Vector",def.size);
|
||||||
|
for(let i in text){
|
||||||
|
if(text[i]=="a"){ g_t.setFontAlign(0,0,2); g_t.drawString("2",x+def.dx,y+def.dy); }
|
||||||
|
else if(text[i]=="b"){ g_t.setFontAlign(0,0,2); g_t.drawString("3",x+def.dx,y+def.dy); }
|
||||||
|
else{ g_t.setFontAlign(0,0,0); g_t.drawString(text[i],x,y); }
|
||||||
|
x = x+def.step[0];
|
||||||
|
y = y+def.step[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function writeDozDate(text,def,colour){
|
||||||
|
dateColour = colour;
|
||||||
|
let pts = def.pts;
|
||||||
|
let x=def.pt0[0];
|
||||||
|
let y=def.pt0[1];
|
||||||
|
g_d.clear();
|
||||||
|
g_d.setFont("Vector",def.size);
|
||||||
|
for(let i in text){
|
||||||
|
if(text[i]=="a"){ g_d.setFontAlign(0,0,2); g_d.drawString("2",x+def.dx,y+def.dy); }
|
||||||
|
else if(text[i]=="b"){ g_d.setFontAlign(0,0,2); g_d.drawString("3",x+def.dx,y+def.dy); }
|
||||||
|
else{ g_d.setFontAlign(0,0,0); g_d.drawString(text[i],x,y); }
|
||||||
|
x = x+def.step[0];
|
||||||
|
y = y+def.step[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions for time mode
|
||||||
|
function drawTime()
|
||||||
|
{
|
||||||
|
let dt = new Date();
|
||||||
|
let date = "";
|
||||||
|
let timeDef;
|
||||||
|
let x = 0;
|
||||||
|
dt.setDate(dt.getDate());
|
||||||
|
if(addTimeDigit){
|
||||||
|
x =
|
||||||
|
10368*dt.getHours()+172.8*dt.getMinutes()+2.88*dt.getSeconds()+0.00288*dt.getMilliseconds();
|
||||||
|
let msg = "00000"+Math.floor(x).toString(12);
|
||||||
|
let time = msg.substr(-5,3)+"."+msg.substr(-2);
|
||||||
|
let wait = 347*(1-(x%1));
|
||||||
|
timeDef = time6;
|
||||||
|
} else {
|
||||||
|
x =
|
||||||
|
864*dt.getHours()+14.4*dt.getMinutes()+0.24*dt.getSeconds()+0.00024*dt.getMilliseconds();
|
||||||
|
let msg = "0000"+Math.floor(x).toString(12);
|
||||||
|
let time = msg.substr(-4,3)+"."+msg.substr(-1);
|
||||||
|
let wait = 4167*(1-(x%1));
|
||||||
|
timeDef = time5;
|
||||||
|
}
|
||||||
|
if(lastX > x){ res = getDate(dt); } // calculate date once at start-up and once when turning over to a new day
|
||||||
|
date = formatDate(res,dateFormat);
|
||||||
|
if(dt<timeActiveUntil)
|
||||||
|
{
|
||||||
|
// Write to background buffers, then display on screen
|
||||||
|
writeDozDate(date,calenDef,res.colour);
|
||||||
|
writeDozTime(time,timeDef,timeColour);
|
||||||
|
g.flip();
|
||||||
|
// Ready next interval
|
||||||
|
setTimeout(drawTime,wait);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear screen
|
||||||
|
g_d.clear();
|
||||||
|
g_t.clear();
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
lastX = x;
|
||||||
|
}
|
||||||
|
function modeTime()
|
||||||
|
{
|
||||||
|
timeActiveUntil = new Date();
|
||||||
|
timeActiveUntil.setDate(timeActiveUntil.getDate());
|
||||||
|
timeActiveUntil.setSeconds(timeActiveUntil.getSeconds()+15);
|
||||||
|
//Bangle.setLCDPower(true);
|
||||||
|
clearTimeout();
|
||||||
|
drawTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time-logging function
|
||||||
|
/*function logTime(label)
|
||||||
|
{
|
||||||
|
var d = new Date();
|
||||||
|
var t = d.getTime();
|
||||||
|
var diff_test = t - last_time_log;
|
||||||
|
last_time_log = t;
|
||||||
|
console.log(label + " at time: " + t + ", since last: " + diff_test);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Functions for weather mode - TODO
|
||||||
|
function drawWeather() {}
|
||||||
|
function modeWeather() {}
|
||||||
|
|
||||||
|
// Start time on twist
|
||||||
|
Bangle.on('twist', function() {
|
||||||
|
modeTime();
|
||||||
|
});
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,3 +1,5 @@
|
||||||
0.01: Initial version
|
0.01: Initial version
|
||||||
0.02: Increase text brightness, improve controls, (try to) reduce memory usage
|
0.02: Increase text brightness, improve controls, (try to) reduce memory usage
|
||||||
0.03: Only auto-start if active app is a clock, auto close after 1 hour of inactivity
|
0.03: Only auto-start if active app is a clock, auto close after 1 hour of inactivity
|
||||||
|
0.04: Setting to disable touch controls, minor bugfix
|
||||||
|
0.05: Setting to disable double/triple press control, remove touch controls setting, reduce fadeout flicker
|
||||||
|
|
@ -16,10 +16,16 @@ Download the [latest Gadgetbridge for Android here](https://f-droid.org/packages
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
The app can automatically load when you play music and close when the music stops.
|
You can change these under `Settings`->`App/Widget Settings`->`Music Controls`.
|
||||||
You can change this under `Settings`->`App/Widget Settings`->`Music Controls`.
|
|
||||||
|
**Auto start**:
|
||||||
|
Automatically load the app when you play music and close when the music stops.
|
||||||
(If the app opened automatically, it closes after music has been paused for 5 minutes.)
|
(If the app opened automatically, it closes after music has been paused for 5 minutes.)
|
||||||
|
|
||||||
|
**Simple button**:
|
||||||
|
Disable double/triple pressing Button 2: always simply toggle play/pause.
|
||||||
|
(For music players which handle multiple button presses themselves.)
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
|
||||||
### Buttons
|
### Buttons
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ function fadeOut() {
|
||||||
if (!Bangle.isLCDOn() || !fade) {
|
if (!Bangle.isLCDOn() || !fade) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
drawMusic();
|
drawMusic(false); // don't clear: draw over existing text to prevent flicker
|
||||||
setTimeout(fadeOut, 500);
|
setTimeout(fadeOut, 500);
|
||||||
}
|
}
|
||||||
function brightness() {
|
function brightness() {
|
||||||
|
|
@ -127,7 +127,7 @@ function f2hex(f) {
|
||||||
return ("00"+(Math.round(f*255)).toString(16)).substr(-2);
|
return ("00"+(Math.round(f*255)).toString(16)).substr(-2);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param name
|
* @param {string} name - musicinfo property "num"/"artist"/"album"/"track"
|
||||||
* @return {string} Semi-random color to use for given info
|
* @return {string} Semi-random color to use for given info
|
||||||
*/
|
*/
|
||||||
function infoColor(name) {
|
function infoColor(name) {
|
||||||
|
|
@ -138,16 +138,13 @@ function infoColor(name) {
|
||||||
s = 0;
|
s = 0;
|
||||||
} else {
|
} else {
|
||||||
// make color depend deterministically on info
|
// make color depend deterministically on info
|
||||||
let code = 0;
|
let code = textCode(info[name]);
|
||||||
switch(name) {
|
switch(name) {
|
||||||
case "track":
|
case "track": // also use album
|
||||||
code += textCode(info.track);
|
|
||||||
// fallthrough: also use album+artist
|
|
||||||
case "album":
|
|
||||||
code += textCode(info.album);
|
code += textCode(info.album);
|
||||||
// fallthrough: also use artist
|
// fallthrough
|
||||||
default:
|
case "album": // also use artist
|
||||||
code += textCode(info[name]);
|
code += textCode(info.artist);
|
||||||
}
|
}
|
||||||
h = code%360;
|
h = code%360;
|
||||||
s = 0.7;
|
s = 0.7;
|
||||||
|
|
@ -173,7 +170,6 @@ function trackColor() {
|
||||||
////////////////////
|
////////////////////
|
||||||
/**
|
/**
|
||||||
* Draw date and time
|
* Draw date and time
|
||||||
* @return {*}
|
|
||||||
*/
|
*/
|
||||||
function drawDateTime() {
|
function drawDateTime() {
|
||||||
const now = new Date;
|
const now = new Date;
|
||||||
|
|
@ -208,8 +204,9 @@ function drawDateTime() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw track number and total count
|
* Draw track number and total count
|
||||||
|
* @param {boolean} clr - Clear area before redrawing?
|
||||||
*/
|
*/
|
||||||
function drawNum() {
|
function drawNum(clr) {
|
||||||
let num = "";
|
let num = "";
|
||||||
if ("n" in info && info.n>0) {
|
if ("n" in info && info.n>0) {
|
||||||
num = "#"+info.n;
|
num = "#"+info.n;
|
||||||
|
|
@ -219,9 +216,11 @@ function drawNum() {
|
||||||
}
|
}
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setFont("Vector", 30)
|
g.setFont("Vector", 30)
|
||||||
.setFontAlign(1, -1) // top right
|
.setFontAlign(1, -1); // top right
|
||||||
.clearRect(225, 30, 120, 60)
|
if (clr) {
|
||||||
.drawString(num, 225, 30);
|
g.clearRect(225, 30, 120, 60);
|
||||||
|
}
|
||||||
|
g.drawString(num, 225, 30);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Clear rectangle used by track title
|
* Clear rectangle used by track title
|
||||||
|
|
@ -231,8 +230,9 @@ function clearTrack() {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Draw track title
|
* Draw track title
|
||||||
|
* @param {boolean} clr - Clear area before redrawing?
|
||||||
*/
|
*/
|
||||||
function drawTrack() {
|
function drawTrack(clr) {
|
||||||
let size = fitText(info.track);
|
let size = fitText(info.track);
|
||||||
if (size<25) {
|
if (size<25) {
|
||||||
// the title is too long: start the scroller
|
// the title is too long: start the scroller
|
||||||
|
|
@ -249,7 +249,9 @@ function drawTrack() {
|
||||||
g.setFont("Vector", size)
|
g.setFont("Vector", size)
|
||||||
.setFontAlign(0, 1) // center bottom
|
.setFontAlign(0, 1) // center bottom
|
||||||
.setColor(trackColor());
|
.setColor(trackColor());
|
||||||
clearTrack();
|
if (clr) {
|
||||||
|
clearTrack();
|
||||||
|
}
|
||||||
g.drawString(info.track, 119, 109);
|
g.drawString(info.track, 119, 109);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
@ -269,8 +271,9 @@ function drawScroller() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw track artist and album
|
* Draw track artist and album
|
||||||
|
* @param {boolean} clr - Clear area before redrawing?
|
||||||
*/
|
*/
|
||||||
function drawArtistAlbum() {
|
function drawArtistAlbum(clr) {
|
||||||
// we just use small enough fonts to make these always fit
|
// we just use small enough fonts to make these always fit
|
||||||
// calculate stuff before clear+redraw
|
// calculate stuff before clear+redraw
|
||||||
const aCol = infoColor("artist");
|
const aCol = infoColor("artist");
|
||||||
|
|
@ -284,7 +287,9 @@ function drawArtistAlbum() {
|
||||||
bSiz = 20;
|
bSiz = 20;
|
||||||
}
|
}
|
||||||
g.reset();
|
g.reset();
|
||||||
g.clearRect(0, 120, 240, 189);
|
if (clr) {
|
||||||
|
g.clearRect(0, 120, 240, 189);
|
||||||
|
}
|
||||||
let top = 124;
|
let top = 124;
|
||||||
if (info.artist) {
|
if (info.artist) {
|
||||||
g.setFont("Vector", aSiz)
|
g.setFont("Vector", aSiz)
|
||||||
|
|
@ -377,10 +382,14 @@ function drawControls() {
|
||||||
controlState = stat;
|
controlState = stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawMusic() {
|
/**
|
||||||
drawNum();
|
* @param {boolean} [clr=true] Clear area before redrawing?
|
||||||
drawTrack();
|
*/
|
||||||
drawArtistAlbum();
|
function drawMusic(clr) {
|
||||||
|
clr = !(clr===false); // undefined means yes
|
||||||
|
drawNum(clr);
|
||||||
|
drawTrack(clr);
|
||||||
|
drawArtistAlbum(clr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
|
|
@ -388,7 +397,7 @@ function drawMusic() {
|
||||||
///////////////////////
|
///////////////////////
|
||||||
/**
|
/**
|
||||||
* Update music info
|
* Update music info
|
||||||
* @param e
|
* @param {Object} e - Gadgetbridge musicinfo event
|
||||||
*/
|
*/
|
||||||
function musicInfo(e) {
|
function musicInfo(e) {
|
||||||
info = e;
|
info = e;
|
||||||
|
|
@ -408,7 +417,11 @@ function musicInfo(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tPxt, tIxt;
|
let tPxt, tIxt; // Timeouts to eXiT when Paused/Inactive for too long
|
||||||
|
/**
|
||||||
|
* Update music state
|
||||||
|
* @param {Object} e - Gadgetbridge musicstate event
|
||||||
|
*/
|
||||||
function musicState(e) {
|
function musicState(e) {
|
||||||
stat = e.state;
|
stat = e.state;
|
||||||
// if paused for five minutes, load the clock
|
// if paused for five minutes, load the clock
|
||||||
|
|
@ -444,6 +457,7 @@ function musicState(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Bangle.isLCDOn()) {
|
if (Bangle.isLCDOn()) {
|
||||||
|
drawMusic(false); // redraw in case we were fading out but resumed play
|
||||||
drawControls();
|
drawControls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -471,11 +485,19 @@ function startButtonWatches() {
|
||||||
tPress = setTimeout(() => {Bangle.showLauncher();}, 3000);
|
tPress = setTimeout(() => {Bangle.showLauncher();}, 3000);
|
||||||
}
|
}
|
||||||
}, BTN2, {repeat: true, edge: "rising"});
|
}, BTN2, {repeat: true, edge: "rising"});
|
||||||
setWatch(() => {
|
const s = require("Storage").readJSON("gbmusic.json", 1) || {};
|
||||||
nPress++;
|
if (s.simpleButton) {
|
||||||
clearTimeout(tPress);
|
setWatch(() => {
|
||||||
tPress = setTimeout(handleButton2Press, 500);
|
clearTimeout(tPress);
|
||||||
}, BTN2, {repeat: true, edge: "falling"});
|
togglePlay();
|
||||||
|
}, BTN2, {repeat: true, edge: "falling"});
|
||||||
|
} else {
|
||||||
|
setWatch(() => {
|
||||||
|
nPress++;
|
||||||
|
clearTimeout(tPress);
|
||||||
|
tPress = setTimeout(handleButton2Press, 500);
|
||||||
|
}, BTN2, {repeat: true, edge: "falling"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function handleButton2Press() {
|
function handleButton2Press() {
|
||||||
tPress = null;
|
tPress = null;
|
||||||
|
|
@ -498,7 +520,7 @@ function handleButton2Press() {
|
||||||
let tCommand = {};
|
let tCommand = {};
|
||||||
/**
|
/**
|
||||||
* Send command and highlight corresponding control
|
* Send command and highlight corresponding control
|
||||||
* @param command "play/pause/next/previous/volumeup/volumedown"
|
* @param {string} command - "play"/"pause"/"next"/"previous"/"volumeup"/"volumedown"
|
||||||
*/
|
*/
|
||||||
function sendCommand(command) {
|
function sendCommand(command) {
|
||||||
Bluetooth.println(JSON.stringify({t: "music", n: command}));
|
Bluetooth.println(JSON.stringify({t: "music", n: command}));
|
||||||
|
|
@ -519,6 +541,7 @@ function togglePlay() {
|
||||||
}
|
}
|
||||||
function startTouchWatches() {
|
function startTouchWatches() {
|
||||||
Bangle.on("touch", side => {
|
Bangle.on("touch", side => {
|
||||||
|
if (!Bangle.isLCDOn()) {return;} // for <2v10 firmware
|
||||||
switch(side) {
|
switch(side) {
|
||||||
case 1:
|
case 1:
|
||||||
sendCommand(stat==="play" ? "pause" : "previous");
|
sendCommand(stat==="play" ? "pause" : "previous");
|
||||||
|
|
@ -531,6 +554,7 @@ function startTouchWatches() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Bangle.on("swipe", dir => {
|
Bangle.on("swipe", dir => {
|
||||||
|
if (!Bangle.isLCDOn()) {return;} // for <2v10 firmware
|
||||||
sendCommand(dir===1 ? "previous" : "next");
|
sendCommand(dir===1 ? "previous" : "next");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,35 +4,42 @@
|
||||||
(function(back) {
|
(function(back) {
|
||||||
const SETTINGS_FILE = "gbmusic.json",
|
const SETTINGS_FILE = "gbmusic.json",
|
||||||
storage = require("Storage"),
|
storage = require("Storage"),
|
||||||
translate = require("locale").translate
|
translate = require("locale").translate;
|
||||||
|
|
||||||
// initialize with default settings...
|
// initialize with default settings...
|
||||||
let s = {
|
let s = {
|
||||||
autoStart: true,
|
autoStart: true,
|
||||||
}
|
simpleButton: false,
|
||||||
|
};
|
||||||
// ...and overwrite them with any saved values
|
// ...and overwrite them with any saved values
|
||||||
// This way saved values are preserved if a new version adds more settings
|
// This way saved values are preserved if a new version adds more settings
|
||||||
const saved = storage.readJSON(SETTINGS_FILE, 1) || {}
|
const saved = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||||
for(const key in saved) {
|
for(const key in saved) {
|
||||||
s[key] = saved[key]
|
s[key] = saved[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a function to safe a specific setting, e.g. save('autoStart')(true)
|
|
||||||
function save(key) {
|
function save(key) {
|
||||||
return function(value) {
|
return function (value) {
|
||||||
s[key] = value
|
s[key] = value;
|
||||||
storage.write(SETTINGS_FILE, s)
|
storage.write(SETTINGS_FILE, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const menu = {
|
const yesNo = (v) => translate(v ? "Yes" : "No");
|
||||||
|
let menu = {
|
||||||
"": {"title": "Music Control"},
|
"": {"title": "Music Control"},
|
||||||
"< Back": back,
|
};
|
||||||
"Auto start": {
|
menu[translate("< Back")] = back;
|
||||||
value: s.autoStart,
|
menu[translate("Auto start")] = {
|
||||||
format: v => translate(v ? "Yes" : "No"),
|
value: !!s.autoStart,
|
||||||
onchange: save("autoStart"),
|
format: yesNo,
|
||||||
}
|
onchange: save("autoStart"),
|
||||||
}
|
};
|
||||||
E.showMenu(menu)
|
menu[translate("Simple button")] = {
|
||||||
})
|
value: !!s.simpleButton,
|
||||||
|
format: yesNo,
|
||||||
|
onchange: save("simpleButton"),
|
||||||
|
};
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,7 @@
|
||||||
0.04: Added stopwatch face
|
0.04: Added stopwatch face
|
||||||
0.05: Stopwatch, hide hours if 0, fixed flicker when stopped, updated README issues
|
0.05: Stopwatch, hide hours if 0, fixed flicker when stopped, updated README issues
|
||||||
0.06: Reduced memory footprint of compass, used direct screen access rather than arrayBuffer
|
0.06: Reduced memory footprint of compass, used direct screen access rather than arrayBuffer
|
||||||
|
0.07: Added error codes if dependancies are missing
|
||||||
|
0.08: Improved error handling for missing firmware features, added template app.kit.js
|
||||||
|
0.09: Added heart rate monitor app
|
||||||
|
0.10: Converted Stepo to use direct screen writes, added a Trip Counter feature to stepo
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
# Kitchen Combo - a multiclock format of the waypointer, walksersclock, stepo and arrow apps.
|
# Kitchen Combo - a multiclock format of the waypointer, walkersclock, stepo, stopwatch, heartrate and arrow apps.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
*...everything but the kitchen sink..*
|
*...everything but the kitchen sink..*
|
||||||
|
|
||||||
NOTE: This app require Bangle firmware 2.08.187 or later.
|
NOTE: This app requires Bangle firmware 2.08.187 or later.
|
||||||
|
|
||||||
The app is aimed at navigation whilst walking. Please note that it
|
The app is aimed at navigation whilst walking. Please note that it
|
||||||
would be foolish in the extreme to rely on this as your only
|
would be foolish in the extreme to rely on this as your only
|
||||||
|
|
@ -44,13 +44,16 @@ The following buttons depend on which face is currently in use
|
||||||
## Stepo
|
## Stepo
|
||||||

|

|
||||||
|
|
||||||
|
- Requires one of the pedominter widgets to be installed
|
||||||
- Displays the time in large font
|
- Displays the time in large font
|
||||||
- Display current step count in a doughnut gauge
|
- Display current step count in a doughnut gauge
|
||||||
- Show step count in the middle of the doughnut gauge
|
- Show step count in the middle of the doughnut gauge
|
||||||
- The gauge show percentage of steps out of a goal of 10000 steps
|
- The gauge show percentage of steps out of a goal of 10000 steps
|
||||||
- When the battery is less than 25% the doughnut turns red
|
- When the battery is less than 25% the doughnut turns red
|
||||||
|
- Use BTN1 to switch to the Trip Counter, use long press to reset Trip Counter
|
||||||
- Use BTN3 to switch to the next app
|
- Use BTN3 to switch to the next app
|
||||||
|
|
||||||
|
|
||||||
## GPS
|
## GPS
|
||||||

|

|
||||||
- Use BTN1 long press to switch the GPS on or off
|
- Use BTN1 long press to switch the GPS on or off
|
||||||
|
|
@ -65,10 +68,16 @@ The following buttons depend on which face is currently in use
|
||||||
- Use BTN3 to switch to the next app.
|
- Use BTN3 to switch to the next app.
|
||||||
|
|
||||||
## Swatch
|
## Swatch
|
||||||
|

|
||||||
- A simple stopwatch
|
- A simple stopwatch
|
||||||
- BTN1 - start, stop
|
- BTN1 - start, stop
|
||||||
- BTN2 - lap if the timer is running, reset if the timer is stopped
|
- BTN2 - lap if the timer is running, reset if the timer is stopped
|
||||||
|
|
||||||
|
## Heart
|
||||||
|

|
||||||
|
- A simple heart rate monitor, at present the app is just showing the raw value from HRM.bpm
|
||||||
|
- BTN1, long press, turn heart rate monitor on / off
|
||||||
|
|
||||||
## Waypointer
|
## Waypointer
|
||||||
- Use BTN1 to select previous waypoint (when GPS is on)
|
- Use BTN1 to select previous waypoint (when GPS is on)
|
||||||
- Use BTN2 to select the next waypoint (when GPS is on)
|
- Use BTN2 to select the next waypoint (when GPS is on)
|
||||||
|
|
@ -217,12 +226,31 @@ I have settled on directly writing to the screen using the Graphics
|
||||||
object (g.) for the compass App. This creates a bit of flicker when
|
object (g.) for the compass App. This creates a bit of flicker when
|
||||||
the arrow moves but is more reliable than using the ArrayBuffer.
|
the arrow moves but is more reliable than using the ArrayBuffer.
|
||||||
|
|
||||||
|
v0.09: Since adding the heart rate monitor I have noticed that I can
|
||||||
|
sometimes can a memory error when switch through the Apps back to the
|
||||||
|
Stepo App. I think this can be cured by statically allocating the
|
||||||
|
ArrayBuffer for stepo rather than using new everytime you switch back
|
||||||
|
into the stepo watch face. The problem is that the bangle memory
|
||||||
|
management / defragmentation is quite slow to run.
|
||||||
|
|
||||||
### Issues
|
v0.10: Revisited having a display buffer for the stepo part of the App.
|
||||||
|
Now use direct screen writing as it means less memory allocation and
|
||||||
|
reduces chance of getting a memory error on switching watch faces.
|
||||||
|
|
||||||
|
### Error Codes
|
||||||
|
|
||||||
|
The following error codes will be displayed if one of the dependancies is not met.
|
||||||
|
|
||||||
|
* E-STEPS - no pedomintor widget has been installed, please install the widpedom or the activepedom widgets
|
||||||
|
* E-CALIB - no compass calibration data was found, see 'Compass Calibration'
|
||||||
|
* E-FW - require firmware 2v08.187 or later to detect gps and compass power status
|
||||||
|
|
||||||
|
### Issues / Future enhancements
|
||||||
|
|
||||||
* GPS time display shows GMT and not BST, needs localising
|
* GPS time display shows GMT and not BST, needs localising
|
||||||
* Occassional buzzing after 2-3 days of use, seems to disappear after
|
* Occassional buzzing after 2-3 days of use, seems to disappear after
|
||||||
a reset to the launcher menu. Needs investigation
|
a reset to the launcher menu. Needs investigation
|
||||||
* Need to gracefully handle incorrect firmware
|
* Automatically switch the GPS power setting from Super-E to PSMOO 10
|
||||||
* Need to gracefully handle missing compass calibration data
|
seconds after the LCD goes off. At present I just rely on using
|
||||||
* Need to gracefully handle missing steps widget
|
the GPSSetup app and set the GPS power mode that I want.
|
||||||
|
* Add a small graph to the heart rate monitor app
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
// simple template
|
||||||
|
(() => {
|
||||||
|
function getFace(){
|
||||||
|
var intervalRefSec;
|
||||||
|
var prevTime;
|
||||||
|
|
||||||
|
const Y_TIME = 30;
|
||||||
|
const Y_ACTIVITY = 116;
|
||||||
|
|
||||||
|
function init(gps,sw) {
|
||||||
|
prevTime = "";
|
||||||
|
g.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
function freeResources() {
|
||||||
|
prevTime = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTimer() {
|
||||||
|
draw();
|
||||||
|
intervalRefSec = setInterval(draw, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopTimer() {
|
||||||
|
if (intervalRefSec) { intervalRefSec = clearInterval(intervalRefSec); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function onButtonShort(btn) {}
|
||||||
|
function onButtonLong(btn) {}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
var d = new Date();
|
||||||
|
var da = d.toString().split(" ");
|
||||||
|
var time = da[4].substr(0,5);
|
||||||
|
|
||||||
|
if (time !== prevTime) {
|
||||||
|
prevTime = time;
|
||||||
|
g.setColor(0);
|
||||||
|
g.fillRect(0, Y_TIME, 239, Y_ACTIVITY -1);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.setFont("Vector",80);
|
||||||
|
g.setFontAlign(0,-1);
|
||||||
|
g.drawString(time, 120, Y_TIME);
|
||||||
|
|
||||||
|
g.setFont("Vector",26);
|
||||||
|
g.drawString("Hello World", 120, Y_ACTIVITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {init:init, freeResources:freeResources, startTimer:startTimer, stopTimer:stopTimer,
|
||||||
|
onButtonShort:onButtonShort, onButtonLong:onButtonLong};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFace;
|
||||||
|
})();
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
//console.log(o);
|
//console.log(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(gps,sw) {
|
function init(gps,sw, hrm) {
|
||||||
showMem("compass init() START");
|
showMem("compass init() START");
|
||||||
gpsObject = gps;
|
gpsObject = gps;
|
||||||
intervalRefSec = undefined;
|
intervalRefSec = undefined;
|
||||||
|
|
@ -49,13 +49,13 @@
|
||||||
loc = undefined;
|
loc = undefined;
|
||||||
CALIBDATA = undefined;
|
CALIBDATA = undefined;
|
||||||
wp = undefined;
|
wp = undefined;
|
||||||
if (Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
if (Bangle.isCompassOn !== undefined && Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
||||||
showMem("compass freeResources() END");
|
showMem("compass freeResources() END");
|
||||||
}
|
}
|
||||||
|
|
||||||
function startTimer() {
|
function startTimer() {
|
||||||
log_debug("startTimer()");
|
log_debug("startTimer()");
|
||||||
if (!Bangle.isCompassOn()) Bangle.setCompassPower(1);
|
if (Bangle.isCompassOn !== undefined && !Bangle.isCompassOn()) Bangle.setCompassPower(1);
|
||||||
resetPrevious();
|
resetPrevious();
|
||||||
draw();
|
draw();
|
||||||
intervalRefSec = setInterval(draw, 500);
|
intervalRefSec = setInterval(draw, 500);
|
||||||
|
|
@ -63,8 +63,8 @@
|
||||||
|
|
||||||
function stopTimer() {
|
function stopTimer() {
|
||||||
log_debug("stopTimer()");
|
log_debug("stopTimer()");
|
||||||
if(intervalRefSec) {intervalRefSec=clearInterval(intervalRefSec);}
|
if (intervalRefSec) {intervalRefSec=clearInterval(intervalRefSec);}
|
||||||
if (Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
if (Bangle.isCompassOn !== undefined && Bangle.isCompassOn()) Bangle.setCompassPower(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMem(msg) {
|
function showMem(msg) {
|
||||||
|
|
@ -175,7 +175,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
//log_debug("draw()");
|
log_debug("draw()");
|
||||||
|
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.setFont("Vector", 24);
|
||||||
|
|
||||||
|
if (Bangle.isCompassOn === undefined) {
|
||||||
|
g.drawString("E-FW", 120, 120);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CALIBDATA === undefined || CALIBDATA === null) {
|
||||||
|
g.drawString("E-CALIB", 120, 120);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var d = tiltfixread(CALIBDATA.offset,CALIBDATA.scale);
|
var d = tiltfixread(CALIBDATA.offset,CALIBDATA.scale);
|
||||||
heading = newHeading(d,heading);
|
heading = newHeading(d,heading);
|
||||||
// sets bearing to waypoint bearing if GPS on else sets to 0 (north)
|
// sets bearing to waypoint bearing if GPS on else sets to 0 (north)
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,12 @@
|
||||||
const INFO_NONE = 0;
|
const INFO_NONE = 0;
|
||||||
const INFO_BATT = 1;
|
const INFO_BATT = 1;
|
||||||
const INFO_MEM = 2;
|
const INFO_MEM = 2;
|
||||||
|
const INFO_FW = 3;
|
||||||
const Y_TIME = 30;
|
const Y_TIME = 30;
|
||||||
const Y_ACTIVITY = 116;
|
const Y_ACTIVITY = 116;
|
||||||
const Y_MODELINE = 200;
|
const Y_MODELINE = 200;
|
||||||
|
|
||||||
function init(gps,sw) {
|
function init(gps,sw,hrm) {
|
||||||
showMem("digi init 1");
|
showMem("digi init 1");
|
||||||
days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday"];
|
days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday"];
|
||||||
prevInfo = "";
|
prevInfo = "";
|
||||||
|
|
@ -98,6 +99,9 @@
|
||||||
infoMode = INFO_MEM
|
infoMode = INFO_MEM
|
||||||
break;
|
break;
|
||||||
case INFO_MEM:
|
case INFO_MEM:
|
||||||
|
infoMode = INFO_FW
|
||||||
|
break;
|
||||||
|
case INFO_FW:
|
||||||
default:
|
default:
|
||||||
infoMode = INFO_NONE;
|
infoMode = INFO_NONE;
|
||||||
break;
|
break;
|
||||||
|
|
@ -111,17 +115,21 @@
|
||||||
let col = 0x07FF; // cyan
|
let col = 0x07FF; // cyan
|
||||||
|
|
||||||
switch(infoMode) {
|
switch(infoMode) {
|
||||||
case INFO_NONE:
|
|
||||||
col = 0x0000;
|
|
||||||
str = "";
|
|
||||||
break;
|
|
||||||
case INFO_MEM:
|
case INFO_MEM:
|
||||||
val = process.memory();
|
val = process.memory();
|
||||||
str = "Memory: " + Math.round(val.usage*100/val.total) + "%";
|
str = "Memory: " + Math.round(val.usage*100/val.total) + "%";
|
||||||
break;
|
break;
|
||||||
case INFO_BATT:
|
case INFO_BATT:
|
||||||
default:
|
|
||||||
str = "Battery: " + E.getBattery() + "%";
|
str = "Battery: " + E.getBattery() + "%";
|
||||||
|
break;
|
||||||
|
case INFO_FW:
|
||||||
|
str = "Fw: " + process.env.VERSION;
|
||||||
|
break;
|
||||||
|
case INFO_NONE:
|
||||||
|
default:
|
||||||
|
col = 0x0000;
|
||||||
|
str = "";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we need to draw, avoid flicker
|
// check if we need to draw, avoid flicker
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
//console.log(o);
|
//console.log(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(gps, sw) {
|
function init(gps, sw, hrm) {
|
||||||
log_debug("gps init");
|
log_debug("gps init");
|
||||||
//log_debug(gps);
|
//log_debug(gps);
|
||||||
gpsObject = gps;
|
gpsObject = gps;
|
||||||
|
|
@ -79,6 +79,12 @@
|
||||||
g.setColor(0xFFC0);
|
g.setColor(0xFFC0);
|
||||||
g.setFontAlign(0, -1);
|
g.setFontAlign(0, -1);
|
||||||
|
|
||||||
|
if (Bangle.isGPSOn === undefined) {
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.drawString("E-FW", 120, Y_ACTIVITY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (gpsObject.getState() === gpsObject.GPS_OFF) {
|
if (gpsObject.getState() === gpsObject.GPS_OFF) {
|
||||||
g.drawString("GPS off", 120, Y_ACTIVITY);
|
g.drawString("GPS off", 120, Y_ACTIVITY);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
(() => {
|
||||||
|
function getFace(){
|
||||||
|
const Y_TIME = 30;
|
||||||
|
const Y_ACTIVITY = 116;
|
||||||
|
let prevTime;
|
||||||
|
let prevBpm;
|
||||||
|
let toggle = 1;
|
||||||
|
let redrawHrmPower = true;
|
||||||
|
let intervalRefSec;
|
||||||
|
let img;
|
||||||
|
let hrmObject;
|
||||||
|
|
||||||
|
function log_debug(o) {
|
||||||
|
//console.log(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(gps, sw, hrm) {
|
||||||
|
img = require("heatshrink").decompress(atob("mEwwRC/ABf/+ADBh//BQgGB//AgYDBCAQWCA4QPCDAYSC//8n4EC4AiEAAo1EBZIeDAAn8BZoKHJAYL7L64LLTa6/DAAi/CKhDjGBZBIGIwQ8IHQQ8IHQYwHBQgwFFwgwGFwgwGFwowFBQwwDFwwwEFwwwEFw4wDBRAkBERAkCERIA/AAYA="));
|
||||||
|
prevTime = "-";
|
||||||
|
prevBpm = "-";
|
||||||
|
toggle = 1;
|
||||||
|
redrawHrmPower = true;
|
||||||
|
hrmObject = hrm;
|
||||||
|
intervalRefSec;
|
||||||
|
g.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
function freeResources() {
|
||||||
|
prevTime = undefined;
|
||||||
|
img = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTimer() {
|
||||||
|
draw();
|
||||||
|
intervalRefSec = setInterval(draw, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopTimer() {
|
||||||
|
if (intervalRefSec) { intervalRefSec = clearInterval(intervalRefSec); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function onButtonShort(btn) {}
|
||||||
|
|
||||||
|
function onButtonLong(btn) {
|
||||||
|
log_debug("toggleHRM");
|
||||||
|
if (btn !== 1) return;
|
||||||
|
if (!Bangle.isHRMOn) return; // old firmware
|
||||||
|
hrmObject.toggleHRMPower();
|
||||||
|
prevBpm = '-';
|
||||||
|
toggle = 1; // ensure we draw the heart first
|
||||||
|
redrawHrmPower = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
let d = new Date();
|
||||||
|
let da = d.toString().split(" ");
|
||||||
|
let time = da[4].substr(0,5);
|
||||||
|
|
||||||
|
if (time !== prevTime) {
|
||||||
|
prevTime = time;
|
||||||
|
g.setColor(0);
|
||||||
|
g.fillRect(0, Y_TIME, 239, Y_ACTIVITY -1);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.setFont("Vector",80);
|
||||||
|
g.setFontAlign(0,-1);
|
||||||
|
g.drawString(time, 120, Y_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bpm = hrmObject.getBpm();
|
||||||
|
|
||||||
|
if (!Bangle.isHRMOn()) {
|
||||||
|
if (!redrawHrmPower) return;
|
||||||
|
redrawHrmPower = false;
|
||||||
|
g.setColor(0);
|
||||||
|
g.drawImage(img, 12, 132, {scale:2});
|
||||||
|
g.fillRect(120,120,239,239);
|
||||||
|
g.setColor(255,0,0);
|
||||||
|
//g.setColor(0xFFC0); // yellow
|
||||||
|
g.drawImage(img, 12, 132, {scale:2});
|
||||||
|
|
||||||
|
g.setFont("Vector",40);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
g.drawString("OFF", 180, 180);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the heart
|
||||||
|
if (++toggle % 2 === 0) {
|
||||||
|
g.setColor(0);
|
||||||
|
g.fillRect(12, 132, 108, 228);
|
||||||
|
} else {
|
||||||
|
g.setColor(255,0,0);
|
||||||
|
//g.setColor(0xFFC0); // yellow
|
||||||
|
g.drawImage(img, 12, 132, {scale:2});
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the bpm
|
||||||
|
if (bpm !== prevBpm) {
|
||||||
|
prevBpm = bpm;
|
||||||
|
g.setColor(0);
|
||||||
|
g.fillRect(120, 120, 239, 239);
|
||||||
|
g.setColor(1,1,1);
|
||||||
|
//g.setColor(0xFFC0); // yellow
|
||||||
|
g.setFont("Vector",52);
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.drawString(bpm, 180, 180);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {init:init, freeResources:freeResources, startTimer:startTimer, stopTimer:stopTimer,
|
||||||
|
onButtonShort:onButtonShort, onButtonLong:onButtonLong};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFace;
|
||||||
|
})();
|
||||||
|
|
@ -26,15 +26,17 @@ function nextFace(){
|
||||||
|
|
||||||
g.clear();
|
g.clear();
|
||||||
g.reset();
|
g.reset();
|
||||||
face.init(gpsObj, swObj);
|
face.init(gpsObj, swObj, hrmObj, tripObject);
|
||||||
startdraw();
|
startdraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// when you feel the buzzer you know you have done a long press
|
// when you feel the buzzer you know you have done a long press
|
||||||
function longPressCheck() {
|
function longPressCheck() {
|
||||||
Bangle.buzz();
|
Bangle.buzz();
|
||||||
|
debug_log("long PressCheck() buzz");
|
||||||
if (pressTimer) {
|
if (pressTimer) {
|
||||||
clearInterval(pressTimer);
|
clearInterval(pressTimer);
|
||||||
|
debug_log("clear pressTimer 2");
|
||||||
pressTimer = undefined;
|
pressTimer = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +47,11 @@ function buttonPressed(btn) {
|
||||||
nextFace();
|
nextFace();
|
||||||
} else {
|
} else {
|
||||||
firstPress = getTime();
|
firstPress = getTime();
|
||||||
|
if (pressTimer) {
|
||||||
|
debug_log("clear pressTimer 1");
|
||||||
|
clearInterval(pressTimer);
|
||||||
|
}
|
||||||
|
debug_log("set pressTimer 1");
|
||||||
pressTimer = setInterval(longPressCheck, 1500);
|
pressTimer = setInterval(longPressCheck, 1500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,6 +60,7 @@ function buttonPressed(btn) {
|
||||||
function buttonReleased(btn) {
|
function buttonReleased(btn) {
|
||||||
var dur = getTime() - firstPress;
|
var dur = getTime() - firstPress;
|
||||||
if (pressTimer) {
|
if (pressTimer) {
|
||||||
|
debug_log("clear pressTimer 3");
|
||||||
clearInterval(pressTimer);
|
clearInterval(pressTimer);
|
||||||
pressTimer = undefined;
|
pressTimer = undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +188,7 @@ GPS.prototype.determineGPSState = function() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.listenerCount > 0) {
|
if (this.listenerCount > 0) {
|
||||||
Bangle.removeListener("GPS", this.processFix);
|
Bangle.removeListener("GPS", processFix);
|
||||||
this.listenerCount--;
|
this.listenerCount--;
|
||||||
this.log_debug("listener removed " + this.listenerCount);
|
this.log_debug("listener removed " + this.listenerCount);
|
||||||
}
|
}
|
||||||
|
|
@ -248,6 +256,7 @@ GPS.prototype.processFix = function(fix) {
|
||||||
this.gpsState = this.GPS_RUNNING;
|
this.gpsState = this.GPS_RUNNING;
|
||||||
if (!this.last_fix.fix && !(require("Storage").readJSON("setting.json", 1) || {}).quiet) {
|
if (!this.last_fix.fix && !(require("Storage").readJSON("setting.json", 1) || {}).quiet) {
|
||||||
Bangle.buzz(); // buzz on first position
|
Bangle.buzz(); // buzz on first position
|
||||||
|
debug_log("GPS fix buzz");
|
||||||
}
|
}
|
||||||
this.last_fix = fix;
|
this.last_fix = fix;
|
||||||
}
|
}
|
||||||
|
|
@ -651,6 +660,122 @@ function stopwatchDraw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
|
||||||
|
Heart Rate Monitor
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
function HRM() {
|
||||||
|
this.bpm = 0;
|
||||||
|
this.confidence = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRM.prototype.log_debug = function(o) {
|
||||||
|
//console.log(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRM.prototype.toggleHRMPower = function() {
|
||||||
|
this.log_debug("HRM.toggleHRMPower()");
|
||||||
|
if (!Bangle.isHRMOn) return; // old firmware
|
||||||
|
|
||||||
|
if (!Bangle.isHRMOn()) {
|
||||||
|
this.log_debug("HRM.toggleHRMPower(powerOn)");
|
||||||
|
Bangle.removeListener('HRM', onHRM);
|
||||||
|
Bangle.setHRMPower(1);
|
||||||
|
Bangle.on('HRM', onHRM);
|
||||||
|
} else {
|
||||||
|
this.log_debug("HRM.toggleHRMPower(powerOff)");
|
||||||
|
Bangle.removeListener('HRM', onHRM);
|
||||||
|
Bangle.setHRMPower(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// poke the hrt widget indicator to change
|
||||||
|
if (WIDGETS.widhrt !== undefined) {
|
||||||
|
WIDGETS.widhrt.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRM.prototype.getBpm = function() {
|
||||||
|
return this.bpm;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRM.prototype.getConfidence = function() {
|
||||||
|
return this.confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRM.prototype.onHRM = function(hrm) {
|
||||||
|
this.bpm = hrm.bpm;
|
||||||
|
this.confidence = hrm.confidence;
|
||||||
|
this.log_debug("onHRM:(bpm)" + this.bpm);
|
||||||
|
this.log_debug("onHRM:(conf) " + this.confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
let hrmObj = new HRM();
|
||||||
|
|
||||||
|
function onHRM(hrm) {
|
||||||
|
hrmObj.onHRM(hrm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
|
||||||
|
Trip Counter
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
function TRIP() {
|
||||||
|
this.showTrip = false;
|
||||||
|
this.tripStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIP.prototype.resetTrip = function(steps) {
|
||||||
|
this.tripStart = (0 + steps);
|
||||||
|
console.log("resetTrip starting=" + this.tripStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIP.prototype.getTrip = function(steps) {
|
||||||
|
let tripSteps = (0 + steps) - this.tripStart;
|
||||||
|
console.log("getTrip steps=" + steps);
|
||||||
|
console.log("getTrip tripStart=" + this.tripStart);
|
||||||
|
console.log("getTrip=" + tripSteps);
|
||||||
|
return tripSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIP.prototype.getTripState = function() {
|
||||||
|
return this.showTrip;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRIP.prototype.setTripState = function(t) {
|
||||||
|
this.showTrip = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tripObject = new TRIP();
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
|
||||||
|
Debug Object
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
function DEBUG() {
|
||||||
|
this.logfile = require("Storage").open("debug.log","a");
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG.prototype.log = function(msg) {
|
||||||
|
let timestamp = new Date().toString().split(" ")[4];
|
||||||
|
let line = timestamp + ", " + msg + "\n";
|
||||||
|
this.logfile.write(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
debugObj = new DEBUG();
|
||||||
|
*/
|
||||||
|
|
||||||
|
function debug_log(m) {
|
||||||
|
//debugObj.log(m);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Start App
|
Start App
|
||||||
|
|
@ -659,6 +784,6 @@ Start App
|
||||||
|
|
||||||
g.clear();
|
g.clear();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
face.init(gpsObj,swObj);
|
face.init(gpsObj,swObj, hrmObj, tripObject);
|
||||||
startdraw();
|
startdraw();
|
||||||
setButtons();
|
setButtons();
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -1,44 +1,28 @@
|
||||||
(() => {
|
(() => {
|
||||||
function getFace(){
|
function getFace(){
|
||||||
var pal4color;
|
|
||||||
var pal4red;
|
|
||||||
var buf;
|
|
||||||
var intervalRefSec;
|
var intervalRefSec;
|
||||||
|
var trip;
|
||||||
|
var prevSteps;
|
||||||
|
|
||||||
function init(g,sw) {
|
function init(g,sw,hrm,tr) {
|
||||||
showMem("stepo init 1");
|
trip = tr;
|
||||||
pal4color = new Uint16Array([0x0000,0xFFFF,0x7BEF,0xAFE5],0,2); // b,w,grey,greenyellow
|
|
||||||
pal4red = new Uint16Array([0x0000,0xFFFF,0xF800,0xAFE5],0,2); // b,w,red,greenyellow
|
|
||||||
buf = Graphics.createArrayBuffer(120,120,2,{msb:true});
|
|
||||||
showMem("stepo init 2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function freeResources() {
|
function freeResources() {
|
||||||
showMem("stepo free 1");
|
trip = undefined;
|
||||||
pal4color = undefined;
|
prevSteps = -1;
|
||||||
pal4red = undefined;
|
|
||||||
buf = undefined;
|
|
||||||
showMem("stepo free 2");
|
|
||||||
}
|
|
||||||
|
|
||||||
function showMem(msg) {
|
|
||||||
var val = process.memory();
|
|
||||||
var str = msg + " " + Math.round(val.usage*100/val.total) + "%";
|
|
||||||
//console.log(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function flip(x,y) {
|
function onButtonShort(btn) {
|
||||||
g.drawImage({width:120,height:120,bpp:2,buffer:buf.buffer, palette:pal4color}, x, y);
|
trip.setTripState(!trip.getTripState());
|
||||||
buf.clear();
|
drawStepText();
|
||||||
}
|
}
|
||||||
|
|
||||||
function flip_red(x,y) {
|
function onButtonLong(btn) {
|
||||||
g.drawImage({width:120,height:120,bpp:2,buffer:buf.buffer, palette:pal4red}, x, y);
|
trip.resetTrip(getSteps());
|
||||||
buf.clear();
|
trip.setTripState(true);
|
||||||
|
drawStepText();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onButtonShort(btn) {}
|
|
||||||
function onButtonLong(btn) {}
|
|
||||||
|
|
||||||
function radians(a) {
|
function radians(a) {
|
||||||
return a*Math.PI/180;
|
return a*Math.PI/180;
|
||||||
|
|
@ -55,10 +39,16 @@
|
||||||
|
|
||||||
function drawSteps() {
|
function drawSteps() {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var cx = 60;
|
var cx = 60 + 60;
|
||||||
var cy = 60;
|
var cy = 60 + 115;
|
||||||
var r = 56;
|
var r = 56;
|
||||||
var steps = getSteps();
|
var steps = getSteps();
|
||||||
|
|
||||||
|
if (prevSteps == steps)
|
||||||
|
return;
|
||||||
|
|
||||||
|
prevSteps = steps;
|
||||||
|
|
||||||
var percent = steps / 10000;
|
var percent = steps / 10000;
|
||||||
|
|
||||||
if (percent > 1) percent = 1;
|
if (percent > 1) percent = 1;
|
||||||
|
|
@ -66,38 +56,60 @@
|
||||||
var startrot = 0 - 180;
|
var startrot = 0 - 180;
|
||||||
var midrot = -180 - (360 * percent);
|
var midrot = -180 - (360 * percent);
|
||||||
var endrot = -360 - 180;
|
var endrot = -360 - 180;
|
||||||
|
|
||||||
buf.setColor(3); // green-yellow
|
g.setColor(0xAFE5); // greenyellow
|
||||||
|
|
||||||
// draw guauge
|
// draw guauge
|
||||||
for (i = startrot; i > midrot; i -= 4) {
|
for (i = startrot; i > midrot; i -= 4) {
|
||||||
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));
|
||||||
buf.fillCircle(x,y,4);
|
g.fillCircle(x,y,4);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.setColor(2); // grey
|
|
||||||
|
|
||||||
// draw remainder of guage in grey
|
|
||||||
for (i = midrot; i > endrot; i -= 4) {
|
|
||||||
x = cx + r * Math.sin(radians(i));
|
|
||||||
y = cy + r * Math.cos(radians(i));
|
|
||||||
buf.fillCircle(x,y,4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw steps
|
|
||||||
buf.setColor(1); // white
|
|
||||||
buf.setFont("Vector", 24);
|
|
||||||
buf.setFontAlign(0,0);
|
|
||||||
buf.drawString(steps, cx, cy);
|
|
||||||
|
|
||||||
// change the remaining color to RED if battery is below 25%
|
// change the remaining color to RED if battery is below 25%
|
||||||
if (E.getBattery() > 25)
|
if (E.getBattery() > 25)
|
||||||
flip(60,115);
|
g.setColor(0x7BEF); // grey
|
||||||
else
|
else
|
||||||
flip_red(60,115);
|
g.setColor(0xF800); // red
|
||||||
|
|
||||||
|
// draw remainder of guage in grey or red
|
||||||
|
for (i = midrot; i > endrot; i -= 4) {
|
||||||
|
x = cx + r * Math.sin(radians(i));
|
||||||
|
y = cy + r * Math.cos(radians(i));
|
||||||
|
g.fillCircle(x,y,4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawStepText() {
|
||||||
|
var cx = 60 + 60;
|
||||||
|
var cy = 60 + 115;
|
||||||
|
var r = 56;
|
||||||
|
var steps = getSteps();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if our trip count is greater than todays steps then we have
|
||||||
|
* rolled over to the next day so we should reset the trip counter
|
||||||
|
*/
|
||||||
|
if (trip.getTrip(steps) < 0)
|
||||||
|
trip.resetTrip(steps);
|
||||||
|
|
||||||
|
// show trip count or total steps today
|
||||||
|
g.setFontAlign(0,0);
|
||||||
|
g.setFont("Vector", 24);
|
||||||
|
|
||||||
|
// clear the space for the text
|
||||||
|
g.clearRect(cx - (r - 12), cy - 16, cx + (r - 12), cy + 16);
|
||||||
|
|
||||||
|
if (trip.getTripState() == true) {
|
||||||
|
g.setColor(0x7BEF); // grey
|
||||||
|
//g.setColor(1,0,0); // red
|
||||||
|
g.drawString(trip.getTrip(steps), cx, cy);
|
||||||
|
} else {
|
||||||
|
g.setColor(1,1,1); // white
|
||||||
|
g.drawString(steps, cx, cy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
var da = d.toString().split(" ");
|
var da = d.toString().split(" ");
|
||||||
|
|
@ -110,12 +122,13 @@
|
||||||
g.drawString(time, 120, 30, true);
|
g.drawString(time, 120, 30, true);
|
||||||
|
|
||||||
drawSteps();
|
drawSteps();
|
||||||
|
drawStepText();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSteps() {
|
function getSteps() {
|
||||||
if (stepsWidget() !== undefined)
|
if (stepsWidget() !== undefined)
|
||||||
return stepsWidget().getSteps();
|
return stepsWidget().getSteps();
|
||||||
return "-";
|
return "E-STEPS";
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepsWidget() {
|
function stepsWidget() {
|
||||||
|
|
@ -132,5 +145,4 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFace;
|
return getFace;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
function getFace(){
|
function getFace(){
|
||||||
let swObject = undefined;
|
let swObject = undefined;
|
||||||
|
|
||||||
function init(gps, sw) {
|
function init(gps, sw, hrm) {
|
||||||
swObject = sw;
|
swObject = sw;
|
||||||
g.clear();
|
g.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Tweaks for app loader
|
0.02: Tweaks for app loader
|
||||||
0.03: Fix app icon, add change of colors
|
0.03: Fix app icon, add change of colors
|
||||||
0.04: Improvements and new round check option elements
|
0.04: Improvements and new radio button option elements
|
||||||
0.05: ...
|
0.05: ...
|
||||||
|
0.06: Improvements, multiple rows with radio buttons
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
# Test User Input
|
# Test User Input
|
||||||
|
|
||||||
This very basic app, allows to *test the bangle.js input interface*, and displays the result in text or a switch on/off image.
|
This basic app, allows to **test the bangle.js input interface** trough every types of finger interaction.
|
||||||
|
Interactrion type is displayed in text or a switch on/off image for swipe screen.
|
||||||
|
|
||||||
|
Besides the basics, the UI also includes multiple rows with radio buttons
|
||||||
|
|
||||||
|
|
||||||
|
## Captures
|
||||||
|
|
||||||
|
(Following images can be outdated)
|
||||||
|
|
||||||
Launcher icon
|
Launcher icon
|
||||||
|
|
||||||
|
|
@ -31,14 +38,14 @@ Colours, font, user input, image, load widgets
|
||||||
|
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
Press left area - Prints Touch1
|
- Press left area - Prints Touch1
|
||||||
Press righ area - Prints Touch2
|
- Press righ area - Prints Touch2
|
||||||
Press center area - Prints Touch3
|
- Press center area - Prints Touch3
|
||||||
Swipe Left - Displays Switch OFF image
|
- Swipe Left - Displays Switch OFF image
|
||||||
Swipe Right - Displays Switch ON image
|
- Swipe Right - Displays Switch ON image
|
||||||
BTN1 - Prints Button1
|
- BTN1 - Prints Button1
|
||||||
BTN2 - Prints Button2
|
- BTN2 - Prints Button2
|
||||||
BTN3 - Quit to Launcher
|
- BTN3 - Quit to Launcher
|
||||||
|
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,71 @@
|
||||||
/* Test bangle.js input interface */
|
/* Test bangle.js input interface */
|
||||||
|
var v_mode_debug=0; //1=yes, 0=no (to disable console msg)
|
||||||
|
if (v_mode_debug==1) console.log("Debug mode enabled");
|
||||||
|
else console.log("Debug mode disabled");
|
||||||
|
var v_model=process.env.BOARD;
|
||||||
|
if (v_mode_debug==1) console.log("device="+v_model);
|
||||||
|
|
||||||
|
var v_str_version='v0.06'; //testing purpose
|
||||||
|
|
||||||
|
var x_max_screen=g.getWidth();//240;
|
||||||
|
var y_max_screen=g.getHeight(); //240;
|
||||||
|
var y_wg_bottom=g.getHeight()-25;
|
||||||
|
var y_wg_top=25;
|
||||||
|
if (v_model=='BANGLEJS') {
|
||||||
|
var x_btn_area=215;
|
||||||
|
var x_max_usable_area=x_btn_area;//Pend! only for bangle.js
|
||||||
|
var y_btn2=124; //harcoded for bangle.js cuz it is not the half of
|
||||||
|
} else x_max_usable_area=240;
|
||||||
|
var x_mid_screen=x_max_screen/2;
|
||||||
|
|
||||||
var colbackg='#111111';//black
|
var colbackg='#111111';//black
|
||||||
var colorange='#e56e06'; //RGB format rrggbb
|
var colorange='#e56e06'; //RGB format rrggbb
|
||||||
var v_color_lines=0xFFFF; //White hex format
|
var v_color_lines=0xFFFF; //White hex format
|
||||||
var v_color_b_area=colbackg;
|
var v_color_b_area=colbackg; //for banner area
|
||||||
var v_font1size='16';
|
var v_color_text='#FB0E01';
|
||||||
var v_clicks='0';
|
//var v_font1size=16;
|
||||||
console.log("*** Test input interface ***");
|
var v_font1size=11; //out of quotes
|
||||||
|
var v_font2size=18;
|
||||||
|
var v_font3size=14;
|
||||||
|
|
||||||
|
var v_clicks=0;
|
||||||
|
var v_selected_row=1; //used by round option
|
||||||
|
var v_total_rows=2;//used by round option
|
||||||
|
var array_r_option=[];
|
||||||
|
|
||||||
|
var v_y_optionrow1=80;
|
||||||
|
var v_y_optionrow2=110;
|
||||||
|
var v_y_optionrow3=140;
|
||||||
|
|
||||||
|
|
||||||
function ClearActiveArea(){
|
if (v_mode_debug==1) console.log("*** Test input interface ***");
|
||||||
|
|
||||||
|
//the biggest usable area, button area not included
|
||||||
|
function ClearActiveArea(x1,y1,x2,y2){
|
||||||
g.setColor(colbackg);
|
g.setColor(colbackg);
|
||||||
g.fillRect(0,32,239,239); //fill all screen except widget area
|
//FOR BANGLE.JS (0,y_wg_top,x_max_usable_area,y_wg_bottom);
|
||||||
|
//fill all screen except widget area
|
||||||
|
g.fillRect(x1,y1,x2,y2);
|
||||||
g.flip();
|
g.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrintHelp(){
|
function PrintHelp(){
|
||||||
console.log("********************************");
|
if (v_mode_debug==1) console.log("Log: *** Print help in screen");
|
||||||
console.log("Log: *** Print help in screen");
|
ClearActiveArea(0,y_wg_top,x_max_usable_area,y_wg_bottom);
|
||||||
ClearActiveArea();
|
g.setColor(colorange);
|
||||||
g.setColor(colorange);
|
/* PRINT FROM widget BOTTOM */
|
||||||
g.setFontVector(18).drawString("To test the input, try :",25,90);
|
g.setFontVector(v_font2size).drawString("To test the UI, try:",5,y_wg_bottom-(10*v_font3size));
|
||||||
g.flip();
|
g.flip();
|
||||||
g.setColor(0,1,0); //green
|
g.setColor(0,1,0); //green
|
||||||
g.setFontVector(v_font1size).drawString("Swipe right -->", 30, 115);
|
g.setFontVector(v_font3size);
|
||||||
g.setFontVector(v_font1size).drawString("Swipe left <--", 30, 130);
|
g.drawString("Swipe right -->", 30, y_wg_bottom-(8*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Click Left area", 30, 145);
|
g.drawString("Swipe left <--", 30, y_wg_bottom-(7*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Click Right area", 30,160);
|
g.drawString("Click Left area", 30, y_wg_bottom-(6*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Click Middle area", 30,175);
|
g.drawString("Click Right area", 30,y_wg_bottom-(5*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Press Button1 ", 30,190);
|
g.drawString("Click Middle area", 30,y_wg_bottom-(4*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Press Button2 for colors", 30,205);
|
g.drawString("Press Button1", 30,y_wg_bottom-(3*v_font3size));
|
||||||
g.setFontVector(v_font1size).drawString("Press Button3 to Quit", 30,220);
|
g.drawString("Press Button2: Colour", 30,y_wg_bottom-(2*v_font3size));
|
||||||
|
g.drawString("Press Button3: Quit", 30,y_wg_bottom-v_font3size);
|
||||||
g.flip();
|
g.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,8 +84,8 @@ function ClearBannerArea(){
|
||||||
g.fillRect(55,32,185,78);
|
g.fillRect(55,32,185,78);
|
||||||
g.flip();
|
g.flip();
|
||||||
}
|
}
|
||||||
|
//arg input area Touch1=left Touch2=right
|
||||||
function DrawRoundOption(area){
|
function DrawRoundOption(x_obj1,y_obj1,x_obj2,y_obj2,i_area){
|
||||||
//draw a img from an Image object
|
//draw a img from an Image object
|
||||||
var img_obj_check = {
|
var img_obj_check = {
|
||||||
width : 30, height : 30, bpp : 4,
|
width : 30, height : 30, bpp : 4,
|
||||||
|
|
@ -63,21 +99,26 @@ function ClearBannerArea(){
|
||||||
palette : new Uint16Array([65535,63422,9532,13789,59197,57084,34266,28220,63390,65503,61310,61277,57116,55003,61309,40604]),
|
palette : new Uint16Array([65535,63422,9532,13789,59197,57084,34266,28220,63390,65503,61310,61277,57116,55003,61309,40604]),
|
||||||
buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMzMwAAAAAAAAAAADMzf//3MzMAAAAAAAAAAzPxmZkRrzMwAAAAAAAAM3mZmZmRiKczAAAAAAADP5mZmZmRiKpjMAAAAAAzeZmZmZkRiKq3MwAAAAAzGZmZmZkRiKq8MwAAAAM/mZmZmZkYiKtE8iAAAAMxmZmZmZEYiqtEUiAAAAN5mZmZmRGIiqtExyAAAAPxmZmZkRiIqrRMViAAAAPxEREREYiKq7RMViAAAAP4ERERiIiqq0TFViAAAAP4iIiIiIqqtETFViAAAAN6iIiIiqq7RExV1yAAAAM0qqqqqru0RMVd0iAAAAM/uqqru7RETFXdYiAAAAAzS7u7RERMxV3dIgAAAAAzdEREREzFVd3XIgAAAAADNkREzMVVXd1iIAAAAAAAM3VVVVVd3dciAAAAAAAAAzNtVd3d1iIgAAAAAAAAADMidmZnIiIAAAAAAAAAAAAiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMzMwAAAAAAAAAAADMzf//3MzMAAAAAAAAAAzPxmZkRrzMwAAAAAAAAM3mZmZmRiKczAAAAAAADP5mZmZmRiKpjMAAAAAAzeZmZmZkRiKq3MwAAAAAzGZmZmZkRiKq8MwAAAAM/mZmZmZkYiKtE8iAAAAMxmZmZmZEYiqtEUiAAAAN5mZmZmRGIiqtExyAAAAPxmZmZkRiIqrRMViAAAAPxEREREYiKq7RMViAAAAP4ERERiIiqq0TFViAAAAP4iIiIiIqqtETFViAAAAN6iIiIiqq7RExV1yAAAAM0qqqqqru0RMVd0iAAAAM/uqqru7RETFXdYiAAAAAzS7u7RERMxV3dIgAAAAAzdEREREzFVd3XIgAAAAADNkREzMVVXd1iIAAAAAAAM3VVVVVd3dciAAAAAAAAAzNtVd3d1iIgAAAAAAAAADMidmZnIiIAAAAAAAAAAAAiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
||||||
};
|
};
|
||||||
if (area=='Touch 1') {
|
if (i_area=='none') {
|
||||||
g.drawImage(img_obj_check,20,80);
|
g.drawImage(img_obj_uncheck,x_obj1,y_obj1);
|
||||||
console.log("Draw option check left");
|
g.drawImage(img_obj_uncheck,x_obj2,y_obj2);
|
||||||
|
}
|
||||||
|
else if (i_area=='Touch 1') {
|
||||||
|
g.drawImage(img_obj_check,x_obj1,y_obj1);
|
||||||
|
g.drawImage(img_obj_uncheck,x_obj2,y_obj2);
|
||||||
|
if (v_mode_debug==1) console.log("Draw option check left");
|
||||||
}
|
}
|
||||||
else g.drawImage(img_obj_uncheck,20,80);
|
else if (i_area=='Touch 2') {
|
||||||
if (area=='Touch 2') {
|
g.drawImage(img_obj_uncheck,x_obj1,y_obj1);
|
||||||
g.drawImage(img_obj_check,190,80);
|
g.drawImage(img_obj_check,x_obj2,y_obj2);
|
||||||
console.log("Draw option check right");
|
if (v_mode_debug==1) console.log("Draw option check right");
|
||||||
}
|
}
|
||||||
else g.drawImage(img_obj_uncheck,190,80);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function DrawSwitch(swipedir){
|
function DrawSwitch(swipedir){
|
||||||
if (swipedir==' <---') {
|
if (swipedir==' <---') {
|
||||||
console.log("Draw switch <--");
|
if (v_mode_debug==1) console.log("Draw switch <--");
|
||||||
var img_off = {
|
var img_off = {
|
||||||
width : 48, height : 48, bpp : 2,
|
width : 48, height : 48, bpp : 2,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
|
|
@ -87,7 +128,7 @@ if (swipedir==' <---') {
|
||||||
g.drawImage(img_off,99,33);
|
g.drawImage(img_off,99,33);
|
||||||
}
|
}
|
||||||
else if (swipedir==' --->') {
|
else if (swipedir==' --->') {
|
||||||
console.log("Draw switch -->");
|
if (v_mode_debug==1) console.log("Draw switch -->");
|
||||||
var img_on = {
|
var img_on = {
|
||||||
width : 48, height : 48, bpp : 2,
|
width : 48, height : 48, bpp : 2,
|
||||||
transparent : 0,
|
transparent : 0,
|
||||||
|
|
@ -100,70 +141,154 @@ if (swipedir==' <---') {
|
||||||
|
|
||||||
|
|
||||||
function PrintUserInput(boton){
|
function PrintUserInput(boton){
|
||||||
console.log("Pressed touch/BTN",boton);
|
if (v_mode_debug==1) console.log("Pressed touch/BTN",boton);
|
||||||
if (v_clicks=='0') {
|
if (v_clicks==0) {
|
||||||
PrintAreas();
|
PrintAreas();
|
||||||
v_clicks=1;
|
v_clicks++;
|
||||||
}
|
}
|
||||||
ClearBannerArea();
|
ClearBannerArea();
|
||||||
|
|
||||||
if (boton==' <---') DrawSwitch(boton);
|
if (boton==' <---') DrawSwitch(boton);
|
||||||
else if (boton==' --->') DrawSwitch(boton);
|
else if (boton==' --->') DrawSwitch(boton);
|
||||||
else
|
//all input but not swipe
|
||||||
{ //a BUTTON or AREA AND NO swipe /slide
|
else {
|
||||||
if (boton=='Touch 1'||boton=='Touch 2') DrawRoundOption(boton);
|
g.setColor(colorange);
|
||||||
g.setColor(colorange);
|
//Call info banner
|
||||||
g.setFontVector(30).drawString(boton, 63, 55);
|
g.setFontVector(30).drawString(boton, 63, 55);
|
||||||
}
|
if ((boton=='Touch 1')||(boton=='Touch 2')){
|
||||||
|
if (v_selected_row==1) v_y_opt=v_y_optionrow1;
|
||||||
|
else if (v_selected_row==2) v_y_opt=v_y_optionrow2;
|
||||||
|
DrawRoundOption(20,v_y_opt,190,v_y_opt,boton);
|
||||||
|
//set the option value in an array
|
||||||
|
array_r_option[v_selected_row]=boton;
|
||||||
|
if (v_mode_debug==1) console.log("array["+v_selected_row+"]="+array_r_option[v_selected_row]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g.flip();
|
g.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrintBtn1(boton){
|
function Btn1Clkd(boton){
|
||||||
console.log("Pressed BTN1");
|
if (v_mode_debug==1) console.log("Pressed BTN1");
|
||||||
if (v_clicks=='0'){
|
if (v_clicks==0){
|
||||||
PrintAreas();
|
PrintAreas(); //only 1st time
|
||||||
v_clicks=1;
|
//v_selected_row=1;
|
||||||
|
v_clicks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
else if ((v_clicks>0)&&(v_selected_row!=v_total_rows)){
|
||||||
|
v_selected_row++;
|
||||||
|
//Params: row_arrow, row_clear_area
|
||||||
|
if (v_mode_debug==1) console.log("row :"+v_selected_row);
|
||||||
|
DrawRowSelArrow(v_selected_row,v_selected_row-1);
|
||||||
|
v_clicks++;
|
||||||
|
}
|
||||||
|
else if ((v_clicks>0)&&(v_selected_row==v_total_rows)){
|
||||||
|
|
||||||
|
DrawRowSelArrow(1,v_selected_row);
|
||||||
|
if (v_mode_debug==1) console.log("last row :"+v_selected_row);
|
||||||
|
v_selected_row=1;
|
||||||
|
v_clicks++;
|
||||||
}
|
}
|
||||||
PrintUserInput("Button1");
|
PrintUserInput("Button1");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function PrintBtn2(boton){
|
function Btn2Clkd(boton){
|
||||||
console.log("Pressed BTN2");
|
if (v_mode_debug==1) console.log("Pressed BTN2");
|
||||||
v_color_b_area=ChangeColorBannerArea(v_color_b_area);
|
v_color_b_area=ChangeColorBannerArea(v_color_b_area);
|
||||||
if (v_clicks=='0'){
|
if (v_clicks==0){
|
||||||
PrintAreas();
|
PrintAreas();//only 1st time
|
||||||
v_clicks=1;
|
v_clicks++;
|
||||||
}
|
}
|
||||||
PrintUserInput("Button2");
|
PrintUserInput("Button2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function DrawBangleButtons(){
|
||||||
|
|
||||||
|
/*Button name */
|
||||||
|
g.setColor(v_color_text); //green
|
||||||
|
g.setFontVector(v_font3size);
|
||||||
|
g.drawString("B1", x_max_screen-g.stringWidth("B1"),y_wg_top);
|
||||||
|
g.drawString("B2", x_max_screen-g.stringWidth("B2"),y_btn2);
|
||||||
|
//y y_wg_bottom-v_font3size ?
|
||||||
|
g.drawString("B3",x_max_screen-g.stringWidth("B3"),y_wg_bottom);
|
||||||
|
|
||||||
|
/*Button area description */
|
||||||
|
g.setFontVector(v_font1size);
|
||||||
|
g.setColor(v_color_lines);
|
||||||
|
//y_wg_bottom-(2*v_font1size)
|
||||||
|
g.drawString("Quit", x_max_screen-g.stringWidth("Quit"),y_wg_bottom-v_font1size-2);
|
||||||
|
|
||||||
|
|
||||||
|
//Print version
|
||||||
|
if (v_mode_debug==1){
|
||||||
|
g.setColor(0,1,0); //green
|
||||||
|
//y_wg_bottom-(2*v_font1size)
|
||||||
|
g.drawString(v_str_version, x_max_screen-g.stringWidth(v_str_version),y_wg_bottom-(v_font1size*3));
|
||||||
|
}
|
||||||
|
|
||||||
|
//under btn2, left top 90grades
|
||||||
|
g.setFontAlign(-1,-1,1);
|
||||||
|
g.drawString("Color", x_max_screen-v_font1size,y_btn2+v_font3size);
|
||||||
|
//g.drawString("Color", x_max_screen-g.stringWidth("Color"),y_btn2+v_font1size);
|
||||||
|
|
||||||
|
|
||||||
|
g.setColor(0,1,0); //green
|
||||||
|
g.drawString("Up", x_max_screen-v_font1size,y_wg_top+v_font3size);
|
||||||
|
g.setColor(v_color_lines);
|
||||||
|
g.drawString("Down", x_max_screen-2*v_font1size,y_wg_top+v_font3size);
|
||||||
|
g.flip();
|
||||||
|
//back to standard /horizontal
|
||||||
|
g.setFontAlign(-1,-1,0);
|
||||||
|
}
|
||||||
|
|
||||||
function PrintAreas(){
|
function DrawRowSelArrow(v_drawRow, v_clearRow){
|
||||||
console.log("********************************");
|
//Params: row_arrow, row_clear_area
|
||||||
console.log("Log: *** Print Areas in screen");
|
//for clear previous draw arrow
|
||||||
ClearActiveArea();
|
if (v_clearRow!== undefined) {
|
||||||
g.setColor(v_color_lines);
|
g.setColor(colbackg);
|
||||||
g.drawLine(1, 140, 1, 200);//vline left border
|
if (v_clearRow==1) v_y_arrow=v_y_optionrow1+14;
|
||||||
g.drawLine(239, 140, 239, 200);//vlide right border
|
else if (v_clearRow==2) v_y_arrow=v_y_optionrow2+14;
|
||||||
g.drawLine(120, 100, 120, 135);//vline middle separation top
|
else if (v_clearRow==3) v_y_arrow=v_y_optionrow3+14;
|
||||||
g.drawLine(120, 170, 120, 200);//vline middle separation bottom
|
g.fillRect(5,v_y_arrow-5,13,v_y_arrow+5);
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
//draw an arrow to select a row
|
||||||
|
if (v_drawRow!== undefined) {
|
||||||
|
if (v_drawRow==1) v_y_arrow=v_y_optionrow1+14;
|
||||||
|
else if (v_drawRow==2) v_y_arrow=v_y_optionrow2+14;
|
||||||
|
else if (v_drawRow==3) v_y_arrow=v_y_optionrow3+14;
|
||||||
|
|
||||||
|
g.setColor(v_color_lines);
|
||||||
|
g.drawLine(5, v_y_arrow, 13, v_y_arrow);//horizontal
|
||||||
|
g.drawLine(13, v_y_arrow, 10, v_y_arrow-5);//over diag
|
||||||
|
g.drawLine(13, v_y_arrow, 10, v_y_arrow+5);//under diag
|
||||||
|
g.flip();
|
||||||
|
}
|
||||||
|
else console.log("Error: Param row nbr missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
function PrintAreas(){
|
||||||
|
if (v_mode_debug==1) console.log("Log: *** Print Areas in screen");
|
||||||
|
ClearActiveArea(0,y_wg_top,x_max_usable_area,y_wg_bottom);
|
||||||
|
g.setColor(v_color_lines);
|
||||||
|
|
||||||
//BTN1
|
DrawRowSelArrow(1);
|
||||||
g.setFontVector(v_font1size).drawString("Color<-", 130,125);
|
DrawRoundOption(20,v_y_optionrow1,190,v_y_optionrow1,'none');
|
||||||
//BTN13
|
DrawRoundOption(20,v_y_optionrow2,190,v_y_optionrow2,'none');
|
||||||
g.setFontVector(v_font1size).drawString("Quit<-", 135,225);
|
|
||||||
g.flip();
|
|
||||||
g.setColor(0,1,0); //green
|
|
||||||
g.setFontVector(v_font1size).drawString("BTN1", 195,45);
|
|
||||||
|
|
||||||
g.setFontVector(v_font1size).drawString("BTN2", 195,125);
|
g.drawLine(x_max_screen-1, 50, x_max_screen-1, 65);//vlide right border
|
||||||
|
g.drawLine(x_mid_screen, 80, x_mid_screen, 105);//vline middle separation part1 up
|
||||||
|
g.drawLine(x_mid_screen, 140, x_mid_screen, 180);//vline middle separation part2 down
|
||||||
|
|
||||||
g.setFontVector(v_font1size).drawString("BTN3", 195,225);
|
|
||||||
g.setFontVector(v_font1size).drawString("Middle area", 80,155);
|
g.setFontVector(v_font3size);
|
||||||
g.setFontVector(v_font1size).drawString("Left area", 15, 185);
|
g.drawString("Middle area", 80,155);
|
||||||
g.setFontVector(v_font1size).drawString("Right area", 140,185);
|
g.drawString("Left area", 15, 185);
|
||||||
g.flip();
|
g.drawString("Right area", 140,185);
|
||||||
|
|
||||||
|
if (v_model=='BANGLEJS') DrawBangleButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
function UserInput(){
|
function UserInput(){
|
||||||
|
|
@ -181,23 +306,26 @@ function UserInput(){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//only the name of the function
|
//only the name of the function
|
||||||
setWatch(PrintBtn1, BTN1, { repeat: true });
|
setWatch(Btn1Clkd, BTN1, { repeat: true });
|
||||||
setWatch(PrintBtn2, BTN2, { repeat: true });
|
setWatch(Btn2Clkd, BTN2, { repeat: true });
|
||||||
setWatch(Bangle.showLauncher, BTN3, { repeat: true });
|
setWatch(Bangle.showLauncher, BTN3, { repeat: true });
|
||||||
Bangle.on('swipe', dir => {
|
Bangle.on('swipe', dir => {
|
||||||
if(dir == 1) PrintUserInput(" --->");
|
if(dir == 1) PrintUserInput(" --->");
|
||||||
else PrintUserInput(" <---");
|
else PrintUserInput(" <---");
|
||||||
});
|
});
|
||||||
console.log("Log: Input conditions loaded");
|
if (v_mode_debug==1) console.log("Log: Input conditions loaded");
|
||||||
} //end of UserInput
|
} //end of UserInput
|
||||||
|
|
||||||
//Main code
|
//Main code
|
||||||
|
g.clear();
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
//optional line below widgets area
|
|
||||||
g.setColor(v_color_lines);
|
g.setColor(v_color_lines);
|
||||||
g.drawLine(60, 30, 180, 30);
|
//optional line below widgets area
|
||||||
g.flip();
|
//g.drawLine(60, 30, 180, 30);
|
||||||
|
//g.flip();
|
||||||
//end optional
|
//end optional
|
||||||
PrintHelp();
|
PrintHelp();
|
||||||
|
|
||||||
UserInput();
|
UserInput();
|
||||||
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 112 KiB |