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-02-12 00:53:08 +00:00
1.16 : Use new GPS settings module
2021-01-21 02:42:19 +00:00
* /
2021-02-20 21:24:16 +00:00
var v = '1.21' ;
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
2021-01-31 03:40:12 +00:00
var wp = { } ; // Waypoint to use for distance from cur position.
2021-02-01 21:40:27 +00:00
function nxtWp ( inc ) {
2021-02-12 01:09:11 +00:00
cfg . wp += inc ;
2021-02-01 21:40:27 +00:00
loadWp ( ) ;
}
function loadWp ( ) {
var w = require ( "Storage" ) . readJSON ( 'waypoints.json' ) || [ { name : "NONE" } ] ;
2021-02-12 01:09:11 +00:00
if ( cfg . wp >= w . length ) cfg . wp = 0 ;
if ( cfg . wp < 0 ) cfg . wp = w . length - 1 ;
2021-02-02 02:57:41 +00:00
savSettings ( ) ;
2021-02-12 01:09:11 +00:00
wp = w [ cfg . wp ] ;
2021-01-31 03:40:12 +00:00
}
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 ;
2021-02-12 01:09:11 +00:00
d = ( d / parseFloat ( cfg . dist ) ) . toFixed ( 2 ) ;
2021-01-31 03:40:12 +00:00
if ( d >= 100 ) d = parseFloat ( d ) . toFixed ( 1 ) ;
if ( d >= 1000 ) d = parseFloat ( d ) . toFixed ( 0 ) ;
return d ;
}
2021-02-12 03:04:11 +00:00
function drawFix ( dat ) {
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-01-31 08:59:22 +00:00
2021-02-04 04:03:44 +00:00
var v = '' ;
2021-01-26 22:33:16 +00:00
var u = '' ;
// Primary Display
2021-02-12 03:04:11 +00:00
v = ( cfg . primSpd ) ? dat . speed . toString ( ) : dat . alt . toString ( ) ;
2021-01-26 22:33:16 +00:00
// Primary Units
2021-02-12 03:04:11 +00:00
u = ( cfg . primSpd ) ? cfg . spd _unit : dat . 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-12 03:04:11 +00:00
v = ( cfg . primSpd ) ? dat . alt . toString ( ) : dat . speed . toString ( ) ;
2021-01-26 22:33:16 +00:00
// Secondary Units
2021-02-12 03:04:11 +00:00
u = ( cfg . primSpd ) ? dat . alt _units : cfg . 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 ( ) ;
2021-01-31 03:40:12 +00:00
// Waypoint name
drawWP ( ) ;
2021-01-26 22:33:16 +00:00
//Sats
2021-02-12 03:04:11 +00:00
if ( dat . age > 10 ) {
if ( dat . age > 90 ) dat . age = '>90' ;
drawSats ( 'Age:' + dat . age ) ;
2021-02-05 01:03:07 +00:00
}
2021-02-12 03:04:11 +00:00
else drawSats ( 'Sats:' + dat . sats ) ;
2021-02-04 22:23:12 +00:00
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-02-20 21:24:16 +00:00
function drawClock ( ) {
if ( ! canDraw ) return ;
buf . clear ( ) ;
drawTime ( ) ;
g . reset ( ) ;
g . drawImage ( img , 0 , 40 ) ;
}
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 ( ) {
2021-02-20 21:24:16 +00:00
var x , y ;
if ( cfg . modeA == 2 ) {
x = 120 ;
y = 80 ;
buf . setFontAlign ( 0 , 0 ) ; //left, bottom
buf . setFontVector ( 80 ) ;
}
else {
x = 0 ;
y = 160 ;
buf . setFontAlign ( - 1 , 1 ) ;
buf . setFont ( "7x11Numeric7Seg" , 2 ) ;
}
2021-01-21 02:42:19 +00:00
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
2021-01-31 03:40:12 +00:00
function drawWP ( ) {
var nm = wp . name ;
2021-02-20 21:24:16 +00:00
if ( nm == undefined || nm == 'NONE' || cfg . modeA != 0 ) nm = '' ;
2021-01-31 03:40:12 +00:00
2021-02-05 01:03:07 +00:00
buf . setFontAlign ( - 1 , 1 ) ; //left, bottom
2021-01-31 03:40:12 +00:00
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-20 21:24:16 +00:00
if ( cfg . modeA == 1 ) {
buf . drawString ( "A" , 240 , 140 ) ;
if ( showMax ) {
buf . setFontAlign ( 0 , 1 ) ; //centre, bottom
buf . drawString ( "MAX" , 120 , 164 ) ;
}
2021-02-01 09:48:30 +00:00
}
2021-02-20 21:24:16 +00:00
if ( cfg . modeA == 0 ) buf . drawString ( "D" , 240 , 140 ) ;
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-12 01:41:37 +00:00
if ( fix . fix ) lf = fix ;
if ( lf . fix ) {
2021-02-04 22:55:25 +00:00
2021-02-04 21:47:54 +00:00
// Speed
2021-02-12 01:09:11 +00:00
if ( cfg . spd == 0 ) {
2021-02-04 21:47:54 +00:00
m = require ( "locale" ) . speed ( lf . speed ) . match ( /([0-9,\.]+)(.*)/ ) ; // regex splits numbers from units
sp = parseFloat ( m [ 1 ] ) ;
2021-02-12 01:09:11 +00:00
cfg . spd _unit = m [ 2 ] ;
2021-02-04 21:47:54 +00:00
}
2021-02-12 01:09:11 +00:00
else sp = parseFloat ( lf . speed ) / parseFloat ( cfg . spd ) ; // Calculate for selected units
2021-02-05 02:20:17 +00:00
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 ;
2021-02-12 01:09:11 +00:00
al = Math . round ( parseFloat ( al ) / parseFloat ( cfg . alt ) ) ;
2021-02-04 21:47:54 +00:00
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-20 21:24:16 +00:00
if ( cfg . modeA == 1 ) {
2021-02-12 03:04:11 +00:00
if ( showMax )
drawFix ( {
speed : max . spd ,
sats : lf . satellites ,
alt : max . alt ,
alt _units : cfg . alt _unit ,
age : age ,
fix : lf . fix
} ) ; // Speed and alt maximums
else
drawFix ( {
speed : sp ,
sats : lf . satellites ,
alt : al ,
alt _units : cfg . alt _unit ,
age : age ,
fix : lf . fix
} ) ; // Show speed/altitude
2021-02-20 21:24:16 +00:00
}
if ( cfg . modeA == 0 ) {
2021-02-04 21:47:54 +00:00
// Show speed/distance
2021-02-12 03:04:11 +00:00
if ( di <= 0 )
drawFix ( {
speed : sp ,
sats : lf . satellites ,
alt : '' ,
alt _units : '' ,
age : age ,
fix : lf . fix
} ) ; // No WP selected
else
drawFix ( {
speed : sp ,
sats : lf . satellites ,
alt : di ,
alt _units : cfg . dist _unit ,
age : age ,
fix : lf . fix
} ) ;
2021-02-04 21:47:54 +00:00
}
2021-02-20 21:24:16 +00:00
if ( cfg . modeA == 2 ) {
// Large clock
drawClock ( ) ;
}
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
2021-01-31 08:59:22 +00:00
// Spd+Dist : Select next waypoint
2021-02-06 04:10:17 +00:00
setWatch ( function ( e ) {
var dur = e . time - e . lastTime ;
2021-02-20 21:24:16 +00:00
if ( cfg . modeA == 1 ) {
2021-02-06 04:10:17 +00:00
// 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.
}
2021-02-20 21:24:16 +00:00
if ( cfg . modeA == 0 ) nxtWp ( 1 ) ; // Spd+Dist mode - Select next waypoint
2021-02-06 04:10:17 +00:00
onGPS ( lf ) ;
2021-02-06 07:42:01 +00:00
} , BTN1 , { edge : "falling" , repeat : true } ) ;
2021-02-06 04:10:17 +00:00
2021-02-06 07:31:31 +00:00
// Power saving on/off
setWatch ( function ( e ) {
2021-02-12 00:53:08 +00:00
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 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 ) {
2021-02-20 21:24:16 +00:00
cfg . modeA = cfg . modeA + 1 ;
if ( cfg . modeA > 2 ) cfg . modeA = 0 ;
2021-02-06 07:31:31 +00:00
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 ) {
2021-02-12 01:09:11 +00:00
cfg . primSpd = ! cfg . primSpd ;
2021-02-06 07:31:31 +00:00
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-09 19:10:06 +00:00
if ( ! tmrLP ) tmrLP = setInterval ( function ( ) { if ( lf . fix ) setLpMode ( 'PSMOO' ) ; } , 10000 ) ; //Drop to low power in 10 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 ( ) {
2021-02-12 01:09:11 +00:00
require ( "Storage" ) . write ( 'speedalt.json' , cfg ) ;
2021-02-02 02:57:41 +00:00
}
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-12 00:53:08 +00:00
if ( ! gpssetup ) return ;
gpssetup . setPowerMode ( { power _mode : m } )
2021-02-06 08:45:54 +00:00
}
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.
2021-02-12 01:09:11 +00:00
let cfg = require ( 'Storage' ) . readJSON ( 'speedalt.json' , 1 ) || { } ;
2021-01-28 10:22:07 +00:00
2021-02-12 01:09:11 +00:00
cfg . spd = cfg . spd || 0 ; // Multiplier for speed unit conversions. 0 = use the locale values for speed
cfg . spd _unit = cfg . spd _unit || '' ; // Displayed speed unit
cfg . alt = cfg . alt || 0.3048 ; // Multiplier for altitude unit conversions.
cfg . alt _unit = cfg . alt _unit || 'feet' ; // Displayed altitude units
cfg . dist = cfg . dist || 1000 ; // Multiplier for distnce unit conversions.
cfg . dist _unit = cfg . dist _unit || 'km' ; // Displayed altitude units
cfg . colour = cfg . colour || 0 ; // Colour scheme.
cfg . wp = cfg . wp || 0 ; // Last selected waypoint for dist
2021-02-20 21:24:16 +00:00
cfg . modeA = cfg . modeA || 0 ; // 0 = [D]ist, 1 = [A]ltitude, 2 = [C]lock
2021-02-12 01:09:11 +00:00
cfg . primSpd = cfg . primSpd || 0 ; // 1 = Spd in primary, 0 = Spd in secondary
2021-02-02 02:57:41 +00:00
2021-02-01 21:40:27 +00:00
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-12 01:09:11 +00:00
if ( cfg . colour == 1 ) img . palette = new Uint16Array ( [ 0 , 0xFFFF , 0xFFF6 , 0xDFFF ] ) ;
if ( cfg . 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-02-12 00:53:08 +00:00
var gpssetup ;
try {
2021-02-12 19:50:57 +00:00
gpssetup = require ( "gpssetup" ) ;
2021-02-12 00:53:08 +00:00
} catch ( e ) {
gpssetup = false ;
}
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-12 00:53:08 +00:00
Bangle . setGPSPower ( 1 ) ;
2021-02-05 20:26:41 +00:00
2021-02-12 00:53:08 +00:00
if ( gpssetup ) {
gpssetup . setPowerMode ( { power _mode : "SuperE" } ) . then ( function ( ) { Bangle . setGPSPower ( 1 ) ; } ) ;
2021-02-05 20:17:33 +00:00
}
else {
Bangle . setGPSPower ( 1 ) ;
}
2021-02-05 20:26:41 +00:00
2021-02-12 00:53:08 +00:00
Bangle . on ( 'GPS' , onGPS ) ;
2021-01-21 02:42:19 +00:00
setButtons ( ) ;
2021-01-26 22:33:16 +00:00
setInterval ( updateClock , 30000 ) ;