BangleApps/apps/gpsnav/app.js

250 lines
5.7 KiB
JavaScript

const Yoff = 40;
var pal2color = new Uint16Array([0x0000,0xffff,0x07ff,0xC618],0,2);
var buf = Graphics.createArrayBuffer(240,50,2,{msb:true});
var candraw = true;
function flip(b,y) {
g.drawImage({width:240,height:50,bpp:2,buffer:b.buffer, palette:pal2color},0,y);
b.clear();
}
var brg=0;
var wpindex=0;
const labels = ["N","NE","E","SE","S","SW","W","NW"];
function drawCompass(course) {
if (!candraw) return;
buf.setColor(1);
buf.setFont("Vector",16);
var start = course-90;
if (start<0) start+=360;
buf.fillRect(28,45,212,49);
var xpos = 30;
var frag = 15 - start%15;
if (frag<15) xpos+=frag; else frag = 0;
for (var i=frag;i<=180-frag;i+=15){
var res = start + i;
if (res%90==0) {
buf.drawString(labels[Math.floor(res/45)%8],xpos-8,0);
buf.fillRect(xpos-2,25,xpos+2,45);
} else if (res%45==0) {
buf.drawString(labels[Math.floor(res/45)%8],xpos-12,0);
buf.fillRect(xpos-2,30,xpos+2,45);
} else if (res%15==0) {
buf.fillRect(xpos,35,xpos+1,45);
}
xpos+=15;
}
if (wpindex!=0) {
var bpos = brg - course;
if (bpos>180) bpos -=360;
if (bpos<-180) bpos +=360;
bpos+=120;
if (bpos<30) bpos = 14;
if (bpos>210) bpos = 226;
buf.setColor(2);
buf.fillCircle(bpos,40,8);
}
flip(buf,Yoff);
}
//displayed heading
var heading = 0;
function newHeading(m,h){
var s = Math.abs(m - h);
var delta = 1;
if (s<2) return h;
if (m > h){
if (s >= 180) { delta = -1; s = 360 - s;}
} else if (m <= h){
if (s < 180) delta = -1;
else s = 360 -s;
}
delta = delta * (1 + Math.round(s/15));
heading+=delta;
if (heading<0) heading += 360;
if (heading>360) heading -= 360;
return heading;
}
var course =0;
var speed = 0;
var satellites = 0;
var wp;
var dist=0;
function radians(a) {
return a*Math.PI/180;
}
function degrees(a) {
var d = a*180/Math.PI;
return (d+360)%360;
}
function bearing(a,b){
var delta = radians(b.lon-a.lon);
var alat = radians(a.lat);
var blat = radians(b.lat);
var y = Math.sin(delta) * Math.cos(blat);
var x = Math.cos(alat)*Math.sin(blat) -
Math.sin(alat)*Math.cos(blat)*Math.cos(delta);
return Math.round(degrees(Math.atan2(y, x)));
}
function distance(a,b){
var dsigma = Math.acos(Math.sin(radians(a.lat))*Math.sin(radians(b.lat))+Math.cos(radians(a.lat))*Math.cos(radians(b.lat))*Math.cos(radians(a.lon-b.lon)));
return Math.round(dsigma*6371000);
}
var selected = false;
function drawN(){
buf.setColor(1);
buf.setFont("6x8",2);
buf.drawString("o",100,0);
buf.setFont("6x8",1);
buf.drawString("kph",220,40);
buf.setFont("Vector",40);
var cs = course.toString();
cs = course<10?"00"+cs : course<100 ?"0"+cs : cs;
buf.drawString(cs,10,0);
var txt = (speed<10) ? speed.toFixed(1) : Math.round(speed);
buf.drawString(txt,140,4);
flip(buf,Yoff+70);
buf.setColor(1);
buf.setFont("Vector",20);
var bs = brg.toString();
bs = brg<10?"00"+bs : brg<100 ?"0"+bs : bs;
buf.setColor(3);
buf.drawString("Brg: ",0,0);
buf.drawString("Dist: ",0,30);
buf.setColor(selected?1:2);
buf.drawString(wp.name,140,0);
buf.setColor(1);
buf.drawString(bs,60,0);
if (dist<1000)
buf.drawString(dist.toString()+"m",60,30);
else
buf.drawString((dist/1000).toFixed(2)+"Km",60,30);
flip(buf,Yoff+130);
g.setFont("6x8",1);
g.setColor(0,0,0);
g.fillRect(10,230,60,239);
g.setColor(1,1,1);
g.drawString("Sats " + satellites.toString(),10,230);
}
var savedfix;
function onGPS(fix) {
savedfix = fix;
if (fix!==undefined){
course = isNaN(fix.course) ? course : Math.round(fix.course);
speed = isNaN(fix.speed) ? speed : fix.speed;
satellites = fix.satellites;
}
if (candraw) {
if (fix!==undefined && fix.fix==1){
dist = distance(fix,wp);
if (isNaN(dist)) dist = 0;
brg = bearing(fix,wp);
if (isNaN(brg)) brg = 0;
}
drawN();
}
}
var intervalRef;
function stopdraw() {
candraw=false;
if(intervalRef) {clearInterval(intervalRef);}
}
function startTimers() {
candraw=true;
intervalRefSec = setInterval(function() {
newHeading(course,heading);
if (course!=heading) drawCompass(heading);
},200);
}
function drawAll(){
g.setColor(1,0.5,0.5);
g.fillPoly([120,Yoff+50,110,Yoff+70,130,Yoff+70]);
g.setColor(1,1,1);
drawN();
drawCompass(heading);
}
function startdraw(){
g.clear();
Bangle.drawWidgets();
startTimers();
drawAll();
}
function setButtons(){
setWatch(nextwp.bind(null,-1), BTN1, {repeat:true,edge:"falling"});
setWatch(doselect, BTN2, {repeat:true,edge:"falling"});
setWatch(nextwp.bind(null,1), BTN3, {repeat:true,edge:"falling"});
}
var SCREENACCESS = {
withApp:true,
request:function(){
this.withApp=false;
stopdraw();
clearWatch();
},
release:function(){
this.withApp=true;
startdraw();
setButtons();
}
}
Bangle.on('lcdPower',function(on) {
if (!SCREENACCESS.withApp) return;
if (on) {
startdraw();
} else {
stopdraw();
}
});
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
wp=waypoints[0];
function nextwp(inc){
if (!selected) return;
wpindex+=inc;
if (wpindex>=waypoints.length) wpindex=0;
if (wpindex<0) wpindex = waypoints.length-1;
wp = waypoints[wpindex];
drawN();
}
function doselect(){
if (selected && waypoints[wpindex].lat===undefined && savedfix.fix) {
waypoints[wpindex] ={name:"@"+wp.name, lat:savedfix.lat, lon:savedfix.lon};
wp = waypoints[wpindex];
require("Storage").writeJSON("waypoints.json", waypoints);
}
selected=!selected;
drawN();
}
g.clear();
Bangle.setLCDBrightness(1);
Bangle.loadWidgets();
Bangle.drawWidgets();
// load widgets can turn off GPS
Bangle.setGPSPower(1);
drawAll();
startTimers();
Bangle.on('GPS', onGPS);
// Toggle selected
setButtons();