forked from FOSS/BangleApps
Big refactor to attempt to merge all the waypoints code into one place. At least 3 apps had basically identical interface.html files, and yet wpmoto had a great map-based editor.
parent
e9fdb1dee5
commit
91728c147f
|
@ -3,4 +3,4 @@
|
|||
0.03: Add Waypoint Editor
|
||||
0.04: Fix great circle formula
|
||||
0.05: Use locale for speed and distance + fix Vector font sizes
|
||||
|
||||
0.06: Move waypoints.json (and editor) to 'waypoints' app
|
||||
|
|
|
@ -207,7 +207,7 @@ Bangle.on('lcdPower',function(on) {
|
|||
}
|
||||
});
|
||||
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
var waypoints = require("waypoints").load();
|
||||
wp=waypoints[0];
|
||||
|
||||
function nextwp(inc){
|
||||
|
@ -223,7 +223,7 @@ function doselect(){
|
|||
if (selected && wpindex!=0 && 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);
|
||||
require("waypoints").save(waypoints);
|
||||
}
|
||||
selected=!selected;
|
||||
drawN();
|
||||
|
|
|
@ -6,6 +6,6 @@ function drawN(){var a=loc.speed(speed);buf.setColor(1);buf.setFont("6x8",2);buf
|
|||
0,30);buf.setColor(selected?1:2);buf.drawString(wp.name,140,0);buf.setColor(1);buf.drawString(a,60,0);buf.drawString(loc.distance(dist),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(a){savedfix=a;void 0!==a&&(course=isNaN(a.course)?course:Math.round(a.course),speed=isNaN(a.speed)?speed:a.speed,satellites=a.satellites);candraw&&(void 0!==a&&1==a.fix&&(dist=distance(a,wp),isNaN(dist)&&(dist=0),brg=bearing(a,wp),isNaN(brg)&&(brg=0)),drawN())}var intervalRef;function stopdraw(){candraw=!1;intervalRef&&clearInterval(intervalRef)}
|
||||
function startTimers(){candraw=!0;intervalRefSec=setInterval(function(){heading=newHeading(course,heading);course!=heading&&drawCompass(heading)},200)}function drawAll(){g.setColor(1,.5,.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:!0,edge:"falling"});setWatch(doselect,BTN2,{repeat:!0,edge:"falling"});setWatch(nextwp.bind(null,1),BTN3,{repeat:!0,edge:"falling"})}var SCREENACCESS={withApp:!0,request:function(){this.withApp=!1;stopdraw();clearWatch()},release:function(){this.withApp=!0;startdraw();setButtons()}};Bangle.on("lcdPower",function(a){SCREENACCESS.withApp&&(a?startdraw():stopdraw())});var waypoints=require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
wp=waypoints[0];function nextwp(a){selected&&(wpindex+=a,wpindex>=waypoints.length&&(wpindex=0),0>wpindex&&(wpindex=waypoints.length-1),wp=waypoints[wpindex],drawN())}function doselect(){selected&&0!=wpindex&&void 0===waypoints[wpindex].lat&&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();
|
||||
function setButtons(){setWatch(nextwp.bind(null,-1),BTN1,{repeat:!0,edge:"falling"});setWatch(doselect,BTN2,{repeat:!0,edge:"falling"});setWatch(nextwp.bind(null,1),BTN3,{repeat:!0,edge:"falling"})}var SCREENACCESS={withApp:!0,request:function(){this.withApp=!1;stopdraw();clearWatch()},release:function(){this.withApp=!0;startdraw();setButtons()}};Bangle.on("lcdPower",function(a){SCREENACCESS.withApp&&(a?startdraw():stopdraw())});var waypoints=require("waypoints").load();
|
||||
wp=waypoints[0];function nextwp(a){selected&&(wpindex+=a,wpindex>=waypoints.length&&(wpindex=0),0>wpindex&&(wpindex=waypoints.length-1),wp=waypoints[wpindex],drawN())}function doselect(){selected&&0!=wpindex&&void 0===waypoints[wpindex].lat&&savedfix.fix&&(waypoints[wpindex]={name:"@"+wp.name,lat:savedfix.lat,lon:savedfix.lon},wp=waypoints[wpindex],require("waypoints").save(waypoints));selected=!selected;drawN()}g.clear();Bangle.setLCDBrightness(1);Bangle.loadWidgets();Bangle.drawWidgets();
|
||||
Bangle.setGPSPower(1);drawAll();startTimers();Bangle.on("GPS",onGPS);setButtons();
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
{
|
||||
"id": "gpsnav",
|
||||
"name": "GPS Navigation",
|
||||
"version": "0.05",
|
||||
"version": "0.06",
|
||||
"description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording, now with waypoint editor",
|
||||
"icon": "icon.png",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"interface": "waypoints.html",
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"storage": [
|
||||
{"name":"gpsnav.app.js","url":"app.min.js"},
|
||||
{"name":"gpsnav.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"waypoints.json","url":"waypoints.json"}]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h4>List of waypoints</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Lat.</th>
|
||||
<th>Long.</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="waypoints">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h4>Add a new waypoint</h4>
|
||||
<form id="add_waypoint_form">
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" type="text" id="add_waypoint_name" placeholder="Name">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_latitude" placeholder="Lat">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_longtitude" placeholder="Long">
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_name_button" class="btn btn-primary btn-sm">Add Name Only</button>
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_waypoint_button" class="btn btn-primary btn-sm">Add Waypoint</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
<button id="Download" class="btn btn-error">Reload</button> <button id="Upload" class="btn btn-primary">Upload</button>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var waypoints = []
|
||||
|
||||
var $name = document.getElementById('add_waypoint_name')
|
||||
var $form = document.getElementById('add_waypoint_form')
|
||||
var $button = document.getElementById('add_waypoint_button')
|
||||
var $name_button = document.getElementById('add_name_button')
|
||||
var $latitude = document.getElementById('add_latitude')
|
||||
var $longtitude = document.getElementById('add_longtitude')
|
||||
var $list = document.getElementById('waypoints')
|
||||
|
||||
function compare(a, b){
|
||||
var x = a.name.toLowerCase();
|
||||
var y = b.name.toLowerCase();
|
||||
if (x=="none") {return -1};
|
||||
if (y=="none") {return 1};
|
||||
if (x < y) {return -1;}
|
||||
if (x > y) {return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
$button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
var lat = parseFloat($latitude.value).toPrecision(5);
|
||||
var lon = parseFloat($longtitude.value).toPrecision(5);
|
||||
|
||||
waypoints.push({
|
||||
name, lat,lon,
|
||||
});
|
||||
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = (0).toPrecision(5);
|
||||
$longtitude.value = (0).toPrecision(5);
|
||||
});
|
||||
|
||||
$name_button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
|
||||
waypoints.push({
|
||||
name
|
||||
});
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = 0.0000
|
||||
$longtitude.value = 0.0000
|
||||
});
|
||||
|
||||
|
||||
function removeWaypoint(index){
|
||||
$name.value = waypoints[index].name
|
||||
$latitude.value = waypoints[index].lat
|
||||
$longtitude.value = waypoints[index].lon
|
||||
waypoints = waypoints.filter((p,i) => i!==index)
|
||||
renderWaypoints()
|
||||
}
|
||||
|
||||
function renderWaypoints(){
|
||||
$list.innerHTML = ''
|
||||
waypoints.forEach((waypoint,index) => {
|
||||
var $waypoint = document.createElement('tr')
|
||||
if (index==0){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td>`
|
||||
} else if(waypoint.lat==undefined){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>------</td><td>-----</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
} else {
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>${waypoint.lat}</td><td>${waypoint.lon}</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
}
|
||||
$list.appendChild($waypoint)
|
||||
})
|
||||
$name.focus()
|
||||
}
|
||||
|
||||
function downloadJSONfile(fileid, callback) {
|
||||
Puck.write(`\x10(function() {
|
||||
var pts = require("Storage").readJSON("${fileid}")||[{name:"NONE"}];
|
||||
Bluetooth.print(JSON.stringify(pts));
|
||||
})()\n`,contents=>{
|
||||
var storedpts = JSON.parse(contents);
|
||||
callback(storedpts);
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFile(fileid, contents) {
|
||||
Puck.write(`\x10(function() {
|
||||
require("Storage").write("${fileid}",'${contents}');
|
||||
Bluetooth.print("OK");
|
||||
})()\n`,ret=>{
|
||||
console.log("uploadFile",ret);
|
||||
});
|
||||
}
|
||||
|
||||
function gotStored(pts){
|
||||
waypoints = pts;
|
||||
renderWaypoints();
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
}
|
||||
|
||||
document.getElementById("Download").addEventListener("click", function() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
});
|
||||
|
||||
document.getElementById("Upload").addEventListener("click", function() {
|
||||
var data = JSON.stringify(waypoints);
|
||||
uploadFile("waypoints.json",data);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
},
|
||||
{ "name":"WP0" },
|
||||
{ "name":"WP1" },
|
||||
{ "name":"WP2" },
|
||||
{ "name":"WP3" },
|
||||
{ "name":"WP4" }
|
||||
]
|
|
@ -11,3 +11,4 @@
|
|||
0.11: Detect when waypoints.json is not present, error E-WPT
|
||||
0.12: Added stepo2 as a replacement for stepo and digi
|
||||
0.13: Added long press BTN2 toggle gpsrec status in GPS clock
|
||||
0.14: Move waypoints.json (and editor) to 'waypoints' app
|
||||
|
|
|
@ -208,14 +208,8 @@ which will obviously limit this.
|
|||
|
||||
### Waypoint Editor
|
||||
|
||||
Clicking on the download icon of gpsnav in the app loader invokes the
|
||||
waypoint editor. The editor downloads and displays the current
|
||||
`waypoints.json` file. Clicking the `Edit` button beside an entry
|
||||
causes the entry to be deleted from the list and displayed in the
|
||||
edit boxes. It can be restored - by clicking the `Add waypoint`
|
||||
button. A new markable entry is created by using the `Add name`
|
||||
button. The edited `waypoints.json` file is uploaded to the Bangle by
|
||||
clicking the `Upload` button.
|
||||
Clicking on the download icon of `Waypoints` in the app loader invokes the
|
||||
waypoint editor. See the `Waypoints` app for more information.
|
||||
|
||||
|
||||
### Calibration of the Compass
|
||||
|
|
|
@ -321,7 +321,7 @@ GPS.prototype.getWPbearing = function() {
|
|||
}
|
||||
|
||||
GPS.prototype.loadFirstWaypoint = function() {
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
var waypoints = require("waypoints").load();
|
||||
this.wp_index = 0;
|
||||
this.wp_current = waypoints[this.wp_index];
|
||||
log_debug(this.wp_current);
|
||||
|
@ -346,7 +346,7 @@ GPS.prototype.markWaypoint = function() {
|
|||
|
||||
log_debug("GPS::markWaypoint()");
|
||||
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
var waypoints = require("waypoints").load();
|
||||
this.wp_current = waypoints[this.wp_index];
|
||||
|
||||
if (this.waypointHasLocation()) {
|
||||
|
@ -356,12 +356,12 @@ GPS.prototype.markWaypoint = function() {
|
|||
}
|
||||
|
||||
this.wp_current = waypoints[this.wp_index];
|
||||
require("Storage").writeJSON("waypoints.json", waypoints);
|
||||
require("waypoints").save(waypoints);
|
||||
log_debug("GPS::markWaypoint() written");
|
||||
}
|
||||
|
||||
GPS.prototype.nextWaypoint = function(inc) {
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"E-WPT"}];
|
||||
var waypoints = require("waypoints").load();
|
||||
this.wp_index+=inc;
|
||||
if (this.wp_index>=waypoints.length) this.wp_index=0;
|
||||
if (this.wp_index<0) this.wp_index = waypoints.length-1;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"id": "kitchen",
|
||||
"name": "Kitchen Combo",
|
||||
"version": "0.13",
|
||||
"version": "0.14",
|
||||
"description": "Combination of the Stepo, Walkersclock, Arrow and Waypointer apps into a multiclock format. 'Everything but the kitchen sink'",
|
||||
"icon": "kitchen.png",
|
||||
"type": "clock",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"interface": "waypoints.html",
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"storage": [
|
||||
{"name":"kitchen.app.js","url":"kitchen.app.js"},
|
||||
{"name":"stepo2.kit.js","url":"stepo2.kit.js"},
|
||||
|
@ -16,6 +16,5 @@
|
|||
{"name":"gps.kit.js","url":"gps.kit.js"},
|
||||
{"name":"compass.kit.js","url":"compass.kit.js"},
|
||||
{"name":"kitchen.img","url":"kitchen.icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"waypoints.json","url":"waypoints.json"}]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h4>List of waypoints</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Lat.</th>
|
||||
<th>Long.</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="waypoints">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h4>Add a new waypoint</h4>
|
||||
<form id="add_waypoint_form">
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" type="text" id="add_waypoint_name" placeholder="Name">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_latitude" placeholder="Lat">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_longtitude" placeholder="Long">
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_name_button" class="btn btn-primary btn-sm">Add Name Only</button>
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_waypoint_button" class="btn btn-primary btn-sm">Add Waypoint</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
<button id="Download" class="btn btn-error">Reload</button> <button id="Upload" class="btn btn-primary">Upload</button>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var waypoints = []
|
||||
|
||||
var $name = document.getElementById('add_waypoint_name')
|
||||
var $form = document.getElementById('add_waypoint_form')
|
||||
var $button = document.getElementById('add_waypoint_button')
|
||||
var $name_button = document.getElementById('add_name_button')
|
||||
var $latitude = document.getElementById('add_latitude')
|
||||
var $longtitude = document.getElementById('add_longtitude')
|
||||
var $list = document.getElementById('waypoints')
|
||||
|
||||
function compare(a, b){
|
||||
var x = a.name.toLowerCase();
|
||||
var y = b.name.toLowerCase();
|
||||
if (x=="none") {return -1};
|
||||
if (y=="none") {return 1};
|
||||
if (x < y) {return -1;}
|
||||
if (x > y) {return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
$button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
var lat = parseFloat($latitude.value).toPrecision(5);
|
||||
var lon = parseFloat($longtitude.value).toPrecision(5);
|
||||
|
||||
waypoints.push({
|
||||
name, lat,lon,
|
||||
});
|
||||
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = (0).toPrecision(5);
|
||||
$longtitude.value = (0).toPrecision(5);
|
||||
});
|
||||
|
||||
$name_button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
|
||||
waypoints.push({
|
||||
name
|
||||
});
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = 0.0000
|
||||
$longtitude.value = 0.0000
|
||||
});
|
||||
|
||||
|
||||
function removeWaypoint(index){
|
||||
$name.value = waypoints[index].name
|
||||
$latitude.value = waypoints[index].lat
|
||||
$longtitude.value = waypoints[index].lon
|
||||
waypoints = waypoints.filter((p,i) => i!==index)
|
||||
renderWaypoints()
|
||||
}
|
||||
|
||||
function renderWaypoints(){
|
||||
$list.innerHTML = ''
|
||||
waypoints.forEach((waypoint,index) => {
|
||||
var $waypoint = document.createElement('tr')
|
||||
if (index==0){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td>`
|
||||
} else if(waypoint.lat==undefined){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>------</td><td>-----</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
} else {
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>${waypoint.lat}</td><td>${waypoint.lon}</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
}
|
||||
$list.appendChild($waypoint)
|
||||
})
|
||||
$name.focus()
|
||||
}
|
||||
|
||||
function downloadJSONfile(fileid, callback) {
|
||||
Puck.write(`\x10(function() {
|
||||
var pts = require("Storage").readJSON("${fileid}")||[{name:"NONE"}];
|
||||
Bluetooth.print(JSON.stringify(pts));
|
||||
})()\n`,contents=>{
|
||||
var storedpts = JSON.parse(contents);
|
||||
callback(storedpts);
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFile(fileid, contents) {
|
||||
Puck.write(`\x10(function() {
|
||||
require("Storage").write("${fileid}",'${contents}');
|
||||
Bluetooth.print("OK");
|
||||
})()\n`,ret=>{
|
||||
console.log("uploadFile",ret);
|
||||
});
|
||||
}
|
||||
|
||||
function gotStored(pts){
|
||||
waypoints = pts;
|
||||
renderWaypoints();
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
}
|
||||
|
||||
document.getElementById("Download").addEventListener("click", function() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
});
|
||||
|
||||
document.getElementById("Upload").addEventListener("click", function() {
|
||||
var data = JSON.stringify(waypoints);
|
||||
uploadFile("waypoints.json",data);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
},
|
||||
{ "name":"WP0" },
|
||||
{ "name":"WP1" },
|
||||
{ "name":"WP2" },
|
||||
{ "name":"WP3" },
|
||||
{ "name":"WP4" }
|
||||
]
|
|
@ -71,9 +71,7 @@ The MAX values continue to be collected with the display off so may appear a lit
|
|||
|
||||
## Waypoints
|
||||
|
||||
Waypoints are used in [D]istance mode. Create a file waypoints.json and write to storage on the Bangle.js using the IDE. The first 6 characters of the name are displayed in Speed+[D]istance mode.
|
||||
|
||||
The [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app in the App Loader has a really nice waypoints file editor. (Must be connected to your Bangle.JS and then click on the Download icon.)
|
||||
Waypoints are used in Distance and VMG modes. See the `Waypoints` app for information on how to create/edit waypoints. The first 6 characters of the name are displayed in Speed+[D]istance mode.
|
||||
|
||||
Sample waypoints.json (My sailing waypoints)
|
||||
|
||||
|
@ -149,5 +147,3 @@ Developed for my use in sailing, cycling and motorcycling. If you find this soft
|
|||
Many thanks to Gordon Williams. Awesome job.
|
||||
|
||||
Special thanks also to @jeffmer, for the [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app and @hughbarney for the Low power GPS code development and Wouter Bulten for the Kalman filter code.
|
||||
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ function nxtWp(inc){
|
|||
}
|
||||
|
||||
function loadWp() {
|
||||
var w = require("Storage").readJSON('waypoints.json')||[{name:"NONE"}];
|
||||
var w = require("waypoints").load();
|
||||
if (cfg.wp>=w.length) cfg.wp=0;
|
||||
if (cfg.wp<0) cfg.wp = w.length-1;
|
||||
savSettings();
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
"type": "app",
|
||||
"tags": "tool,outdoors",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"speedalt.app.js","url":"app.js"},
|
||||
{"name":"speedalt.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"speedalt.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [{"name":"speedalt.json"}]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -15,3 +15,4 @@
|
|||
0.15: Droidscript mirroring prog automatically uses last connection address. Auto connects when run.
|
||||
0.16: Add configuration item Wpt File Suffix. A one character suffix to append to the waypoints.json file. A number of other apps also use this file name. Using the file name suffix allows the speedalt2 waypoints to be retained if one of these other apps is installed for a different use.
|
||||
0.17: Use default Bangle formatter for booleans
|
||||
0.18: Move waypoints.json to 'waypoints' app (with editor)
|
||||
|
|
|
@ -74,13 +74,11 @@ Android Screen Mirroring:<br>
|
|||
|
||||
## Waypoints
|
||||
|
||||
Waypoints are used in Distance and VMG modes. Create a file waypoints.json and write to storage on the Bangle.js using the IDE. The first 6 characters of the name are displayed in Speed+[D]istance mode.
|
||||
|
||||
The [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app in the App Loader has a really nice waypoints file editor. (Must be connected to your Bangle.JS and then click on the Download icon.)
|
||||
Waypoints are used in Distance and VMG modes. See the `Waypoints` app for information on how to create/edit waypoints. The first 6 characters of the name are displayed in Speed+[D]istance mode.
|
||||
|
||||
By default the waypoints file is called waypoints.json
|
||||
|
||||
**Note** : The waypoints.json file is used by a number of different gps apps. The setting 'Wpt File Suffix' allows one of waypoints1.json, waypoints2.json or waypoints3.json to be used instead. This allows the other apps to be used with a different set of waypoints without losing the speedalt2 waypoint set.
|
||||
**Note** : The waypoints.json file is used by a number of different gps apps. The setting 'Wpt File Suffix' allows one of waypoints.1.json, waypoints.2.json or waypoints.3.json to be used instead. This allows the other apps to be used with a different set of waypoints without losing the speedalt2 waypoint set.
|
||||
|
||||
Sample waypoints.json (My sailing waypoints)
|
||||
|
||||
|
@ -156,4 +154,3 @@ Developed for my use in sailing, cycling and motorcycling. If you find this soft
|
|||
Many thanks to Gordon Williams. Awesome job.
|
||||
|
||||
Special thanks also to @jeffmer, for the [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app and @hughbarney for the Low power GPS code development and Wouter Bulten for the Kalman filter code.
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ function nxtWp(){
|
|||
}
|
||||
|
||||
function loadWp() {
|
||||
var w = require("Storage").readJSON('waypoints'+cfg.wptSfx+'.json')||[{name:"NONE"}];
|
||||
var w = require("waypoints").load(cfg.wptSfx);
|
||||
if (cfg.wp>=w.length) cfg.wp=0;
|
||||
if (cfg.wp<0) cfg.wp = w.length-1;
|
||||
savSettings();
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
"id": "speedalt2",
|
||||
"name": "GPS Adventure Sports II",
|
||||
"shortName":"GPS Adv Sport II",
|
||||
"version":"0.17",
|
||||
"version":"0.18",
|
||||
"description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
"tags": "tool,outdoors",
|
||||
"supports": ["BANGLEJS"],
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
|
@ -16,10 +17,6 @@
|
|||
{"name":"speedalt2.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [
|
||||
{"name":"speedalt2.json"},
|
||||
{"name":"waypoints.json"},
|
||||
{"name":"waypoints1.json"},
|
||||
{"name":"waypoints2.json"},
|
||||
{"name":"waypoints3.json"}
|
||||
{"name":"speedalt2.json"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: New app!
|
||||
0.02: Make Bangle.js 2 compatible
|
||||
0.03: Silently use built in heading when no magnav calibration file is present
|
||||
0.04: Move waypoints.json (and editor) to 'waypoints' app
|
||||
|
|
|
@ -61,58 +61,10 @@ The app indicates that WP2 is now marked by adding the prefix @ to
|
|||
it's name. The distance should be small as shown in the screen shot
|
||||
as you have just marked your current location.
|
||||
|
||||
## Waypoint JSON file
|
||||
|
||||
When the app is loaded from the app loader, a file named
|
||||
`waypoints.json` is loaded along with the javascript etc. The file
|
||||
has the following contents:
|
||||
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
},
|
||||
{ "name":"WP0" },
|
||||
{ "name":"WP1" },
|
||||
{ "name":"WP2" },
|
||||
{ "name":"WP3" },
|
||||
{ "name":"WP4" }
|
||||
]
|
||||
```
|
||||
|
||||
The file contains the initial NONE waypoint which is useful if you
|
||||
just want to display course and speed. The next two entries are
|
||||
waypoints to No 10 Downing Street and to Stone Henge - obtained from
|
||||
Google Maps. The last five entries are entries which can be *marked*.
|
||||
|
||||
You add and delete entries using the Web IDE to load and then save
|
||||
the file from and to watch storage. The app itself does not limit the
|
||||
number of entries although it does load the entire file into RAM
|
||||
which will obviously limit this.
|
||||
|
||||
|
||||
## Waypoint Editor
|
||||
|
||||
Clicking on the download icon of gpsnav in the app loader invokes the
|
||||
waypoint editor. The editor downloads and displays the current
|
||||
`waypoints.json` file. Clicking the `Edit` button beside an entry
|
||||
causes the entry to be deleted from the list and displayed in the
|
||||
edit boxes. It can be restored - by clicking the `Add waypoint`
|
||||
button. A new markable entry is created by using the `Add name`
|
||||
button. The edited `waypoints.json` file is uploaded to the Bangle by
|
||||
clicking the `Upload` button.
|
||||
## Setting Waypoints
|
||||
|
||||
Check out the documentation for the `Waypoints` app. This provides
|
||||
the ability to set waypoints from your browser.
|
||||
|
||||
## Calibration of the Compass
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ Bangle.on('lcdPower',function(on) {
|
|||
}
|
||||
});
|
||||
|
||||
var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}];
|
||||
var waypoints = require("waypoints").load();
|
||||
wp=waypoints[0];
|
||||
|
||||
function nextwp(inc){
|
||||
|
@ -266,7 +266,7 @@ function doselect(){
|
|||
if (selected && wpindex!=0 && 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);
|
||||
require("waypoints").save(waypoints);
|
||||
}
|
||||
selected=!selected;
|
||||
drawN();
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
{
|
||||
"id": "waypointer",
|
||||
"name": "Way Pointer",
|
||||
"version": "0.03",
|
||||
"version": "0.04",
|
||||
"description": "Navigate to a waypoint using the GPS for bearing and compass to point way, uses the same waypoint interface as GPS Navigation",
|
||||
"icon": "waypointer.png",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"readme": "README.md",
|
||||
"interface": "waypoints.html",
|
||||
"storage": [
|
||||
{"name":"waypointer.app.js","url":"app.js"},
|
||||
{"name":"waypointer.img","url":"icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"waypoints.json","url":"waypoints.json"}]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h4>List of waypoints</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Lat.</th>
|
||||
<th>Long.</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="waypoints">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h4>Add a new waypoint</h4>
|
||||
<form id="add_waypoint_form">
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" type="text" id="add_waypoint_name" placeholder="Name">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_latitude" placeholder="Lat">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_longtitude" placeholder="Long">
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_name_button" class="btn btn-primary btn-sm">Add Name Only</button>
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_waypoint_button" class="btn btn-primary btn-sm">Add Waypoint</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
<button id="Download" class="btn btn-error">Reload</button> <button id="Upload" class="btn btn-primary">Upload</button>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var waypoints = []
|
||||
|
||||
var $name = document.getElementById('add_waypoint_name')
|
||||
var $form = document.getElementById('add_waypoint_form')
|
||||
var $button = document.getElementById('add_waypoint_button')
|
||||
var $name_button = document.getElementById('add_name_button')
|
||||
var $latitude = document.getElementById('add_latitude')
|
||||
var $longtitude = document.getElementById('add_longtitude')
|
||||
var $list = document.getElementById('waypoints')
|
||||
|
||||
function compare(a, b){
|
||||
var x = a.name.toLowerCase();
|
||||
var y = b.name.toLowerCase();
|
||||
if (x=="none") {return -1};
|
||||
if (y=="none") {return 1};
|
||||
if (x < y) {return -1;}
|
||||
if (x > y) {return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
$button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
var lat = parseFloat($latitude.value);
|
||||
var lon = parseFloat($longtitude.value);
|
||||
|
||||
waypoints.push({
|
||||
name, lat,lon,
|
||||
});
|
||||
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = (0).toPrecision(5);
|
||||
$longtitude.value = (0).toPrecision(5);
|
||||
});
|
||||
|
||||
$name_button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
|
||||
waypoints.push({
|
||||
name
|
||||
});
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = 0.0000
|
||||
$longtitude.value = 0.0000
|
||||
});
|
||||
|
||||
|
||||
function removeWaypoint(index){
|
||||
$name.value = waypoints[index].name
|
||||
$latitude.value = waypoints[index].lat
|
||||
$longtitude.value = waypoints[index].lon
|
||||
waypoints = waypoints.filter((p,i) => i!==index)
|
||||
renderWaypoints()
|
||||
}
|
||||
|
||||
function renderWaypoints(){
|
||||
$list.innerHTML = ''
|
||||
waypoints.forEach((waypoint,index) => {
|
||||
var $waypoint = document.createElement('tr')
|
||||
if (index==0){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td>`
|
||||
} else if(waypoint.lat==undefined){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>------</td><td>-----</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
} else {
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>${waypoint.lat}</td><td>${waypoint.lon}</td><td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-edit"></i></button></td>`
|
||||
}
|
||||
$list.appendChild($waypoint)
|
||||
})
|
||||
$name.focus()
|
||||
}
|
||||
|
||||
function downloadJSONfile(fileid, callback) {
|
||||
Puck.write(`\x10(function() {
|
||||
var pts = require("Storage").readJSON("${fileid}")||[{name:"NONE"}];
|
||||
Bluetooth.print(JSON.stringify(pts));
|
||||
})()\n`,contents=>{
|
||||
var storedpts = JSON.parse(contents);
|
||||
callback(storedpts);
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFile(fileid, contents) {
|
||||
Puck.write(`\x10(function() {
|
||||
require("Storage").write("${fileid}",'${contents}');
|
||||
Bluetooth.print("OK");
|
||||
})()\n`,ret=>{
|
||||
console.log("uploadFile",ret);
|
||||
});
|
||||
}
|
||||
|
||||
function gotStored(pts){
|
||||
waypoints = pts;
|
||||
renderWaypoints();
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
}
|
||||
|
||||
document.getElementById("Download").addEventListener("click", function() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
});
|
||||
|
||||
document.getElementById("Upload").addEventListener("click", function() {
|
||||
var data = JSON.stringify(waypoints);
|
||||
uploadFile("waypoints.json",data);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
},
|
||||
{ "name":"WP0" },
|
||||
{ "name":"WP1" },
|
||||
{ "name":"WP2" },
|
||||
{ "name":"WP3" },
|
||||
{ "name":"WP4" }
|
||||
]
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,56 @@
|
|||
# Waypoints
|
||||
|
||||
This app provides a common way to set up the `waypoints.json` file,
|
||||
which several other apps rely on for navigation.
|
||||
|
||||
## Waypoint JSON file
|
||||
|
||||
When the app is loaded from the app loader, a file named
|
||||
`waypoints.json` is loaded along with the javascript etc. The file
|
||||
has the following contents:
|
||||
|
||||
|
||||
```
|
||||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
},
|
||||
{ "name":"WP0" },
|
||||
{ "name":"WP1" },
|
||||
{ "name":"WP2" },
|
||||
{ "name":"WP3" },
|
||||
{ "name":"WP4" }
|
||||
]
|
||||
```
|
||||
|
||||
The file contains the initial NONE waypoint which is useful if you
|
||||
just want to display course and speed. The next two entries are
|
||||
waypoints to No 10 Downing Street and to Stone Henge - obtained from
|
||||
Google Maps. The last five entries are entries which can be *marked*.
|
||||
|
||||
You add and delete entries using the Web IDE to load and then save
|
||||
the file from and to watch storage. The app itself does not limit the
|
||||
number of entries although it does load the entire file into RAM
|
||||
which will obviously limit this.
|
||||
|
||||
|
||||
## Waypoint Editor
|
||||
|
||||
Clicking on the download icon of `Waypoints` in the app loader invokes the
|
||||
waypoint editor. The editor downloads and displays the current
|
||||
`waypoints.json` file. Clicking the `Edit` button beside an entry
|
||||
causes the entry to be deleted from the list and displayed in the
|
||||
edit boxes. It can be restored - by clicking the `Add waypoint`
|
||||
button. A new markable entry is created by using the `Add name`
|
||||
button. The edited `waypoints.json` file is uploaded to the Bangle by
|
||||
clicking the `Upload` button.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="))
|
|
@ -0,0 +1,34 @@
|
|||
// place your const, vars, functions or classes here
|
||||
|
||||
// clear the screen
|
||||
g.clear();
|
||||
|
||||
var n = 0;
|
||||
|
||||
// redraw the screen
|
||||
function draw() {
|
||||
g.reset().clearRect(Bangle.appRect);
|
||||
g.setFont("6x8").setFontAlign(0,0).drawString("Up / Down",g.getWidth()/2,g.getHeight()/2 - 20);
|
||||
g.setFont("Vector",60).setFontAlign(0,0).drawString(n,g.getWidth()/2,g.getHeight()/2 + 30);
|
||||
}
|
||||
|
||||
// Respond to user input
|
||||
Bangle.setUI({mode: "updown"}, function(dir) {
|
||||
if (dir<0) {
|
||||
n--;
|
||||
draw();
|
||||
} else if (dir>0) {
|
||||
n++;
|
||||
draw();
|
||||
} else {
|
||||
n = 0;
|
||||
draw();
|
||||
}
|
||||
});
|
||||
|
||||
// First draw...
|
||||
draw();
|
||||
|
||||
// Load widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -4,6 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css">
|
||||
|
||||
|
@ -11,6 +12,8 @@
|
|||
html, body { height: 100% }
|
||||
.flex-col { display:flex; flex-direction:column; height:100% }
|
||||
#map { width:100%; height:100% }
|
||||
#tab-map { width:100%; height:100% }
|
||||
#tab-list { width:100%; height:100% }
|
||||
|
||||
/* https://stackoverflow.com/a/58686215 */
|
||||
.arrow-icon {
|
||||
|
@ -23,6 +26,7 @@
|
|||
transform-origin: center center;
|
||||
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -32,8 +36,57 @@
|
|||
<span id="status"></span>
|
||||
<span id="routestatus"></span>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="tab tab-block">
|
||||
<li class="tab-item active" id="tabitem-map">
|
||||
<a href="#">Map</a>
|
||||
</li>
|
||||
<li class="tab-item" id="tabitem-list">
|
||||
<a href="#">List</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="flex: 1">
|
||||
<div id="tab-map">
|
||||
<div id="map"></div>
|
||||
</div>
|
||||
<div id="tab-list" style="display:none">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Lat.</th>
|
||||
<th>Long.</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="waypoints">
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h4>Add a new waypoint</h4>
|
||||
<form id="add_waypoint_form">
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" type="text" id="add_waypoint_name" placeholder="Name">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_latitude" placeholder="Lat">
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<input class="form-input input-sm" value="0.0000" type="number" step="any" id="add_longtitude" placeholder="Long">
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_name_button" class="btn btn-primary btn-sm">Add Name Only</button>
|
||||
</div>
|
||||
<div class="column col-3 col-xs-8">
|
||||
<button id="add_waypoint_button" class="btn btn-primary btn-sm">Add Waypoint</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -44,8 +97,23 @@
|
|||
<script src="../../core/lib/interface.js"></script>
|
||||
|
||||
<script>
|
||||
var map;
|
||||
var waypoints = [];
|
||||
|
||||
// ========================================================================== tabs
|
||||
document.getElementById('tabitem-map').addEventListener('click',function() {
|
||||
document.getElementById('tabitem-map').classList.remove("active");
|
||||
document.getElementById('tabitem-list').classList.add("active");
|
||||
document.getElementById('tab-map').style.display="block";
|
||||
document.getElementById('tab-list').style.display="none";
|
||||
});
|
||||
document.getElementById('tabitem-list').addEventListener('click',function() {
|
||||
document.getElementById('tabitem-map').classList.add("active");
|
||||
document.getElementById('tabitem-list').classList.remove("active");
|
||||
document.getElementById('tab-map').style.display="none";
|
||||
document.getElementById('tab-list').style.display="block";
|
||||
});
|
||||
// ========================================================================== MAP
|
||||
var map;
|
||||
var mapmarkers = L.layerGroup();
|
||||
var searchresult = L.layerGroup();
|
||||
var dynamicarrow = L.layerGroup();
|
||||
|
@ -100,9 +168,6 @@
|
|||
L.featureGroup(getArrows(latlngs, 'black', 2, map)).addTo(dynamicarrow)
|
||||
map.addLayer(dynamicarrow);
|
||||
});
|
||||
clean();
|
||||
renderAllWaypoints();
|
||||
|
||||
/*** status ***/
|
||||
|
||||
function clean() {
|
||||
|
@ -152,11 +217,11 @@
|
|||
dirty();
|
||||
}
|
||||
|
||||
function renderWaypoints(wps, isroute, parentidx) {
|
||||
function renderWaypointsMap(wps, isroute, parentidx) {
|
||||
var latlngs = [];
|
||||
for (var i = 0; i < wps.length; i++) {
|
||||
if (wps[i].route) {
|
||||
renderWaypoints(wps[i].route, true, i);
|
||||
renderWaypointsMap(wps[i].route, true, i);
|
||||
continue;
|
||||
}
|
||||
if (wps[i].lat == null || wps[i].lon == null)
|
||||
|
@ -182,7 +247,8 @@
|
|||
|
||||
function renderAllWaypoints() {
|
||||
mapmarkers.clearLayers();
|
||||
renderWaypoints(waypoints, false, 0);
|
||||
renderWaypointsMap(waypoints, false, 0);
|
||||
renderWaypointsList();
|
||||
map.addLayer(mapmarkers);
|
||||
}
|
||||
|
||||
|
@ -234,51 +300,18 @@
|
|||
|
||||
/*** Bangle.js ***/
|
||||
|
||||
function downloadJSONfile(fileid, callback) {
|
||||
Puck.write(`\x10(function() {
|
||||
var pts = require("Storage").readJSON("${fileid}")||[{name:"NONE"}];
|
||||
Bluetooth.print(JSON.stringify(pts));
|
||||
})()\n`, contents => {
|
||||
var storedpts = JSON.parse(contents);
|
||||
callback(storedpts);
|
||||
clean();
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFile(fileid, contents) {
|
||||
Puck.write(`\x10(function() {
|
||||
require("Storage").write("${fileid}",'${contents}');
|
||||
Bluetooth.print("OK");
|
||||
})()\n`, ret => {
|
||||
console.log("uploadFile", ret);
|
||||
if (ret == "OK")
|
||||
clean();
|
||||
});
|
||||
}
|
||||
|
||||
function gotStored(pts) {
|
||||
waypoints = pts;
|
||||
|
||||
var latlngs = waypoints.map(p => [p.lat, p.lon]);
|
||||
var latlngs = waypoints.filter(p => isFinite(p.lat)&&isFinite(p.lon)).map(p => [p.lat, p.lon]);
|
||||
var poly = L.polygon(latlngs);
|
||||
map.fitBounds(poly.getBounds());
|
||||
var bounds = poly.getBounds();
|
||||
if (bounds.isValid())
|
||||
map.fitBounds(bounds);
|
||||
|
||||
renderAllWaypoints();
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
}
|
||||
|
||||
$('#download').on('click', function() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
});
|
||||
|
||||
$('#upload').click(function() {
|
||||
var data = JSON.stringify(waypoints);
|
||||
uploadFile("waypoints.json",data);
|
||||
});
|
||||
|
||||
$('#statusarea').click(closeRoute);
|
||||
|
||||
/*** map arrows ***/
|
||||
|
@ -348,5 +381,136 @@
|
|||
this.x = (round ? Math.round(x) : x);
|
||||
this.y = (round ? Math.round(y) : y);
|
||||
}
|
||||
|
||||
// ========================================================================== LIST
|
||||
|
||||
var $name = document.getElementById('add_waypoint_name')
|
||||
var $form = document.getElementById('add_waypoint_form')
|
||||
var $button = document.getElementById('add_waypoint_button')
|
||||
var $name_button = document.getElementById('add_name_button')
|
||||
var $latitude = document.getElementById('add_latitude')
|
||||
var $longtitude = document.getElementById('add_longtitude')
|
||||
var $list = document.getElementById('waypoints')
|
||||
|
||||
function compare(a, b){
|
||||
var x = a.name.toLowerCase();
|
||||
var y = b.name.toLowerCase();
|
||||
if (x=="none") {return -1};
|
||||
if (y=="none") {return 1};
|
||||
if (x < y) {return -1;}
|
||||
if (x > y) {return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
$button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
var lat = parseFloat($latitude.value);
|
||||
var lon = parseFloat($longtitude.value);
|
||||
|
||||
waypoints.push({
|
||||
name, lat,lon,
|
||||
});
|
||||
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderAllWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = (0).toPrecision(5);
|
||||
$longtitude.value = (0).toPrecision(5);
|
||||
});
|
||||
|
||||
$name_button.addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
var name = $name.value.trim()
|
||||
if(!name) return;
|
||||
|
||||
waypoints.push({
|
||||
name
|
||||
});
|
||||
waypoints.sort(compare);
|
||||
|
||||
renderAllWaypoints()
|
||||
$name.value = ''
|
||||
$latitude.value = 0.0000
|
||||
$longtitude.value = 0.0000
|
||||
});
|
||||
|
||||
|
||||
function removeWaypoint(index){
|
||||
$name.value = waypoints[index].name
|
||||
$latitude.value = waypoints[index].lat
|
||||
$longtitude.value = waypoints[index].lon
|
||||
waypoints = waypoints.filter((p,i) => i!==index)
|
||||
renderAllWaypoints()
|
||||
}
|
||||
|
||||
function renderWaypointsList(){
|
||||
$list.innerHTML = ''
|
||||
waypoints.forEach((waypoint,index) => {
|
||||
var $waypoint = document.createElement('tr')
|
||||
if (index==0){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td></td><td></td>`
|
||||
} else if(waypoint.lat==undefined){
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>------</td><td>-----</td>`;
|
||||
} else {
|
||||
$waypoint.innerHTML = `<td>${waypoint.name}</td><td>${waypoint.lat.toFixed(6)}</td><td>${waypoint.lon.toFixed(6)}</td>`;
|
||||
}
|
||||
$waypoint.innerHTML += `<td><button class="btn btn-action btn-primary" onclick="removeWaypoint(${index})"><i class="icon icon-delete"></i></button></td>`;
|
||||
$list.appendChild($waypoint)
|
||||
})
|
||||
$name.focus()
|
||||
}
|
||||
|
||||
function renderWaypoints() {
|
||||
renderWaypointsList();
|
||||
renderWaypointsMap();
|
||||
}
|
||||
|
||||
// ========================================================================== UPLOAD/DOWNLOAD
|
||||
|
||||
function downloadJSONfile(fileid, callback) {
|
||||
// TODO: use interface.js-provided stuff?
|
||||
Puck.write(`\x10(function() {
|
||||
var pts = require("Storage").readJSON("${fileid}")||[{name:"NONE"}];
|
||||
Bluetooth.print(JSON.stringify(pts));
|
||||
})()\n`, contents => {
|
||||
if (contents=='[{name:"NONE"}]') contents="[]";
|
||||
var storedpts = JSON.parse(contents);
|
||||
callback(storedpts);
|
||||
clean();
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFile(fileid, contents) {
|
||||
// TODO: use interface.js-provided stuff?
|
||||
Puck.write(`\x10(function() {
|
||||
require("Storage").write("${fileid}",'${contents}');
|
||||
Bluetooth.print("OK");
|
||||
})()\n`, ret => {
|
||||
console.log("uploadFile", ret);
|
||||
if (ret == "OK")
|
||||
clean();
|
||||
});
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
}
|
||||
|
||||
$('#download').on('click', function() {
|
||||
downloadJSONfile("waypoints.json", gotStored);
|
||||
});
|
||||
|
||||
$('#upload').click(function() {
|
||||
var data = JSON.stringify(waypoints);
|
||||
uploadFile("waypoints.json",data);
|
||||
});
|
||||
|
||||
// ========================================================================== FINALLY...
|
||||
clean();
|
||||
renderAllWaypoints();
|
||||
</script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
exports.load = (num) => {
|
||||
return require("Storage").readJSON(`waypoints${num?`.${num}`:""}.json`)||[{name:"NONE"}];
|
||||
};
|
||||
|
||||
exports.save = (waypoints,num) => {
|
||||
require("Storage").writeJSON(`waypoints${num?`.${num}`:""}.json`, waypoints);
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
{ "id": "waypoints",
|
||||
"name": "Waypoints",
|
||||
"version":"0.01",
|
||||
"description": "Provides 'waypoints.json' used by various navigation apps, as well as a way to edit it from the App Loader with maps or a list",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"type": "waypoints",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"interface": "interface.html",
|
||||
"storage": [
|
||||
{"name":"waypoints","url":"lib.js"}
|
||||
],
|
||||
"data": [
|
||||
{"name":"waypoints.json","url":"waypoints.json"},
|
||||
{"name":"waypoints.1.json"},
|
||||
{"name":"waypoints.2.json"},
|
||||
{"name":"waypoints.3.json"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
[
|
||||
{
|
||||
"name":"No10",
|
||||
"lat":51.5032,
|
||||
"lon":-0.1269
|
||||
},
|
||||
{
|
||||
"name":"Stone",
|
||||
"lat":51.1788,
|
||||
"lon":-1.8260
|
||||
}
|
||||
]
|
|
@ -1,2 +1,3 @@
|
|||
...
|
||||
0.02: First update with ChangeLog Added
|
||||
0.03: Move waypoints.json (and editor) to 'waypoints' app
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var loc = require("locale");
|
||||
|
||||
var waypoints = require("Storage").readJSON("waypoints.json") || [];
|
||||
var waypoints = require("waypoints").load();
|
||||
var wp = waypoints[0];
|
||||
if (wp == undefined) wp = {name:"NONE"};
|
||||
var wp_bearing = 0;
|
||||
|
@ -196,7 +196,7 @@ function addCurrentWaypoint() {
|
|||
}
|
||||
|
||||
function saveWaypoints() {
|
||||
require("Storage").writeJSON("waypoints.json", waypoints);
|
||||
require("waypoints").save(waypoints);
|
||||
}
|
||||
|
||||
function deleteWaypoint(w) {
|
||||
|
|
|
@ -2,17 +2,16 @@
|
|||
"id": "wpmoto",
|
||||
"name": "Waypointer Moto",
|
||||
"shortName": "Waypointer Moto",
|
||||
"version": "0.02",
|
||||
"version": "0.03",
|
||||
"description": "Waypoint-based motorcycle navigation aid",
|
||||
"icon": "wpmoto.png",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot-menu.png"},{"url":"screenshot-delete.png"}],
|
||||
"readme": "README.md",
|
||||
"interface": "wpmoto.html",
|
||||
"dependencies" : { "waypoints":"type" },
|
||||
"storage": [
|
||||
{"name":"wpmoto.app.js","url":"app.js"},
|
||||
{"name":"wpmoto.img","url":"icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"waypoints.json","url":"waypoints.json"}]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
]
|
|
@ -77,12 +77,13 @@ const APP_KEYS = [
|
|||
const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports'];
|
||||
const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate'];
|
||||
const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports'
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale","settings"]; // values allowed for "type" field
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale","settings","waypoints"]; // values allowed for "type" field
|
||||
const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
|
||||
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
|
||||
const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"];
|
||||
const INTERNAL_FILES_IN_APP_TYPE = { // list of app types and files they SHOULD provide...
|
||||
'textinput' : ['textinput'],
|
||||
'waypoints' : ['waypoints'],
|
||||
// notify?
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue