BangleApps/apps/speedalt/app.js

491 lines
10 KiB
JavaScript
Raw Normal View History

2021-01-21 02:42:19 +00:00
/*
Speed and Altitude [speedalt]
Ver : 0.10
2021-01-26 22:33:16 +00:00
Mike Bennett mike[at]kereru.com
2021-01-21 02:42:19 +00:00
*/
2021-01-28 21:03:18 +00:00
const dbg = 0;
2021-01-26 22:33:16 +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-01-21 02:42:19 +00:00
var lastFix = {fix:0,satellites:0};
var primaryDisp = 1; // 1 = Speed in primary display. 0 = alt/dist in primary
var altDisp = 1; // 1 = alt, 0 = dist to wp
2021-01-26 22:33:16 +00:00
var showMax = 0; // 1 = display the max values. 0 = display the cur fix
var maxPress = 0; // Time max button pressed. Used to calculate short or long press.
2021-01-28 10:22:07 +00:00
var canDraw = 1;
2021-01-28 21:03:18 +00:00
var lastBuzz = 0; // What sort of buzz was last performed. 0 = no fix, 1 = fix.
var timerBuzz2 = 0; // ID of timer for fix second buzz
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-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-01-26 22:33:16 +00:00
var emulator = 0;
if (process.env.BOARD=="EMSCRIPTEN") emulator = 1; // 1 = running in emulator. Supplies test values;
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
var wpindex=0;
var wp = {}; // Waypoint to use for distance from cur position.
function nextwp(inc){
if (altDisp) return;
2021-01-31 04:33:49 +00:00
if ( showMax ) return;
wpindex+=inc;
if (wpindex>=waypoints.length) wpindex=0;
if (wpindex<0) wpindex = waypoints.length-1;
wp = waypoints[wpindex];
onGPS(lastFix);
}
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-01-26 22:33:16 +00:00
function drawFix(speed,units,sats,alt,alt_units) {
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-26 22:33:16 +00:00
var val = '';
var u='';
// Primary Display
val = speed.toString();
if ( !primaryDisp ) val = alt.toString();
2021-01-26 22:33:16 +00:00
// Primary Units
u = settings.spd_unit;
if ( !primaryDisp ) u = alt_units;
2021-01-26 22:33:16 +00:00
drawPrimary(val,u);
// Secondary Display
val = alt.toString();
if ( !primaryDisp ) val = speed.toString();
2021-01-26 22:33:16 +00:00
// Secondary Units
u = alt_units;
if ( !primaryDisp ) u = settings.spd_unit;
2021-01-26 22:33:16 +00:00
drawSecondary(val,u);
// Time
drawTime();
// Waypoint name
drawWP();
2021-01-26 22:33:16 +00:00
//Sats
drawSats(sats);
2021-01-28 10:22:07 +00:00
g.reset();
g.drawImage(img,0,40);
// g.flip();
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 drawNoFix(sats) {
2021-01-28 10:22:07 +00:00
if (!canDraw) return;
2021-01-26 22:33:16 +00:00
var u;
2021-01-28 10:22:07 +00:00
buf.clear();
2021-01-26 22:33:16 +00:00
buf.setFontAlign(0,0);
buf.setColor(3);
buf.setFontVector(25);
buf.drawString("Waiting for GPS",120,56);
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
// Time
drawTime();
//Sats
drawSats(sats);
2021-01-28 10:22:07 +00:00
g.reset();
g.drawImage(img,0,40);
// g.flip();
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
if ( n.length <= 7 ) s=48;
if ( n.length <= 6 ) s=55;
if ( n.length <= 5 ) s=68;
if ( n.length <= 4 ) s=85;
if ( n.length <= 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
if ( n.length <= 5 ) s=155;
if ( n.length <= 4 ) s=125;
if ( n.length <= 3 ) s=100;
if ( n.length <= 2 ) s=65;
if ( n.length <= 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;
if ( nm == undefined ) nm = '';
if ( nm == 'NONE' ) nm = '';
if ( altDisp ) nm='';
2021-01-31 04:33:49 +00:00
if ( showMax ) nm='';
buf.setFontAlign(-12,1); //left, bottom
buf.setColor(2);
// buf.setFont("6x8", 1);
buf.setFontVector(20);
buf.drawString(nm.substring(0,6),77,160);
}
2021-01-26 22:33:16 +00:00
function drawSats(sats) {
buf.setFontAlign(1,1); //right, bottom
buf.setColor(3);
2021-01-28 21:03:18 +00:00
buf.setFont("6x8", 2);
2021-01-26 22:33:16 +00:00
if ( showMax ) {
buf.setColor(2);
buf.drawString("MAX",240,160);
}
else buf.drawString("Sats:"+sats,240,160);
}
2021-01-21 02:42:19 +00:00
function onGPS(fix) {
lastFix = fix;
var m;
if (fix.fix || emulator) {
2021-01-28 21:03:18 +00:00
doBuzz(1);
2021-01-26 22:33:16 +00:00
2021-01-21 02:42:19 +00:00
//==== Speed ====
2021-01-26 22:33:16 +00:00
if ( settings.spd == 0 ) {
2021-01-21 02:42:19 +00:00
var strSpeed = require("locale").speed(fix.speed);
m = strSpeed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
if ( emulator ) {
speed = '125'; //testing only
2021-01-26 22:33:16 +00:00
settings.spd_unit = 'kph';
2021-01-21 02:42:19 +00:00
}
else {
speed = m[1];
2021-01-26 22:33:16 +00:00
settings.spd_unit = m[2];
2021-01-21 02:42:19 +00:00
}
}
// Calculate for selected units
else {
speed = fix.speed;
if ( emulator ) speed = '100';
speed = Math.round(parseFloat(speed)/parseFloat(settings.spd));
2021-01-21 02:42:19 +00:00
}
// ==== Altitude ====
alt = fix.alt;
if ( emulator ) alt = '360';
alt = Math.round(parseFloat(alt)/parseFloat(settings.alt));
// ==== Distance to waypoint ====
if ( emulator ) {
lastFix.lat = -38.92;
lastFix.lon = 175.7613350;
}
dist = distance(lastFix,wp);
if (isNaN(dist)) dist = 0;
2021-01-26 22:33:16 +00:00
// Record max values
if (parseFloat(speed) > parseFloat(max.spd) ) max.spd = parseFloat(speed);
if (parseFloat(alt) > parseFloat(max.alt) ) max.alt = parseFloat(alt);
2021-01-21 02:42:19 +00:00
if ( showMax ) {
// Speed and alt maximums
drawFix(max.spd,settings.spd_unit,fix.satellites,max.alt,settings.alt_unit);
}
else {
if ( altDisp ) {
// Show speed/altitude
drawFix(speed,settings.spd_unit,fix.satellites,alt,settings.alt_unit);
}
else {
// Show speed/distance
if ( dist <= 0 ) {
// No WP selected
drawFix(speed,settings.spd_unit,fix.satellites,'','');
}
else {
drawFix(speed,settings.spd_unit,fix.satellites,dist,settings.dist_unit);
}
}
}
2021-01-21 02:42:19 +00:00
}
else {
2021-01-28 21:03:18 +00:00
doBuzz(0);
2021-01-21 02:42:19 +00:00
drawNoFix(fix.satellites);
}
2021-01-28 10:22:07 +00:00
2021-01-21 02:42:19 +00:00
}
2021-01-28 21:03:18 +00:00
// Vibrate watch when fix lost or gained.
function doBuzz(hasFix) {
// nothing to do
2021-01-29 00:55:06 +00:00
if ( lastBuzz === hasFix || !settings.buzz ) {
2021-01-28 21:03:18 +00:00
return;
}
// fix gained - double buzz
if ( !lastBuzz && hasFix ) {
if ( dbg ) print('Fix');
2021-01-28 21:29:33 +00:00
lastBuzz = 1;
2021-01-28 21:03:18 +00:00
Bangle.buzz();
2021-01-29 00:55:06 +00:00
timerBuzz2 = setInterval(doBuzz2, 600); // Trigger a second buzz
2021-01-28 21:03:18 +00:00
return;
}
// fix lost - single buzz
if ( lastBuzz && !hasFix ) {
if ( dbg ) print('Fix lost');
2021-01-28 21:15:39 +00:00
lastBuzz = 0;
2021-01-28 21:29:33 +00:00
Bangle.buzz();
2021-01-28 21:03:18 +00:00
return;
}
}
// Second buzz
function doBuzz2() {
if ( dbg ) print('Buzz2');
clearInterval(timerBuzz2);
Bangle.buzz();
}
2021-01-21 02:42:19 +00:00
function toggleDisplay() {
primaryDisp = !primaryDisp;
onGPS(lastFix); // Update display
}
function toggleAltDist() {
altDisp = !altDisp;
onGPS(lastFix);
2021-01-26 22:33:16 +00:00
}
function toggleMax() {
// if ( inMenu ) return;
showMax = !showMax;
onGPS(lastFix);
2021-01-21 02:42:19 +00:00
}
function setButtons(){
2021-01-26 22:33:16 +00:00
2021-01-28 21:15:39 +00:00
// Switch between fix and max display on short press or reset max values on long press
setWatch(maxPressed, BTN1,{repeat:true,edge:"rising"});
setWatch(maxReleased, BTN1,{repeat:true,edge:"falling"});
2021-01-26 22:33:16 +00:00
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Select a waypoint for dist display
setWatch(nextwp.bind(this,1), BTN3, {repeat:true,edge:"falling"});
// Touch left screen to toggle display
2021-01-26 22:33:16 +00:00
setWatch(toggleDisplay, BTN4, {repeat:true,edge:"falling"});
// Touch left screen to toggle between alt or dist
setWatch(toggleAltDist, BTN5, {repeat:true,edge:"falling"});
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 maxPressed() {
maxPress = getTime();
2021-01-21 02:42:19 +00:00
}
2021-01-26 22:33:16 +00:00
function maxReleased() {
var dur = getTime()-maxPress;
if ( dur < 2 ) toggleMax(); // Short press toggle fix/max display
else {
max.spd = 0; // Long press resets max values.
max.alt = 0;
onGPS(lastFix); // redraw display
}
}
2021-01-21 02:42:19 +00:00
2021-01-26 22:33:16 +00:00
function updateClock() {
if ( dbg ) print('Updating clock');
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-01-28 10:22:07 +00:00
// g.flip();
2021-01-26 22:33:16 +00:00
// Something different to display in the emulator
if ( emulator ) {
max.spd++;
max.alt++;
}
}
2021-01-28 10:22:07 +00:00
function startDraw(){
canDraw=true;
g.clear();
Bangle.drawWidgets();
onGPS(lastFix); // draw app screen
}
function stopDraw() {
canDraw=false;
}
// ===== Main Prog =====
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
2021-01-26 22:33:16 +00:00
settings.colour = settings.colour||0; // Colour scheme.
2021-01-29 02:11:44 +00:00
settings.buzz = settings.buzz||0; // Buzz when fix lost or gained.
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(),
bpp:2,
buffer:buf.buffer,
palette:new Uint16Array([0,0x4FE0,0xEFE0,0x07DB])
};
if ( settings.colour == 1 ) img.palette = new Uint16Array([0,0xFFFF,0xFFFF,0xFFFF]);
if ( settings.colour == 2 ) img.palette = new Uint16Array([0,0xFF800,0xF800,0xF800]);
// Find speed unit if using locale speed
if ( settings.spd == 0 ) {
var strSpeed = require("locale").speed(1);
m = strSpeed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
settings.spd_unit = m[2];
}
2021-01-28 10:22:07 +00:00
var SCREENACCESS = {
withApp:true,
request:function(){
this.withApp=false;
stopDraw();
clearWatch();
},
release:function(){
this.withApp=true;
startDraw();
setButtons();
}
};
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;
if (on) {
startDraw();
} else {
stopDraw();
}
});
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-28 10:22:07 +00:00
Bangle.setLCDBrightness(1);
2021-01-21 02:42:19 +00:00
Bangle.loadWidgets();
Bangle.drawWidgets();
Bangle.setGPSPower(1);
2021-01-28 10:22:07 +00:00
2021-01-28 21:03:18 +00:00
onGPS(lastFix);
2021-01-28 10:22:07 +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);