BangleApps/apps/speedalt/app.js

425 lines
10 KiB
JavaScript
Raw Normal View History

2021-01-21 02:42:19 +00:00
/*
Speed and Altitude [speedalt]
2021-01-26 22:33:16 +00:00
Mike Bennett mike[at]kereru.com
2021-01-21 02:42:19 +00:00
*/
2021-02-06 08:52:57 +00:00
var v = '1.13';
2021-02-01 09:48:30 +00:00
var buf = Graphics.createArrayBuffer(240,160,2,{msb:true});
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
// Load fonts
require("Font7x11Numeric7Seg").add(Graphics);
2021-02-01 09:48:30 +00:00
var lf = {fix:0,satellites:0};
2021-01-26 22:33:16 +00:00
var showMax = 0; // 1 = display the max values. 0 = display the cur fix
2021-02-05 08:48:15 +00:00
var pwrSav = 1; // 1 = default power saving with watch screen off and GPS to PMOO mode. 0 = screen kept on.
2021-01-28 10:22:07 +00:00
var canDraw = 1;
2021-01-26 22:33:16 +00:00
var time = ''; // Last time string displayed. Re displayed in background colour to remove before drawing new time.
2021-02-05 00:22:00 +00:00
var tmrLP; // Timer for delay in switching to low power after screen turns off
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
var max = {};
max.spd = 0;
max.alt = 0;
2021-01-21 02:42:19 +00:00
2021-02-04 04:03:44 +00:00
var emulator = (process.env.BOARD=="EMSCRIPTEN")?1:0; // 1 = running in emulator. Supplies test values;
2021-01-26 22:33:16 +00:00
var wp = {}; // Waypoint to use for distance from cur position.
function nxtWp(inc){
2021-02-02 02:57:41 +00:00
if (settings.modeA) return;
settings.wp+=inc;
loadWp();
}
function loadWp() {
var w = require("Storage").readJSON('waypoints.json')||[{name:"NONE"}];
if (settings.wp>=w.length) settings.wp=0;
if (settings.wp<0) settings.wp = w.length-1;
2021-02-02 02:57:41 +00:00
savSettings();
wp = w[settings.wp];
}
function radians(a) {
return a*Math.PI/180;
}
function distance(a,b){
var x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2));
var y = radians(b.lat-a.lat);
// Distance in selected units
var d = Math.sqrt(x*x + y*y) * 6371000;
d = (d/parseFloat(settings.dist)).toFixed(2);
if ( d >= 100 ) d = parseFloat(d).toFixed(1);
if ( d >= 1000 ) d = parseFloat(d).toFixed(0);
return d;
}
2021-02-01 06:40:37 +00:00
function drawFix(speed,units,sats,alt,alt_units,age,fix) {
2021-01-28 10:22:07 +00:00
if (!canDraw) return;
2021-01-26 22:33:16 +00:00
2021-01-28 10:22:07 +00:00
buf.clear();
2021-02-04 04:03:44 +00:00
var v = '';
2021-01-26 22:33:16 +00:00
var u='';
// Primary Display
2021-02-05 01:31:24 +00:00
v = (settings.primSpd)?speed.toString():alt.toString();
2021-01-26 22:33:16 +00:00
// Primary Units
2021-02-05 01:31:24 +00:00
u = (settings.primSpd)?settings.spd_unit:alt_units;
2021-01-26 22:33:16 +00:00
2021-02-04 04:03:44 +00:00
drawPrimary(v,u);
2021-01-26 22:33:16 +00:00
// Secondary Display
2021-02-05 01:31:24 +00:00
v = (settings.primSpd)?alt.toString():speed.toString();
2021-01-26 22:33:16 +00:00
// Secondary Units
2021-02-05 01:31:24 +00:00
u = (settings.primSpd)?alt_units:settings.spd_unit;
2021-01-26 22:33:16 +00:00
2021-02-04 04:03:44 +00:00
drawSecondary(v,u);
2021-01-26 22:33:16 +00:00
// Time
drawTime();
// Waypoint name
drawWP();
2021-01-26 22:33:16 +00:00
//Sats
2021-02-05 01:03:07 +00:00
if ( age > 10 ) {
if ( age > 90 ) age = '>90';
drawSats('Age:'+age);
}
2021-02-04 22:23:12 +00:00
else drawSats('Sats:'+sats);
2021-01-28 10:22:07 +00:00
g.reset();
g.drawImage(img,0,40);
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
}
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
function drawPrimary(n,u) {
2021-01-21 02:42:19 +00:00
// Primary Display
2021-01-26 22:33:16 +00:00
var s=40; // Font size
2021-02-04 04:03:44 +00:00
var l=n.length;
if ( l <= 7 ) s=48;
if ( l <= 6 ) s=55;
if ( l <= 5 ) s=68;
if ( l <= 4 ) s=85;
if ( l <= 3 ) s=110;
2021-01-21 02:42:19 +00:00
buf.setFontAlign(0,-1); //Centre
buf.setColor(1);
buf.setFontVector(s);
2021-01-26 22:33:16 +00:00
buf.drawString(n,110,0);
2021-01-21 02:42:19 +00:00
// Primary Units
buf.setFontAlign(1,-1,3); //right
buf.setColor(2);
buf.setFontVector(25);
2021-01-26 22:33:16 +00:00
buf.drawString(u,210,0);
}
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
function drawSecondary(n,u) {
var s=180; // units X position
2021-02-04 04:03:44 +00:00
var l=n.length;
if ( l <= 5 ) s=155;
if ( l <= 4 ) s=125;
if ( l <= 3 ) s=100;
if ( l <= 2 ) s=65;
if ( l <= 1 ) s=35;
2021-01-21 02:42:19 +00:00
buf.setFontAlign(-1,1); //left, bottom
buf.setColor(1);
2021-01-26 22:33:16 +00:00
buf.setFontVector(45);
buf.drawString(n,5,140);
2021-01-21 02:42:19 +00:00
// Secondary Units
buf.setFontAlign(-1,1); //left, bottom
buf.setColor(2);
2021-01-26 22:33:16 +00:00
buf.setFontVector(25);
buf.drawString(u,s,135);
2021-01-21 02:42:19 +00:00
}
2021-01-26 22:33:16 +00:00
function drawTime() {
var x = 0;
var y = 160;
2021-01-21 02:42:19 +00:00
2021-01-28 21:03:18 +00:00
buf.setFont("7x11Numeric7Seg", 2);
2021-01-28 10:22:07 +00:00
buf.setFontAlign(-1,1); //left, bottom
2021-01-26 22:33:16 +00:00
buf.setColor(0);
buf.drawString(time,x,y);
time = require("locale").time(new Date(),1);
2021-01-21 02:42:19 +00:00
buf.setColor(3);
2021-01-26 22:33:16 +00:00
buf.drawString(time,x,y);
}
2021-01-21 02:42:19 +00:00
function drawWP() {
var nm = wp.name;
2021-02-05 01:03:07 +00:00
if ( nm == undefined || nm == 'NONE' || settings.modeA ) nm = '';
2021-02-05 01:03:07 +00:00
buf.setFontAlign(-1,1); //left, bottom
buf.setColor(2);
buf.setFontVector(20);
buf.drawString(nm.substring(0,6),77,160);
}
2021-01-26 22:33:16 +00:00
function drawSats(sats) {
2021-02-01 06:40:37 +00:00
buf.setColor(3);
buf.setFont("6x8", 2);
buf.setFontAlign(1,1); //right, bottom
buf.drawString(sats,240,160);
2021-02-01 09:48:30 +00:00
buf.setFontVector(20);
buf.setColor(2);
2021-02-02 02:57:41 +00:00
if ( settings.modeA ) buf.drawString("A",240,140);
2021-02-01 09:48:30 +00:00
else buf.drawString("D",240,140);
2021-02-02 02:57:41 +00:00
if ( showMax && settings.modeA ) {
2021-02-01 09:48:30 +00:00
buf.setFontAlign(0,1); //centre, bottom
buf.drawString("MAX",120,164);
}
2021-01-26 22:33:16 +00:00
}
2021-01-21 02:42:19 +00:00
function onGPS(fix) {
2021-02-01 06:40:37 +00:00
if ( emulator ) {
2021-02-01 22:09:40 +00:00
fix.fix = 1;
2021-02-01 22:21:41 +00:00
fix.speed = 10;
2021-02-01 22:09:40 +00:00
fix.alt = 354;
2021-02-01 06:40:37 +00:00
fix.lat = -38.92;
fix.lon = 175.7613350;
fix.course = 245;
fix.satellites = 12;
fix.time = new Date();
}
2021-02-04 21:31:26 +00:00
2021-02-01 06:40:37 +00:00
var m;
2021-01-26 22:33:16 +00:00
2021-02-04 05:58:03 +00:00
var sp = '---';
var al = '---';
var di = '---';
2021-02-04 04:03:44 +00:00
var age = '---';
2021-02-04 21:31:26 +00:00
2021-02-04 22:55:25 +00:00
if (fix.fix) {
lf = fix;
2021-02-04 21:47:54 +00:00
// Speed
if ( settings.spd == 0 ) {
m = require("locale").speed(lf.speed).match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
sp = parseFloat(m[1]);
settings.spd_unit = m[2];
}
2021-02-05 02:20:17 +00:00
else sp = parseFloat(lf.speed)/parseFloat(settings.spd); // Calculate for selected units
2021-02-04 21:47:54 +00:00
if ( sp < 10 ) sp = sp.toFixed(1);
else sp = Math.round(sp);
if (parseFloat(sp) > parseFloat(max.spd) ) max.spd = parseFloat(sp);
// Altitude
al = lf.alt;
al = Math.round(parseFloat(al)/parseFloat(settings.alt));
if (parseFloat(al) > parseFloat(max.alt) ) max.alt = parseFloat(al);
// Distance to waypoint
di = distance(lf,wp);
if (isNaN(di)) di = 0;
// Age of last fix (secs)
2021-02-04 22:27:07 +00:00
age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000));
2021-02-04 22:14:34 +00:00
}
2021-02-01 06:40:37 +00:00
2021-02-04 21:47:54 +00:00
if ( settings.modeA ) {
2021-02-05 02:20:17 +00:00
if ( showMax ) drawFix(max.spd,settings.spd_unit,lf.satellites,max.alt,settings.alt_unit,age,lf.fix); // Speed and alt maximums
else drawFix(sp,settings.spd_unit,lf.satellites,al,settings.alt_unit,age,lf.fix); // Show speed/altitude
}
2021-02-04 21:47:54 +00:00
else {
// Show speed/distance
2021-02-05 02:20:17 +00:00
if ( di <= 0 ) drawFix(sp,settings.spd_unit,lf.satellites,'','',age,lf.fix); // No WP selected
else drawFix(sp,settings.spd_unit,lf.satellites,di,settings.dist_unit,age,lf.fix);
2021-02-04 21:47:54 +00:00
}
2021-01-21 02:42:19 +00:00
2021-01-28 21:03:18 +00:00
}
2021-01-21 02:42:19 +00:00
function setButtons(){
2021-01-26 22:33:16 +00:00
// Spd+Dist : Select next waypoint
2021-02-06 04:10:17 +00:00
setWatch(function(e) {
var dur = e.time - e.lastTime;
if ( settings.modeA ) {
// Spd+Alt mode - Switch between fix and MAX
if ( dur < 2 ) showMax = !showMax; // Short press toggle fix/max display
else { max.spd = 0; max.alt = 0; } // Long press resets max values.
}
else nxtWp(1); // Spd+Dist mode - Select next waypoint
onGPS(lf);
2021-02-06 07:42:01 +00:00
}, BTN1, { edge:"falling",repeat:true});
2021-02-06 04:10:17 +00:00
// Show launcher when middle button pressed
2021-02-06 07:31:31 +00:00
// setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Power saving on/off
setWatch(function(e){
2021-02-06 08:08:13 +00:00
var dur = e.time - e.lastTime;
if ( dur < 2 ) { // Short press.
pwrSav=!pwrSav;
if ( pwrSav ) {
LED1.reset();
var s = require('Storage').readJSON('setting.json',1)||{};
var t = s.timeout||10;
Bangle.setLCDTimeout(t);
}
else {
Bangle.setLCDTimeout(0);
Bangle.setLCDPower(1);
LED1.set();
}
2021-02-06 07:31:31 +00:00
}
2021-02-06 08:45:54 +00:00
else gpsOff(); // long press, power off LP GPS
2021-02-06 07:42:01 +00:00
}, BTN2, {repeat:true,edge:"falling"});
2021-02-06 07:31:31 +00:00
2021-02-01 19:16:28 +00:00
// Toggle between alt or dist
2021-02-06 07:31:31 +00:00
setWatch(function(e){
settings.modeA = !settings.modeA;
savSettings();
onGPS(lf);
2021-02-06 07:42:01 +00:00
}, BTN3, {repeat:true,edge:"falling"});
2021-01-21 02:42:19 +00:00
2021-02-01 19:32:36 +00:00
// Touch left screen to toggle display
2021-02-06 07:31:31 +00:00
setWatch(function(e){
settings.primSpd = !settings.primSpd;
savSettings();
onGPS(lf); // Update display
2021-02-06 07:42:01 +00:00
}, BTN4, {repeat:true,edge:"falling"});
2021-02-01 19:32:36 +00:00
2021-01-26 22:33:16 +00:00
}
function updateClock() {
2021-01-28 10:22:07 +00:00
if (!canDraw) return;
2021-01-26 22:33:16 +00:00
drawTime();
g.reset();
g.drawImage(img,0,40);
2021-02-04 04:03:44 +00:00
if ( emulator ) {max.spd++;max.alt++;}
2021-01-26 22:33:16 +00:00
}
2021-01-28 10:22:07 +00:00
function startDraw(){
canDraw=true;
2021-02-06 08:45:54 +00:00
setLpMode('SuperE'); // off
2021-01-28 10:22:07 +00:00
g.clear();
Bangle.drawWidgets();
2021-02-01 09:48:30 +00:00
onGPS(lf); // draw app screen
2021-01-28 10:22:07 +00:00
}
function stopDraw() {
canDraw=false;
2021-02-06 08:45:54 +00:00
if (!tmrLP) tmrLP=setInterval(function () {if (lf.fix) setLpMode('PSMOO');}, 30000); //Drop to low power in 30 secs. Keep lp mode off until we have a first fix.
2021-01-28 10:22:07 +00:00
}
2021-02-02 02:57:41 +00:00
function savSettings() {
require("Storage").write('speedalt.json',settings);
}
2021-02-04 19:06:09 +00:00
// Is low power GPS service available to use?
function isLP() {
if (WIDGETS.gpsservice == undefined) return(0);
return(1);
}
2021-02-06 08:45:54 +00:00
function setLpMode(m) {
2021-02-05 00:54:04 +00:00
if (tmrLP) {clearInterval(tmrLP);tmrLP = false;} // Stop any scheduled drop to low power
2021-02-04 19:06:09 +00:00
if ( !lp ) return;
2021-02-04 20:01:14 +00:00
var s = WIDGETS.gpsservice.gps_get_settings();
2021-02-05 21:28:20 +00:00
if ( m !== s.power_mode || !s.gpsservice ) {
2021-02-06 08:45:54 +00:00
s.gpsservice = true;
2021-02-05 01:46:26 +00:00
s.power_mode = m;
2021-02-05 01:44:12 +00:00
WIDGETS.gpsservice.gps_set_settings(s);
WIDGETS.gpsservice.reload();
}
2021-02-04 19:06:09 +00:00
}
2021-02-06 08:45:54 +00:00
function gpsOff() {
if ( !lp ) return;
var s = WIDGETS.gpsservice.gps_get_settings();
2021-02-06 08:52:57 +00:00
s.gpsservice = false;
2021-02-06 08:45:54 +00:00
s.power_mode = 'SuperE';
WIDGETS.gpsservice.gps_set_settings(s);
WIDGETS.gpsservice.reload();
}
2021-02-01 09:20:48 +00:00
// =Main Prog
2021-01-28 10:22:07 +00:00
2021-01-26 22:33:16 +00:00
// Read settings.
let settings = require('Storage').readJSON('speedalt.json',1)||{};
2021-01-28 10:22:07 +00:00
2021-01-26 22:33:16 +00:00
settings.spd = settings.spd||0; // Multiplier for speed unit conversions. 0 = use the locale values for speed
settings.spd_unit = settings.spd_unit||''; // Displayed speed unit
settings.alt = settings.alt||0.3048;// Multiplier for altitude unit conversions.
settings.alt_unit = settings.alt_unit||'feet'; // Displayed altitude units
settings.dist = settings.dist||1000;// Multiplier for distnce unit conversions.
settings.dist_unit = settings.dist_unit||'km'; // Displayed altitude units
settings.colour = settings.colour||0; // Colour scheme.
settings.wp = settings.wp||0; // Last selected waypoint for dist
2021-02-02 02:57:41 +00:00
settings.modeA = settings.modeA||0; // 0 = [D], 1 = [A]
settings.primSpd = settings.primSpd||0; // 1 = Spd in primary, 0 = Spd in secondary
loadWp();
2021-01-26 22:33:16 +00:00
/*
Colour Pallet Idx
0 : Background (black)
1 : Speed/Alt
2 : Units
3 : Sats
*/
var img = {
width:buf.getWidth(),
height:buf.getHeight(),
2021-02-01 09:48:30 +00:00
bpp:2,
2021-01-26 22:33:16 +00:00
buffer:buf.buffer,
2021-02-01 09:48:30 +00:00
palette:new Uint16Array([0,0x4FE0,0xEFE0,0x07DB])
2021-01-26 22:33:16 +00:00
};
2021-02-05 23:09:14 +00:00
if ( settings.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFF6,0xDFFF]);
if ( settings.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xFAE0,0xF813]);
2021-01-26 22:33:16 +00:00
2021-01-28 10:22:07 +00:00
var SCREENACCESS = {
withApp:true,
2021-02-04 05:58:03 +00:00
request:function(){this.withApp=false;stopDraw();},
release:function(){this.withApp=true;startDraw();}
2021-01-28 10:22:07 +00:00
};
2021-01-26 22:33:16 +00:00
2021-01-28 10:22:07 +00:00
Bangle.on('lcdPower',function(on) {
if (!SCREENACCESS.withApp) return;
2021-02-04 05:58:03 +00:00
if (on) startDraw();
else stopDraw();
2021-01-28 10:22:07 +00:00
});
2021-01-26 22:33:16 +00:00
2021-01-28 10:22:07 +00:00
// All set up. Lets go.
2021-01-26 22:33:16 +00:00
g.clear();
2021-01-21 02:42:19 +00:00
Bangle.loadWidgets();
Bangle.drawWidgets();
2021-02-01 09:48:30 +00:00
onGPS(lf);
2021-02-05 20:26:41 +00:00
var lp = isLP(); // Low power GPS widget installed?
2021-02-05 20:17:33 +00:00
if ( lp ) {
2021-02-06 08:45:54 +00:00
setLpMode('SuperE');
2021-02-05 20:26:41 +00:00
setInterval(()=>onGPS(WIDGETS.gpsservice.gps_get_fix()), 1000);
2021-02-05 20:17:33 +00:00
}
else {
Bangle.setGPSPower(1);
Bangle.on('GPS', onGPS);
}
2021-02-05 20:26:41 +00:00
2021-01-21 02:42:19 +00:00
setButtons();
2021-01-26 22:33:16 +00:00
setInterval(updateClock, 30000);