Merge pull request #2255 from halemmerich/gpstrek

gpstrek - Improvements
master
Gordon Williams 2022-11-11 15:20:16 +00:00 committed by GitHub
commit aa7c38a08c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 355 additions and 262 deletions

View File

@ -8,3 +8,8 @@
Fix widget adding listeners more than once Fix widget adding listeners more than once
0.07: Show checkered flag for target markers 0.07: Show checkered flag for target markers
Single waypoints are now shown in the compass view Single waypoints are now shown in the compass view
0.08: Better handle state in widget
Slightly faster drawing by doing some caching
Reconstruct battery voltage by using calibrated batFullVoltage
Averaging for smoothing compass headings
Save state if route or waypoint has been chosen

View File

@ -1,48 +1,69 @@
{ //run in own scope for fast switch
const STORAGE = require("Storage"); const STORAGE = require("Storage");
const showWidgets = true; const BAT_FULL = require("Storage").readJSON("setting.json").batFullVoltage || 0.3144;
let numberOfSlices=4;
let init = function(){
global.screen = 1;
global.drawTimeout = undefined;
global.lastDrawnScreen = 0;
global.firstDraw = true;
global.slices = [];
global.maxScreens = 1;
global.scheduleDraw = false;
if (showWidgets){
Bangle.loadWidgets(); Bangle.loadWidgets();
} WIDGETS.gpstrek.start(false);
if (!WIDGETS.gpstrek.getState().numberOfSlices) WIDGETS.gpstrek.getState().numberOfSlices = 3;
};
let state = WIDGETS.gpstrek.getState(); let cleanup = function(){
WIDGETS.gpstrek.start(false); if (global.drawTimeout) clearTimeout(global.drawTimeout);
delete global.screen;
delete global.drawTimeout;
delete global.lastDrawnScreen;
delete global.firstDraw;
delete global.slices;
delete global.maxScreens;
};
function parseNumber(toParse){ init();
scheduleDraw = true;
let parseNumber = function(toParse){
if (toParse.includes(".")) return parseFloat(toParse); if (toParse.includes(".")) return parseFloat(toParse);
return parseFloat("" + toParse + ".0"); return parseFloat("" + toParse + ".0");
} };
function parseWaypoint(filename, offset, result){ let parseWaypoint = function(filename, offset, result){
result.lat = parseNumber(STORAGE.read(filename, offset, 11)); result.lat = parseNumber(STORAGE.read(filename, offset, 11));
result.lon = parseNumber(STORAGE.read(filename, offset += 11, 12)); result.lon = parseNumber(STORAGE.read(filename, offset += 11, 12));
return offset + 12; return offset + 12;
} };
function parseWaypointWithElevation(filename, offset, result){ let parseWaypointWithElevation = function (filename, offset, result){
offset = parseWaypoint(filename, offset, result); offset = parseWaypoint(filename, offset, result);
result.alt = parseNumber(STORAGE.read(filename, offset, 6)); result.alt = parseNumber(STORAGE.read(filename, offset, 6));
return offset + 6; return offset + 6;
} };
function parseWaypointWithName(filename, offset, result){ let parseWaypointWithName = function(filename, offset, result){
offset = parseWaypoint(filename, offset, result); offset = parseWaypoint(filename, offset, result);
return parseName(filename, offset, result); return parseName(filename, offset, result);
} };
function parseName(filename, offset, result){ let parseName = function(filename, offset, result){
let nameLength = STORAGE.read(filename, offset, 2) - 0; let nameLength = STORAGE.read(filename, offset, 2) - 0;
result.name = STORAGE.read(filename, offset += 2, nameLength); result.name = STORAGE.read(filename, offset += 2, nameLength);
return offset + nameLength; return offset + nameLength;
} };
function parseWaypointWithElevationAndName(filename, offset, result){ let parseWaypointWithElevationAndName = function(filename, offset, result){
offset = parseWaypointWithElevation(filename, offset, result); offset = parseWaypointWithElevation(filename, offset, result);
return parseName(filename, offset, result); return parseName(filename, offset, result);
} };
function getEntry(filename, offset, result){ let getEntry = function(filename, offset, result){
result.fileOffset = offset; result.fileOffset = offset;
let type = STORAGE.read(filename, offset++, 1); let type = STORAGE.read(filename, offset++, 1);
if (type == "") return -1; if (type == "") return -1;
@ -68,12 +89,12 @@ function getEntry(filename, offset, result){
result.fileLength = offset - result.fileOffset; result.fileLength = offset - result.fileOffset;
//print(result); //print(result);
return offset; return offset;
} };
const labels = ["N","NE","E","SE","S","SW","W","NW"]; const labels = ["N","NE","E","SE","S","SW","W","NW"];
const loc = require("locale"); const loc = require("locale");
function matchFontSize(graphics, text, height, width){ let matchFontSize = function(graphics, text, height, width){
graphics.setFontVector(height); graphics.setFontVector(height);
let metrics; let metrics;
let size = 1; let size = 1;
@ -81,13 +102,19 @@ function matchFontSize(graphics, text, height, width){
size -= 0.05; size -= 0.05;
graphics.setFont("Vector",Math.floor(height*size)); graphics.setFont("Vector",Math.floor(height*size));
} }
} };
function getDoubleLineSlice(title1,title2,provider1,provider2,refreshTime){ let getDoubleLineSlice = function(title1,title2,provider1,provider2,refreshTime){
let lastDrawn = Date.now() - Math.random()*refreshTime; let lastDrawn = Date.now() - Math.random()*refreshTime;
let lastValue1 = 0;
let lastValue2 = 0;
return { return {
refresh: function (){ refresh: function (){
return Date.now() - lastDrawn > (Bangle.isLocked()?(refreshTime?refreshTime:5000):(refreshTime?refreshTime*2:10000)); let bigChange1 = (Math.abs(lastValue1 - provider1()) > 1);
let bigChange2 = (Math.abs(lastValue2 - provider2()) > 1);
let refresh = (Bangle.isLocked()?(refreshTime?refreshTime*5:10000):(refreshTime?refreshTime*2:1000));
let old = (Date.now() - lastDrawn) > refresh;
return (bigChange1 || bigChange2) && old;
}, },
draw: function (graphics, x, y, height, width){ draw: function (graphics, x, y, height, width){
lastDrawn = Date.now(); lastDrawn = Date.now();
@ -95,29 +122,29 @@ function getDoubleLineSlice(title1,title2,provider1,provider2,refreshTime){
if (typeof title2 == "function") title2 = title2(); if (typeof title2 == "function") title2 = title2();
graphics.clearRect(x,y,x+width,y+height); graphics.clearRect(x,y,x+width,y+height);
let value = provider1(); lastValue1 = provider1();
matchFontSize(graphics, title1 + value, Math.floor(height*0.5), width); matchFontSize(graphics, title1 + lastValue1, Math.floor(height*0.5), width);
graphics.setFontAlign(-1,-1); graphics.setFontAlign(-1,-1);
graphics.drawString(title1, x+2, y); graphics.drawString(title1, x+2, y);
graphics.setFontAlign(1,-1); graphics.setFontAlign(1,-1);
graphics.drawString(value, x+width, y); graphics.drawString(lastValue1, x+width, y);
value = provider2(); lastValue2 = provider2();
matchFontSize(graphics, title2 + value, Math.floor(height*0.5), width); matchFontSize(graphics, title2 + lastValue2, Math.floor(height*0.5), width);
graphics.setFontAlign(-1,-1); graphics.setFontAlign(-1,-1);
graphics.drawString(title2, x+2, y+(height*0.5)); graphics.drawString(title2, x+2, y+(height*0.5));
graphics.setFontAlign(1,-1); graphics.setFontAlign(1,-1);
graphics.drawString(value, x+width, y+(height*0.5)); graphics.drawString(lastValue2, x+width, y+(height*0.5));
} }
}; };
} };
function getTargetSlice(targetDataSource){ let getTargetSlice = function(targetDataSource){
let nameIndex = 0; let nameIndex = 0;
let lastDrawn = Date.now() - Math.random()*3000; let lastDrawn = Date.now() - Math.random()*3000;
return { return {
refresh: function (){ refresh: function (){
return Date.now() - lastDrawn > (Bangle.isLocked()?10000:3000); return Date.now() - lastDrawn > (Bangle.isLocked()?3000:10000);
}, },
draw: function (graphics, x, y, height, width){ draw: function (graphics, x, y, height, width){
lastDrawn = Date.now(); lastDrawn = Date.now();
@ -174,9 +201,9 @@ function getTargetSlice(targetDataSource){
} }
} }
}; };
} };
function drawCompass(graphics, x, y, height, width, increment, start){ let drawCompass = function(graphics, x, y, height, width, increment, start){
graphics.setFont12x20(); graphics.setFont12x20();
graphics.setFontAlign(0,-1); graphics.setFontAlign(0,-1);
graphics.setColor(graphics.theme.fg); graphics.setColor(graphics.theme.fg);
@ -197,14 +224,19 @@ function drawCompass(graphics, x, y, height, width, increment, start){
xpos+=increment*15; xpos+=increment*15;
if (xpos > width + 20) break; if (xpos > width + 20) break;
} }
} };
function getCompassSlice(compassDataSource){ let getCompassSlice = function(compassDataSource){
let lastDrawn = Date.now() - Math.random()*2000; let lastDrawn = Date.now() - Math.random()*2000;
let lastDrawnValue = 0;
const buffers = 4; const buffers = 4;
let buf = []; let buf = [];
return { return {
refresh : function (){return Bangle.isLocked()?(Date.now() - lastDrawn > 2000):true;}, refresh : function (){
let bigChange = (Math.abs(lastDrawnValue - compassDataSource.getCourse()) > 2);
let old = (Bangle.isLocked()?(Date.now() - lastDrawn > 2000):true);
return bigChange && old;
},
draw: function (graphics, x,y,height,width){ draw: function (graphics, x,y,height,width){
lastDrawn = Date.now(); lastDrawn = Date.now();
const max = 180; const max = 180;
@ -212,12 +244,14 @@ function getCompassSlice(compassDataSource){
graphics.clearRect(x,y,x+width,y+height); graphics.clearRect(x,y,x+width,y+height);
var start = compassDataSource.getCourse() - 90; lastDrawnValue = compassDataSource.getCourse();
if (isNaN(compassDataSource.getCourse())) start = -90;
var start = lastDrawnValue - 90;
if (isNaN(lastDrawnValue)) start = -90;
if (start<0) start+=360; if (start<0) start+=360;
start = start % 360; start = start % 360;
if (state.acc && compassDataSource.getCourseType() == "MAG"){ if (WIDGETS.gpstrek.getState().acc && compassDataSource.getCourseType() == "MAG"){
drawCompass(graphics,0,y+width*0.05,height-width*0.05,width,increment,start); drawCompass(graphics,0,y+width*0.05,height-width*0.05,width,increment,start);
} else { } else {
drawCompass(graphics,0,y,height,width,increment,start); drawCompass(graphics,0,y,height,width,increment,start);
@ -226,7 +260,8 @@ function getCompassSlice(compassDataSource){
if (compassDataSource.getPoints){ if (compassDataSource.getPoints){
for (let p of compassDataSource.getPoints()){ for (let p of compassDataSource.getPoints()){
var bpos = p.bearing - compassDataSource.getCourse(); g.reset();
var bpos = p.bearing - lastDrawnValue;
if (bpos>180) bpos -=360; if (bpos>180) bpos -=360;
if (bpos<-180) bpos +=360; if (bpos<-180) bpos +=360;
bpos+=120; bpos+=120;
@ -251,6 +286,7 @@ function getCompassSlice(compassDataSource){
} }
if (compassDataSource.getMarkers){ if (compassDataSource.getMarkers){
for (let m of compassDataSource.getMarkers()){ for (let m of compassDataSource.getMarkers()){
g.reset();
g.setColor(m.fillcolor); g.setColor(m.fillcolor);
let mpos = m.xpos * width; let mpos = m.xpos * width;
if (m.xpos < 0.05) mpos = Math.floor(width*0.05); if (m.xpos < 0.05) mpos = Math.floor(width*0.05);
@ -263,9 +299,9 @@ function getCompassSlice(compassDataSource){
graphics.setColor(g.theme.fg); graphics.setColor(g.theme.fg);
graphics.fillRect(x,y,Math.floor(width*0.05),y+height); graphics.fillRect(x,y,Math.floor(width*0.05),y+height);
graphics.fillRect(Math.ceil(width*0.95),y,width,y+height); graphics.fillRect(Math.ceil(width*0.95),y,width,y+height);
if (state.acc && compassDataSource.getCourseType() == "MAG") { if (WIDGETS.gpstrek.getState().acc && compassDataSource.getCourseType() == "MAG") {
let xh = E.clip(width*0.5-height/2+(((state.acc.x+1)/2)*height),width*0.5 - height/2, width*0.5 + height/2); let xh = E.clip(width*0.5-height/2+(((WIDGETS.gpstrek.getState().acc.x+1)/2)*height),width*0.5 - height/2, width*0.5 + height/2);
let yh = E.clip(y+(((state.acc.y+1)/2)*height),y,y+height); let yh = E.clip(y+(((WIDGETS.gpstrek.getState().acc.y+1)/2)*height),y,y+height);
graphics.fillRect(width*0.5 - height/2, y, width*0.5 + height/2, y + Math.floor(width*0.05)); graphics.fillRect(width*0.5 - height/2, y, width*0.5 + height/2, y + Math.floor(width*0.05));
@ -287,44 +323,48 @@ function getCompassSlice(compassDataSource){
graphics.drawRect(Math.floor(width*0.05),y,Math.ceil(width*0.95),y+height); graphics.drawRect(Math.floor(width*0.05),y,Math.ceil(width*0.95),y+height);
} }
}; };
} };
function radians(a) { let radians = function(a) {
return a*Math.PI/180; return a*Math.PI/180;
} };
function degrees(a) { let degrees = function(a) {
var d = a*180/Math.PI; let d = a*180/Math.PI;
return (d+360)%360; return (d+360)%360;
} };
function bearing(a,b){ let bearing = function(a,b){
if (!a || !b || !a.lon || !a.lat || !b.lon || !b.lat) return Infinity; if (!a || !b || !a.lon || !a.lat || !b.lon || !b.lat) return Infinity;
var delta = radians(b.lon-a.lon); let delta = radians(b.lon-a.lon);
var alat = radians(a.lat); let alat = radians(a.lat);
var blat = radians(b.lat); let blat = radians(b.lat);
var y = Math.sin(delta) * Math.cos(blat); let y = Math.sin(delta) * Math.cos(blat);
var x = Math.cos(alat)*Math.sin(blat) - let x = Math.cos(alat)*Math.sin(blat) -
Math.sin(alat)*Math.cos(blat)*Math.cos(delta); Math.sin(alat)*Math.cos(blat)*Math.cos(delta);
return Math.round(degrees(Math.atan2(y, x))); return Math.round(degrees(Math.atan2(y, x)));
} };
function distance(a,b){ let distance = function(a,b){
if (!a || !b || !a.lon || !a.lat || !b.lon || !b.lat) return Infinity; if (!a || !b || !a.lon || !a.lat || !b.lon || !b.lat) return Infinity;
var x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2)); let x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2));
var y = radians(b.lat-a.lat); let y = radians(b.lat-a.lat);
return Math.round(Math.sqrt(x*x + y*y) * 6371000); return Math.round(Math.sqrt(x*x + y*y) * 6371000);
} };
function triangle (x, y, width, height){ let getAveragedCompass = function(){
return Math.round(WIDGETS.gpstrek.getState().avgComp);
};
let triangle = function(x, y, width, height){
return [ return [
Math.round(x),Math.round(y), Math.round(x),Math.round(y),
Math.round(x+width * 0.5), Math.round(y+height), Math.round(x+width * 0.5), Math.round(y+height),
Math.round(x-width * 0.5), Math.round(y+height) Math.round(x-width * 0.5), Math.round(y+height)
]; ];
} };
function onSwipe(dir){ let onSwipe = function(dir){
if (dir < 0) { if (dir < 0) {
nextScreen(); nextScreen();
} else if (dir > 0) { } else if (dir > 0) {
@ -332,9 +372,9 @@ function onSwipe(dir){
} else { } else {
nextScreen(); nextScreen();
} }
} };
function setButtons(){ let setButtons = function(){
let options = { let options = {
mode: "custom", mode: "custom",
swipe: onSwipe, swipe: onSwipe,
@ -342,9 +382,9 @@ function setButtons(){
touch: nextScreen touch: nextScreen
}; };
Bangle.setUI(options); Bangle.setUI(options);
} };
function getApproxFileSize(name){ let getApproxFileSize = function(name){
let currentStart = STORAGE.getStats().totalBytes; let currentStart = STORAGE.getStats().totalBytes;
let currentSize = 0; let currentSize = 0;
for (let i = currentStart; i > 500; i/=2){ for (let i = currentStart; i > 500; i/=2){
@ -358,9 +398,9 @@ function getApproxFileSize(name){
currentSize += currentDiff; currentSize += currentDiff;
} }
return currentSize; return currentSize;
} };
function parseRouteData(filename, progressMonitor){ let parseRouteData = function(filename, progressMonitor){
let routeInfo = {}; let routeInfo = {};
routeInfo.filename = filename; routeInfo.filename = filename;
@ -406,40 +446,40 @@ function parseRouteData(filename, progressMonitor){
set(routeInfo, 0); set(routeInfo, 0);
return routeInfo; return routeInfo;
} };
function hasPrev(route){ let hasPrev = function(route){
if (route.mirror) return route.index < (route.count - 1); if (route.mirror) return route.index < (route.count - 1);
return route.index > 0; return route.index > 0;
} };
function hasNext(route){ let hasNext = function(route){
if (route.mirror) return route.index > 0; if (route.mirror) return route.index > 0;
return route.index < (route.count - 1); return route.index < (route.count - 1);
} };
function next(route){ let next = function(route){
if (!hasNext(route)) return; if (!hasNext(route)) return;
if (route.mirror) set(route, --route.index); if (route.mirror) set(route, --route.index);
if (!route.mirror) set(route, ++route.index); if (!route.mirror) set(route, ++route.index);
} };
function set(route, index){ let set = function(route, index){
route.currentWaypoint = {}; route.currentWaypoint = {};
route.index = index; route.index = index;
getEntry(route.filename, route.refs[index], route.currentWaypoint); getEntry(route.filename, route.refs[index], route.currentWaypoint);
} };
function prev(route){ let prev = function(route){
if (!hasPrev(route)) return; if (!hasPrev(route)) return;
if (route.mirror) set(route, ++route.index); if (route.mirror) set(route, ++route.index);
if (!route.mirror) set(route, --route.index); if (!route.mirror) set(route, --route.index);
} };
let lastMirror; let lastMirror;
let cachedLast; let cachedLast;
function getLast(route){ let getLast = function(route){
let wp = {}; let wp = {};
if (lastMirror != route.mirror){ if (lastMirror != route.mirror){
if (route.mirror) getEntry(route.filename, route.refs[0], wp); if (route.mirror) getEntry(route.filename, route.refs[0], wp);
@ -448,14 +488,14 @@ function getLast(route){
cachedLast = wp; cachedLast = wp;
} }
return cachedLast; return cachedLast;
} };
function removeMenu(){ let removeMenu = function(){
E.showMenu(); E.showMenu();
switchNav(); switchNav();
} };
function showProgress(progress, title, max){ let showProgress = function(progress, title, max){
//print("Progress",progress,max) //print("Progress",progress,max)
let message = title? title: "Loading"; let message = title? title: "Loading";
if (max){ if (max){
@ -466,17 +506,17 @@ function showProgress(progress, title, max){
for (let i = dots; i < 4; i++) message += " "; for (let i = dots; i < 4; i++) message += " ";
} }
E.showMessage(message); E.showMessage(message);
} };
function handleLoading(c){ let handleLoading = function(c){
E.showMenu(); E.showMenu();
state.route = parseRouteData(c, showProgress); WIDGETS.gpstrek.getState().route = parseRouteData(c, showProgress);
state.waypoint = null; WIDGETS.gpstrek.getState().waypoint = null;
WIDGETS.gpstrek.getState().route.mirror = false;
removeMenu(); removeMenu();
state.route.mirror = false; };
}
function showRouteSelector (){ let showRouteSelector = function(){
var menu = { var menu = {
"" : { "" : {
back : showRouteMenu, back : showRouteMenu,
@ -488,9 +528,9 @@ function showRouteSelector (){
}); });
E.showMenu(menu); E.showMenu(menu);
} };
function showRouteMenu(){ let showRouteMenu = function(){
var menu = { var menu = {
"" : { "" : {
"title" : "Route", "title" : "Route",
@ -499,48 +539,48 @@ function showRouteMenu(){
"Select file" : showRouteSelector "Select file" : showRouteSelector
}; };
if (state.route){ if (WIDGETS.gpstrek.getState().route){
menu.Mirror = { menu.Mirror = {
value: state && state.route && !!state.route.mirror || false, value: WIDGETS.gpstrek.getState() && WIDGETS.gpstrek.getState().route && !!WIDGETS.gpstrek.getState().route.mirror || false,
onchange: v=>{ onchange: v=>{
state.route.mirror = v; WIDGETS.gpstrek.getState().route.mirror = v;
} }
}; };
menu['Select closest waypoint'] = function () { menu['Select closest waypoint'] = function () {
if (state.currentPos && state.currentPos.lat){ if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lat){
setClosestWaypoint(state.route, null, showProgress); removeMenu(); setClosestWaypoint(WIDGETS.gpstrek.getState().route, null, showProgress); removeMenu();
} else { } else {
E.showAlert("No position").then(()=>{E.showMenu(menu);}); E.showAlert("No position").then(()=>{E.showMenu(menu);});
} }
}; };
menu['Select closest waypoint (not visited)'] = function () { menu['Select closest waypoint (not visited)'] = function () {
if (state.currentPos && state.currentPos.lat){ if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lat){
setClosestWaypoint(state.route, state.route.index, showProgress); removeMenu(); setClosestWaypoint(WIDGETS.gpstrek.getState().route, WIDGETS.gpstrek.getState().route.index, showProgress); removeMenu();
} else { } else {
E.showAlert("No position").then(()=>{E.showMenu(menu);}); E.showAlert("No position").then(()=>{E.showMenu(menu);});
} }
}; };
menu['Select waypoint'] = { menu['Select waypoint'] = {
value : state.route.index, value : WIDGETS.gpstrek.getState().route.index,
min:1,max:state.route.count,step:1, min:1,max:WIDGETS.gpstrek.getState().route.count,step:1,
onchange : v => { set(state.route, v-1); } onchange : v => { set(WIDGETS.gpstrek.getState().route, v-1); }
}; };
menu['Select waypoint as current position'] = function (){ menu['Select waypoint as current position'] = function (){
state.currentPos.lat = state.route.currentWaypoint.lat; WIDGETS.gpstrek.getState().currentPos.lat = WIDGETS.gpstrek.getState().route.currentWaypoint.lat;
state.currentPos.lon = state.route.currentWaypoint.lon; WIDGETS.gpstrek.getState().currentPos.lon = WIDGETS.gpstrek.getState().route.currentWaypoint.lon;
state.currentPos.alt = state.route.currentWaypoint.alt; WIDGETS.gpstrek.getState().currentPos.alt = WIDGETS.gpstrek.getState().route.currentWaypoint.alt;
removeMenu(); removeMenu();
}; };
} }
if (state.route && hasPrev(state.route)) if (WIDGETS.gpstrek.getState().route && hasPrev(WIDGETS.gpstrek.getState().route))
menu['Previous waypoint'] = function() { prev(state.route); removeMenu(); }; menu['Previous waypoint'] = function() { prev(WIDGETS.gpstrek.getState().route); removeMenu(); };
if (state.route && hasNext(state.route)) if (WIDGETS.gpstrek.getState().route && hasNext(WIDGETS.gpstrek.getState().route))
menu['Next waypoint'] = function() { next(state.route); removeMenu(); }; menu['Next waypoint'] = function() { next(WIDGETS.gpstrek.getState().route); removeMenu(); };
E.showMenu(menu); E.showMenu(menu);
} };
function showWaypointSelector(){ let showWaypointSelector = function(){
let waypoints = require("waypoints").load(); let waypoints = require("waypoints").load();
var menu = { var menu = {
"" : { "" : {
@ -550,41 +590,41 @@ function showWaypointSelector(){
waypoints.forEach((wp,c)=>{ waypoints.forEach((wp,c)=>{
menu[waypoints[c].name] = function (){ menu[waypoints[c].name] = function (){
state.waypoint = waypoints[c]; WIDGETS.gpstrek.getState().waypoint = waypoints[c];
state.waypointIndex = c; WIDGETS.gpstrek.getState().waypointIndex = c;
state.route = null; WIDGETS.gpstrek.getState().route = null;
removeMenu(); removeMenu();
}; };
}); });
E.showMenu(menu); E.showMenu(menu);
} };
function showCalibrationMenu(){ let showCalibrationMenu = function(){
let menu = { let menu = {
"" : { "" : {
"title" : "Calibration", "title" : "Calibration",
back : showMenu, back : showMenu,
}, },
"Barometer (GPS)" : ()=>{ "Barometer (GPS)" : ()=>{
if (!state.currentPos || isNaN(state.currentPos.alt)){ if (!WIDGETS.gpstrek.getState().currentPos || isNaN(WIDGETS.gpstrek.getState().currentPos.alt)){
E.showAlert("No GPS altitude").then(()=>{E.showMenu(menu);}); E.showAlert("No GPS altitude").then(()=>{E.showMenu(menu);});
} else { } else {
state.calibAltDiff = state.altitude - state.currentPos.alt; WIDGETS.gpstrek.getState().calibAltDiff = WIDGETS.gpstrek.getState().altitude - WIDGETS.gpstrek.getState().currentPos.alt;
E.showAlert("Calibrated Altitude Difference: " + state.calibAltDiff.toFixed(0)).then(()=>{removeMenu();}); E.showAlert("Calibrated Altitude Difference: " + WIDGETS.gpstrek.getState().calibAltDiff.toFixed(0)).then(()=>{removeMenu();});
} }
}, },
"Barometer (Manual)" : { "Barometer (Manual)" : {
value : Math.round(state.currentPos && (state.currentPos.alt != undefined && !isNaN(state.currentPos.alt)) ? state.currentPos.alt: state.altitude), value : Math.round(WIDGETS.gpstrek.getState().currentPos && (WIDGETS.gpstrek.getState().currentPos.alt != undefined && !isNaN(WIDGETS.gpstrek.getState().currentPos.alt)) ? WIDGETS.gpstrek.getState().currentPos.alt: WIDGETS.gpstrek.getState().altitude),
min:-2000,max: 10000,step:1, min:-2000,max: 10000,step:1,
onchange : v => { state.calibAltDiff = state.altitude - v; } onchange : v => { WIDGETS.gpstrek.getState().calibAltDiff = WIDGETS.gpstrek.getState().altitude - v; }
}, },
"Reset Compass" : ()=>{ Bangle.resetCompass(); removeMenu();}, "Reset Compass" : ()=>{ Bangle.resetCompass(); removeMenu();},
}; };
E.showMenu(menu); E.showMenu(menu);
} };
function showWaypointMenu(){ let showWaypointMenu = function(){
let menu = { let menu = {
"" : { "" : {
"title" : "Waypoint", "title" : "Waypoint",
@ -593,21 +633,21 @@ function showWaypointMenu(){
"Select waypoint" : showWaypointSelector, "Select waypoint" : showWaypointSelector,
}; };
E.showMenu(menu); E.showMenu(menu);
} };
function showBackgroundMenu(){ let showBackgroundMenu = function(){
let menu = { let menu = {
"" : { "" : {
"title" : "Background", "title" : "Background",
back : showMenu, back : showMenu,
}, },
"Start" : ()=>{ E.showPrompt("Start?").then((v)=>{ if (v) {WIDGETS.gpstrek.start(true); removeMenu();} else {showMenu();}}).catch(()=>{E.showMenu(mainmenu);});}, "Start" : ()=>{ E.showPrompt("Start?").then((v)=>{ if (v) {WIDGETS.gpstrek.start(true); removeMenu();} else {showMenu();}}).catch(()=>{showMenu();});},
"Stop" : ()=>{ E.showPrompt("Stop?").then((v)=>{ if (v) {WIDGETS.gpstrek.stop(true); removeMenu();} else {showMenu();}}).catch(()=>{E.showMenu(mainmenu);});}, "Stop" : ()=>{ E.showPrompt("Stop?").then((v)=>{ if (v) {WIDGETS.gpstrek.stop(true); removeMenu();} else {showMenu();}}).catch(()=>{showMenu();});},
}; };
E.showMenu(menu); E.showMenu(menu);
} };
function showMenu(){ let showMenu = function(){
var mainmenu = { var mainmenu = {
"" : { "" : {
"title" : "Main", "title" : "Main",
@ -617,50 +657,55 @@ function showMenu(){
"Waypoint" : showWaypointMenu, "Waypoint" : showWaypointMenu,
"Background" : showBackgroundMenu, "Background" : showBackgroundMenu,
"Calibration": showCalibrationMenu, "Calibration": showCalibrationMenu,
"Reset" : ()=>{ E.showPrompt("Do Reset?").then((v)=>{ if (v) {WIDGETS.gpstrek.resetState(); removeMenu();} else {E.showMenu(mainmenu);}});}, "Reset" : ()=>{ E.showPrompt("Do Reset?").then((v)=>{ if (v) {WIDGETS.gpstrek.resetState(); removeMenu();} else {E.showMenu(mainmenu);}}).catch(()=>{E.showMenu(mainmenu);});},
"Info rows" : { "Info rows" : {
value : numberOfSlices, value : WIDGETS.gpstrek.getState().numberOfSlices,
min:1,max:6,step:1, min:1,max:6,step:1,
onchange : v => { setNumberOfSlices(v); } onchange : v => { WIDGETS.gpstrek.getState().numberOfSlices = v; }
}, },
}; };
E.showMenu(mainmenu); E.showMenu(mainmenu);
} };
let scheduleDraw = true;
function switchMenu(){ let switchMenu = function(){
screen = 0; stopDrawing();
scheduleDraw = false;
showMenu(); showMenu();
} };
function drawInTimeout(){ let stopDrawing = function(){
setTimeout(()=>{ if (drawTimeout) clearTimeout(drawTimeout);
scheduleDraw = false;
};
let drawInTimeout = function(){
if (global.drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(()=>{
drawTimeout = undefined;
draw(); draw();
if (scheduleDraw) },50);
setTimeout(drawInTimeout, 0); };
},0);
}
function switchNav(){ let switchNav = function(){
if (!screen) screen = 1; if (!screen) screen = 1;
setButtons(); setButtons();
scheduleDraw = true; scheduleDraw = true;
firstDraw = true;
drawInTimeout(); drawInTimeout();
} };
function nextScreen(){ let nextScreen = function(){
screen++; screen++;
if (screen > maxScreens){ if (screen > maxScreens){
screen = 1; screen = 1;
} }
} drawInTimeout();
};
function setClosestWaypoint(route, startindex, progress){ let setClosestWaypoint = function(route, startindex, progress){
if (startindex >= state.route.count) startindex = state.route.count - 1; if (startindex >= WIDGETS.gpstrek.getState().route.count) startindex = WIDGETS.gpstrek.getState().route.count - 1;
if (!state.currentPos.lat){ if (!WIDGETS.gpstrek.getState().currentPos.lat){
set(route, startindex); set(route, startindex);
return; return;
} }
@ -670,7 +715,7 @@ function setClosestWaypoint(route, startindex, progress){
if (progress && (i % 5 == 0)) progress(i-(startindex?startindex:0), "Searching", route.count); if (progress && (i % 5 == 0)) progress(i-(startindex?startindex:0), "Searching", route.count);
let wp = {}; let wp = {};
getEntry(route.filename, route.refs[i], wp); getEntry(route.filename, route.refs[i], wp);
let curDist = distance(state.currentPos, wp); let curDist = distance(WIDGETS.gpstrek.getState().currentPos, wp);
if (curDist < minDist){ if (curDist < minDist){
minDist = curDist; minDist = curDist;
minIndex = i; minIndex = i;
@ -679,30 +724,28 @@ function setClosestWaypoint(route, startindex, progress){
} }
} }
set(route, minIndex); set(route, minIndex);
} };
let screen = 1;
const finishIcon = atob("CggB//meZmeZ+Z5n/w=="); const finishIcon = atob("CggB//meZmeZ+Z5n/w==");
const compassSliceData = { const compassSliceData = {
getCourseType: function(){ getCourseType: function(){
return (state.currentPos && state.currentPos.course) ? "GPS" : "MAG"; return (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.course) ? "GPS" : "MAG";
}, },
getCourse: function (){ getCourse: function (){
if(compassSliceData.getCourseType() == "GPS") return state.currentPos.course; if(compassSliceData.getCourseType() == "GPS") return WIDGETS.gpstrek.getState().currentPos.course;
return state.compassHeading?state.compassHeading:undefined; return getAveragedCompass();
}, },
getPoints: function (){ getPoints: function (){
let points = []; let points = [];
if (state.currentPos && state.currentPos.lon && state.route && state.route.currentWaypoint){ if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lon && WIDGETS.gpstrek.getState().route && WIDGETS.gpstrek.getState().route.currentWaypoint){
points.push({bearing:bearing(state.currentPos, state.route.currentWaypoint), color:"#0f0"}); points.push({bearing:bearing(WIDGETS.gpstrek.getState().currentPos, WIDGETS.gpstrek.getState().route.currentWaypoint), color:"#0f0"});
} }
if (state.currentPos && state.currentPos.lon && state.route){ if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lon && WIDGETS.gpstrek.getState().route){
points.push({bearing:bearing(state.currentPos, getLast(state.route)), icon: finishIcon}); points.push({bearing:bearing(WIDGETS.gpstrek.getState().currentPos, getLast(WIDGETS.gpstrek.getState().route)), icon: finishIcon});
} }
if (state.currentPos && state.currentPos.lon && state.waypoint){ if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lon && WIDGETS.gpstrek.getState().waypoint){
points.push({bearing:bearing(state.currentPos, state.waypoint), icon: finishIcon}); points.push({bearing:bearing(WIDGETS.gpstrek.getState().currentPos, WIDGETS.gpstrek.getState().waypoint), icon: finishIcon});
} }
return points; return points;
}, },
@ -714,79 +757,74 @@ const compassSliceData = {
const waypointData = { const waypointData = {
icon: atob("EBCBAAAAAAAAAAAAcIB+zg/uAe4AwACAAAAAAAAAAAAAAAAA"), icon: atob("EBCBAAAAAAAAAAAAcIB+zg/uAe4AwACAAAAAAAAAAAAAAAAA"),
getProgress: function() { getProgress: function() {
return (state.route.index + 1) + "/" + state.route.count; return (WIDGETS.gpstrek.getState().route.index + 1) + "/" + WIDGETS.gpstrek.getState().route.count;
}, },
getTarget: function (){ getTarget: function (){
if (distance(state.currentPos,state.route.currentWaypoint) < 30 && hasNext(state.route)){ if (distance(WIDGETS.gpstrek.getState().currentPos,WIDGETS.gpstrek.getState().route.currentWaypoint) < 30 && hasNext(WIDGETS.gpstrek.getState().route)){
next(state.route); next(WIDGETS.gpstrek.getState().route);
Bangle.buzz(1000); Bangle.buzz(1000);
} }
return state.route.currentWaypoint; return WIDGETS.gpstrek.getState().route.currentWaypoint;
}, },
getStart: function (){ getStart: function (){
return state.currentPos; return WIDGETS.gpstrek.getState().currentPos;
} }
}; };
const finishData = { const finishData = {
icon: atob("EBABAAA/4DmgJmAmYDmgOaAmYD/gMAAwADAAMAAwAAAAAAA="), icon: atob("EBABAAA/4DmgJmAmYDmgOaAmYD/gMAAwADAAMAAwAAAAAAA="),
getTarget: function (){ getTarget: function (){
if (state.route) return getLast(state.route); if (WIDGETS.gpstrek.getState().route) return getLast(WIDGETS.gpstrek.getState().route);
if (state.waypoint) return state.waypoint; if (WIDGETS.gpstrek.getState().waypoint) return WIDGETS.gpstrek.getState().waypoint;
}, },
getStart: function (){ getStart: function (){
return state.currentPos; return WIDGETS.gpstrek.getState().currentPos;
} }
}; };
let sliceHeight; let getSliceHeight = function(number){
function setNumberOfSlices(number){ return Math.floor(Bangle.appRect.h/WIDGETS.gpstrek.getState().numberOfSlices);
numberOfSlices = number; };
sliceHeight = Math.floor((g.getHeight()-(showWidgets?24:0))/numberOfSlices);
}
let slices = [];
let maxScreens = 1;
setNumberOfSlices(3);
let compassSlice = getCompassSlice(compassSliceData); let compassSlice = getCompassSlice(compassSliceData);
let waypointSlice = getTargetSlice(waypointData); let waypointSlice = getTargetSlice(waypointData);
let finishSlice = getTargetSlice(finishData); let finishSlice = getTargetSlice(finishData);
let eleSlice = getDoubleLineSlice("Up","Down",()=>{ let eleSlice = getDoubleLineSlice("Up","Down",()=>{
return loc.distance(state.up,3) + "/" + (state.route ? loc.distance(state.route.up,3):"---"); return loc.distance(WIDGETS.gpstrek.getState().up,3) + "/" + (WIDGETS.gpstrek.getState().route ? loc.distance(WIDGETS.gpstrek.getState().route.up,3):"---");
},()=>{ },()=>{
return loc.distance(state.down,3) + "/" + (state.route ? loc.distance(state.route.down,3): "---"); return loc.distance(WIDGETS.gpstrek.getState().down,3) + "/" + (WIDGETS.gpstrek.getState().route ? loc.distance(WIDGETS.gpstrek.getState().route.down,3): "---");
}); });
let statusSlice = getDoubleLineSlice("Speed","Alt",()=>{ let statusSlice = getDoubleLineSlice("Speed","Alt",()=>{
let speed = 0; let speed = 0;
if (state.currentPos && state.currentPos.speed) speed = state.currentPos.speed; if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.speed) speed = WIDGETS.gpstrek.getState().currentPos.speed;
return loc.speed(speed,2); return loc.speed(speed,2);
},()=>{ },()=>{
let alt = Infinity; let alt = Infinity;
if (!isNaN(state.altitude)){ if (!isNaN(WIDGETS.gpstrek.getState().altitude)){
alt = isNaN(state.calibAltDiff) ? state.altitude : (state.altitude - state.calibAltDiff); alt = isNaN(WIDGETS.gpstrek.getState().calibAltDiff) ? WIDGETS.gpstrek.getState().altitude : (WIDGETS.gpstrek.getState().altitude - WIDGETS.gpstrek.getState().calibAltDiff);
} }
if (state.currentPos && state.currentPos.alt) alt = state.currentPos.alt; if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.alt) alt = WIDGETS.gpstrek.getState().currentPos.alt;
if (isNaN(alt)) return "---";
return loc.distance(alt,3); return loc.distance(alt,3);
}); });
let status2Slice = getDoubleLineSlice("Compass","GPS",()=>{ let status2Slice = getDoubleLineSlice("Compass","GPS",()=>{
return (state.compassHeading?Math.round(state.compassHeading):"---") + "°"; return getAveragedCompass() + "°";
},()=>{ },()=>{
let course = "---°"; let course = "---°";
if (state.currentPos && state.currentPos.course) course = state.currentPos.course + "°"; if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.course) course = WIDGETS.gpstrek.getState().currentPos.course + "°";
return course; return course;
},200); },200);
let healthSlice = getDoubleLineSlice("Heart","Steps",()=>{ let healthSlice = getDoubleLineSlice("Heart","Steps",()=>{
return state.bpm; return WIDGETS.gpstrek.getState().bpm || "---";
},()=>{ },()=>{
return state.steps; return !isNaN(WIDGETS.gpstrek.getState().steps)? WIDGETS.gpstrek.getState().steps: "---";
}); });
let system2Slice = getDoubleLineSlice("Bat","",()=>{ let system2Slice = getDoubleLineSlice("Bat","",()=>{
return (Bangle.isCharging()?"+":"") + E.getBattery().toFixed(0)+"% " + NRF.getBattery().toFixed(2) + "V"; return (Bangle.isCharging()?"+":"") + E.getBattery().toFixed(0)+"% " + (analogRead(D3)*4.2/BAT_FULL).toFixed(2) + "V";
},()=>{ },()=>{
return ""; return "";
}); });
@ -798,17 +836,17 @@ let systemSlice = getDoubleLineSlice("RAM","Storage",()=>{
return (STORAGE.getFree()/1024).toFixed(0)+"kB"; return (STORAGE.getFree()/1024).toFixed(0)+"kB";
}); });
function updateSlices(){ let updateSlices = function(){
slices = []; slices = [];
slices.push(compassSlice); slices.push(compassSlice);
if (state.currentPos && state.currentPos.lat && state.route && state.route.currentWaypoint && state.route.index < state.route.count - 1) { if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lat && WIDGETS.gpstrek.getState().route && WIDGETS.gpstrek.getState().route.currentWaypoint && WIDGETS.gpstrek.getState().route.index < WIDGETS.gpstrek.getState().route.count - 1) {
slices.push(waypointSlice); slices.push(waypointSlice);
} }
if (state.currentPos && state.currentPos.lat && (state.route || state.waypoint)) { if (WIDGETS.gpstrek.getState().currentPos && WIDGETS.gpstrek.getState().currentPos.lat && (WIDGETS.gpstrek.getState().route || WIDGETS.gpstrek.getState().waypoint)) {
slices.push(finishSlice); slices.push(finishSlice);
} }
if ((state.route && state.route.down !== undefined) || state.down != undefined) { if ((WIDGETS.gpstrek.getState().route && WIDGETS.gpstrek.getState().route.down !== undefined) || WIDGETS.gpstrek.getState().down != undefined) {
slices.push(eleSlice); slices.push(eleSlice);
} }
slices.push(statusSlice); slices.push(statusSlice);
@ -816,42 +854,44 @@ function updateSlices(){
slices.push(healthSlice); slices.push(healthSlice);
slices.push(systemSlice); slices.push(systemSlice);
slices.push(system2Slice); slices.push(system2Slice);
maxScreens = Math.ceil(slices.length/numberOfSlices); maxScreens = Math.ceil(slices.length/WIDGETS.gpstrek.getState().numberOfSlices);
} };
function clear() { let clear = function() {
g.clearRect(0,(showWidgets ? 24 : 0), g.getWidth(),g.getHeight()); g.clearRect(Bangle.appRect);
} };
let lastDrawnScreen;
let firstDraw = true;
function draw(){ let draw = function(){
if (!screen) return; if (!global.screen) return;
let ypos = showWidgets ? 24 : 0; let ypos = Bangle.appRect.y;
let firstSlice = (screen-1)*numberOfSlices; let firstSlice = (screen-1)*WIDGETS.gpstrek.getState().numberOfSlices;
updateSlices(); updateSlices();
let force = lastDrawnScreen != screen || firstDraw; let force = lastDrawnScreen != screen || firstDraw;
if (force){ if (force){
clear(); clear();
if (showWidgets){
Bangle.drawWidgets();
}
} }
if (firstDraw) Bangle.drawWidgets();
lastDrawnScreen = screen; lastDrawnScreen = screen;
for (let slice of slices.slice(firstSlice,firstSlice + numberOfSlices)) { let sliceHeight = getSliceHeight();
for (let slice of slices.slice(firstSlice,firstSlice + WIDGETS.gpstrek.getState().numberOfSlices)) {
g.reset(); g.reset();
if (!slice.refresh || slice.refresh() || force) slice.draw(g,0,ypos,sliceHeight,g.getWidth()); if (!slice.refresh || slice.refresh() || force) slice.draw(g,0,ypos,sliceHeight,g.getWidth());
ypos += sliceHeight+1; ypos += sliceHeight+1;
g.drawLine(0,ypos-1,g.getWidth(),ypos-1); g.drawLine(0,ypos-1,g.getWidth(),ypos-1);
} }
if (scheduleDraw){
drawInTimeout();
}
firstDraw = false; firstDraw = false;
} };
switchNav(); switchNav();
g.clear(); clear();
}

View File

@ -1,7 +1,7 @@
{ {
"id": "gpstrek", "id": "gpstrek",
"name": "GPS Trekking", "name": "GPS Trekking",
"version": "0.07", "version": "0.08",
"description": "Helper for tracking the status/progress during hiking. Do NOT depend on this for navigation!", "description": "Helper for tracking the status/progress during hiking. Do NOT depend on this for navigation!",
"icon": "icon.png", "icon": "icon.png",
"screenshots": [{"url":"screen1.png"},{"url":"screen2.png"},{"url":"screen3.png"},{"url":"screen4.png"}], "screenshots": [{"url":"screen1.png"},{"url":"screen2.png"},{"url":"screen3.png"},{"url":"screen4.png"}],

View File

@ -1,6 +1,28 @@
(() => { (() => {
const SAMPLES=5;
function initState(){
//cleanup volatile state here
state = {};
state.compassSamples = new Array(SAMPLES).fill(0);
state.lastSample = 0;
state.sampleIndex = 0;
state.currentPos={};
state.steps = 0;
state.calibAltDiff = 0;
state.numberOfSlices = 3;
state.steps = 0;
state.up = 0;
state.down = 0;
state.saved = 0;
state.avgComp = 0;
}
const STORAGE=require('Storage'); const STORAGE=require('Storage');
let state = STORAGE.readJSON("gpstrek.state.json")||{}; let state = STORAGE.readJSON("gpstrek.state.json");
if (!state) {
state = {};
initState();
}
let bgChanged = false; let bgChanged = false;
function saveState(){ function saveState(){
@ -8,12 +30,13 @@ function saveState(){
STORAGE.writeJSON("gpstrek.state.json", state); STORAGE.writeJSON("gpstrek.state.json", state);
} }
E.on("kill",()=>{ function onKill(){
if (bgChanged){ if (bgChanged || state.route || state.waypoint){
saveState(); saveState();
} }
}); }
E.on("kill", onKill);
function onPulse(e){ function onPulse(e){
state.bpm = e.bpm; state.bpm = e.bpm;
@ -23,27 +46,47 @@ function onGPS(fix) {
if(fix.fix) state.currentPos = fix; if(fix.fix) state.currentPos = fix;
} }
function onMag(e) { let radians = function(a) {
if (!state.compassHeading) state.compassHeading = e.heading; return a*Math.PI/180;
};
//if (a+180)mod 360 == b then let degrees = function(a) {
//return (a+b)/2 mod 360 and ((a+b)/2 mod 360) + 180 (they are both the solution, so you may choose one depending if you prefer counterclockwise or clockwise direction) let d = a*180/Math.PI;
//else return (d+360)%360;
//return arctan( (sin(a)+sin(b)) / (cos(a)+cos(b) ) };
/* function average(samples){
let average; let s = 0;
let a = radians(compassHeading); let c = 0;
let b = radians(e.heading); for (let h of samples){
if ((a+180) % 360 == b){ s += Math.sin(radians(h));
average = ((a+b)/2 % 360); //can add 180 depending on rotation c += Math.cos(radians(h));
} else { }
average = Math.atan( (Math.sin(a)+Math.sin(b))/(Math.cos(a)+Math.cos(b)) ); s /= samples.length;
c /= samples.length;
let result = degrees(Math.atan(s/c));
if (c < 0) result += 180;
if (s < 0 && c > 0) result += 360;
result%=360;
return result;
}
function onMag(e) {
if (!isNaN(e.heading)){
if (Bangle.isLocked() || (Bangle.getGPSFix() && Bangle.getGPSFix().lon))
state.avgComp = e.heading;
else {
state.compassSamples[state.sampleIndex++] = e.heading;
state.lastSample = Date.now();
if (state.sampleIndex > SAMPLES - 1){
state.sampleIndex = 0;
let avg = average(state.compassSamples);
state.avgComp = average([state.avgComp,avg]);
}
}
} }
print("Angle",compassHeading,e.heading, average);
compassHeading = (compassHeading + degrees(average)) % 360;
*/
state.compassHeading = Math.round(e.heading);
} }
function onStep(e) { function onStep(e) {
@ -73,6 +116,16 @@ function onAcc (e){
state.acc = e; state.acc = e;
} }
function update(){
if (state.active){
start(false);
}
if (state.active == !(WIDGETS.gpstrek.width)) {
if(WIDGETS.gpstrek) WIDGETS.gpstrek.width = state.active?24:0;
Bangle.drawWidgets();
}
}
function start(bg){ function start(bg){
Bangle.removeListener('GPS', onGPS); Bangle.removeListener('GPS', onGPS);
Bangle.removeListener("HRM", onPulse); Bangle.removeListener("HRM", onPulse);
@ -94,9 +147,9 @@ function start(bg){
if (bg){ if (bg){
if (!state.active) bgChanged = true; if (!state.active) bgChanged = true;
state.active = true; state.active = true;
update();
saveState(); saveState();
} }
Bangle.drawWidgets();
} }
function stop(bg){ function stop(bg){
@ -114,22 +167,10 @@ function stop(bg){
Bangle.removeListener("step", onStep); Bangle.removeListener("step", onStep);
Bangle.removeListener("pressure", onPressure); Bangle.removeListener("pressure", onPressure);
Bangle.removeListener('accel', onAcc); Bangle.removeListener('accel', onAcc);
E.removeListener("kill", onKill);
} }
update();
saveState(); saveState();
Bangle.drawWidgets();
}
function initState(){
//cleanup volatile state here
state.currentPos={};
state.steps = Bangle.getStepCount();
state.calibAltDiff = 0;
state.up = 0;
state.down = 0;
}
if (state.saved && state.saved < Date.now() - 60000){
initState();
} }
if (state.active){ if (state.active){
@ -141,11 +182,15 @@ WIDGETS["gpstrek"]={
width:state.active?24:0, width:state.active?24:0,
resetState: initState, resetState: initState,
getState: function() { getState: function() {
if (state.saved && Date.now() - state.saved > 60000 || !state){
initState();
}
return state; return state;
}, },
start:start, start:start,
stop:stop, stop:stop,
draw:function() { draw:function() {
update();
if (state.active){ if (state.active){
g.reset(); g.reset();
g.drawImage(atob("GBiBAAAAAAAAAAAYAAAYAAAYAAA8AAA8AAB+AAB+AADbAADbAAGZgAGZgAMYwAMYwAcY4AYYYA5+cA3/sB/D+B4AeBAACAAAAAAAAA=="), this.x, this.y); g.drawImage(atob("GBiBAAAAAAAAAAAYAAAYAAAYAAA8AAA8AAB+AAB+AADbAADbAAGZgAGZgAMYwAMYwAcY4AYYYA5+cA3/sB/D+B4AeBAACAAAAAAAAA=="), this.x, this.y);

View File

@ -1,2 +1,3 @@
0.01: New App! 0.01: New App!
0.02: Less time used during boot if disabled 0.02: Less time used during boot if disabled
0.03: Fixed some test data

View File

@ -278,12 +278,13 @@ exports.enable = () => {
let currentLat=20; let currentLat=20;
let currentLon=10; let currentLon=10;
let currentCourse=10; let currentCourse=10;
let currentAlt=-100; let currentDir=1000;
let currentAlt=500;
let currentSats=5; let currentSats=5;
modGps(() => { modGps(() => {
currentLat += 0.1; currentLat += 0.01;
if (currentLat > 50) currentLat = 20; if (currentLat > 50) currentLat = 20;
currentLon += 0.1; currentLon += 0.01;
if (currentLon > 20) currentLon = 10; if (currentLon > 20) currentLon = 10;
currentSpeed *= 10; currentSpeed *= 10;
if (currentSpeed > 1000) currentSpeed = 1; if (currentSpeed > 1000) currentSpeed = 1;
@ -291,8 +292,9 @@ exports.enable = () => {
if (currentCourse > 360) currentCourse -= 360; if (currentCourse > 360) currentCourse -= 360;
currentSats += 1; currentSats += 1;
if (currentSats > 10) currentSats = 5; if (currentSats > 10) currentSats = 5;
currentAlt *= 10; currentAlt += currentDir;
if (currentAlt > 1000) currentAlt = -100; if (currentAlt > 20000) currentDir = -2000;
if (currentAlt < -2000) currentDir = 2000;
return { return {
"lat": currentLat, "lat": currentLat,
"lon": currentLon, "lon": currentLon,

View File

@ -2,7 +2,7 @@
"id": "sensortools", "id": "sensortools",
"name": "Sensor tools", "name": "Sensor tools",
"shortName": "Sensor tools", "shortName": "Sensor tools",
"version": "0.02", "version": "0.03",
"description": "Tools for testing and debugging apps that use sensor input", "description": "Tools for testing and debugging apps that use sensor input",
"icon": "icon.png", "icon": "icon.png",
"type": "bootloader", "type": "bootloader",