Merge branch 'master' of git@github.com:nujw/BangleApps.git
|
@ -6,3 +6,4 @@ package-lock.json
|
|||
appdates.csv
|
||||
.vscode
|
||||
.idea/
|
||||
_config.yml
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
theme: jekyll-theme-leap-day
|
130
apps.json
|
@ -53,7 +53,7 @@
|
|||
{ "id": "about",
|
||||
"name": "About",
|
||||
"icon": "app.png",
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers",
|
||||
"tags": "tool,system",
|
||||
"allow_emulator":true,
|
||||
|
@ -80,7 +80,7 @@
|
|||
"name": "Notifications (default)",
|
||||
"shortName":"Notifications",
|
||||
"icon": "notify.png",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"description": "A handler for displaying notifications that displays them in a bar at the top of the screen",
|
||||
"tags": "widget",
|
||||
"type": "notify",
|
||||
|
@ -93,7 +93,7 @@
|
|||
"name": "Fullscreen Notifications",
|
||||
"shortName":"Notifications",
|
||||
"icon": "notify.png",
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"description": "A handler for displaying notifications that displays them fullscreen. This may not fully restore the screen after on some apps. See `Notifications (default)` for more information about the notifications library.",
|
||||
"tags": "widget",
|
||||
"type": "notify",
|
||||
|
@ -139,7 +139,7 @@
|
|||
{ "id": "gbridge",
|
||||
"name": "Gadgetbridge",
|
||||
"icon": "app.png",
|
||||
"version":"0.18",
|
||||
"version":"0.20",
|
||||
"description": "The default notification handler for Gadgetbridge notifications from Android",
|
||||
"tags": "tool,system,android,widget",
|
||||
"readme": "README.md",
|
||||
|
@ -363,7 +363,7 @@
|
|||
{ "id": "gpsrec",
|
||||
"name": "GPS Recorder",
|
||||
"icon": "app.png",
|
||||
"version":"0.16",
|
||||
"version":"0.17",
|
||||
"interface": "interface.html",
|
||||
"description": "Application that allows you to record a GPS track. Can run in background",
|
||||
"tags": "tool,outdoors,gps,widget",
|
||||
|
@ -1153,7 +1153,7 @@
|
|||
"name": "Commandline-Clock",
|
||||
"shortName":"CLI-Clock",
|
||||
"icon": "app.png",
|
||||
"version":"0.09",
|
||||
"version":"0.11",
|
||||
"description": "Simple CLI-Styled Clock",
|
||||
"tags": "clock,cli,command,bash,shell",
|
||||
"type":"clock",
|
||||
|
@ -1341,7 +1341,7 @@
|
|||
"name": "Active Pedometer",
|
||||
"shortName":"Active Pedometer",
|
||||
"icon": "app.png",
|
||||
"version":"0.06",
|
||||
"version":"0.09",
|
||||
"description": "Pedometer that filters out arm movement and displays a step goal progress. Steps are saved to a daily file and can be viewed as graph.",
|
||||
"tags": "outdoors,widget",
|
||||
"readme": "README.md",
|
||||
|
@ -1553,7 +1553,7 @@
|
|||
"name": "BangleRun",
|
||||
"shortName": "BangleRun",
|
||||
"icon": "banglerun.png",
|
||||
"version": "0.07",
|
||||
"version": "0.09",
|
||||
"interface": "interface.html",
|
||||
"description": "An app for running sessions. Displays info and logs your run for later viewing.",
|
||||
"tags": "run,running,fitness,outdoors",
|
||||
|
@ -1638,7 +1638,7 @@
|
|||
"name": "Round clock with seconds, minutes and date",
|
||||
"shortName":"Round Clock",
|
||||
"icon": "app.png",
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "Designed round clock with ticks for minutes and seconds and heart rate indication",
|
||||
"tags": "clock",
|
||||
"type": "clock",
|
||||
|
@ -2139,7 +2139,7 @@
|
|||
{ "id": "multiclock",
|
||||
"name": "Multi Clock",
|
||||
"icon": "multiclock.png",
|
||||
"version":"0.11",
|
||||
"version":"0.12",
|
||||
"description": "Clock with multiple faces - Big, Analogue, Digital, Text, Time-Date.\n Switch between faces with BTN1 & BTN3",
|
||||
"readme": "README.md",
|
||||
"tags": "clock",
|
||||
|
@ -2153,8 +2153,6 @@
|
|||
{"name":"txt.face.js","url":"txt.js"},
|
||||
{"name":"timdat.face.js","url":"timdat.js"},
|
||||
{"name":"ped.face.js","url":"ped.js"},
|
||||
{"name":"gps.face.js","url":"gps.js"},
|
||||
{"name":"osref.face.js","url":"osref.js"},
|
||||
{"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
|
@ -2189,6 +2187,23 @@
|
|||
{"wildcard":"accelrec.?.csv" }
|
||||
]
|
||||
},
|
||||
{ "id": "accellog",
|
||||
"name": "Acceleration Logger",
|
||||
"shortName":"Accel Log",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"interface": "interface.html",
|
||||
"description": "Logs XYZ acceleration data to a CSV file that can be downloaded to your PC",
|
||||
"tags": "outdoor",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"accellog.app.js","url":"app.js"},
|
||||
{"name":"accellog.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [
|
||||
{"wildcard":"accellog.?.csv" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cprassist",
|
||||
"name":"CPR Assist",
|
||||
|
@ -2298,7 +2313,7 @@
|
|||
"name": "File manager",
|
||||
"shortName":"FileManager",
|
||||
"icon": "icons8-filing-cabinet-48.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Simple file manager, allows user to examine watch storage and display, load or delete individual files",
|
||||
"tags": "tools",
|
||||
"readme": "README.md",
|
||||
|
@ -2655,7 +2670,7 @@
|
|||
"name": "Low power GPS Service",
|
||||
"shortName":"GPS Service",
|
||||
"icon": "gpsservice.png",
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "low power GPS widget",
|
||||
"tags": "gps outdoors navigation",
|
||||
"readme": "README.md",
|
||||
|
@ -2692,5 +2707,92 @@
|
|||
{"name":"intervals.app.js","url":"intervals.app.js"},
|
||||
{"name":"intervals.img","url":"intervals-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "planetarium",
|
||||
"name": "Planetarium",
|
||||
"shortName":"Planetarium",
|
||||
"icon": "planetarium.png",
|
||||
"readme": "README.md",
|
||||
"version":"0.03",
|
||||
"description": "Planetarium showing up to 500 stars using the watch location and time",
|
||||
"tags": "",
|
||||
"storage": [
|
||||
{"name":"planetarium.app.js","url":"planetarium.app.js"},
|
||||
{"name":"planetarium.data.csv","url":"planetarium.data.csv"},
|
||||
{"name":"planetarium.const.csv","url":"planetarium.const.csv"},
|
||||
{"name":"planetarium.extra.csv","url":"planetarium.extra.csv"},
|
||||
{"name":"planetarium.settings.js","url":"settings.js"},
|
||||
{"name":"planetarium.img","url":"planetarium-icon.js","evaluate":true}
|
||||
],
|
||||
"data":[
|
||||
{"name":"planetarium.json"}
|
||||
]
|
||||
},
|
||||
{ "id": "tapelauncher",
|
||||
"name": "Tape Launcher",
|
||||
"icon": "icon.png",
|
||||
"version":"0.02",
|
||||
"description": "An App launcher, icons displayed in a horizontal tape, swipe or use buttons",
|
||||
"readme": "README.md",
|
||||
"tags": "tool,system,launcher",
|
||||
"type":"launch",
|
||||
"storage": [
|
||||
{"name":"tapelauncher.app.js","url":"app.js"},
|
||||
{"name":"tapelauncher.img","url":"icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "oblique",
|
||||
"name": "Oblique Strategies",
|
||||
"icon": "eno.png",
|
||||
"version": "0.01",
|
||||
"description": "Oblique Strategies for creativity. Copied from Brian Eno.",
|
||||
"tags": "tool",
|
||||
"storage": [
|
||||
{"name":"oblique.app.js","url":"app.js"},
|
||||
{"name":"oblique.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "testuserinput",
|
||||
"name": "Test User Input",
|
||||
"shortName":"Test User Input",
|
||||
"icon": "app.png",
|
||||
"readme": "README.md",
|
||||
"version":"0.02",
|
||||
"description": "Basic app to test the bangle.js input interface. It displays the result in text or a switch on/off image.",
|
||||
"tags": "input,interface,buttons,touch",
|
||||
"storage": [
|
||||
{"name":"testuserinput.app.js","url":"app.js"},
|
||||
{"name":"testuserinput.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "gpssetup",
|
||||
"name": "GPS Setup",
|
||||
"shortName":"GPS Setup",
|
||||
"icon": "gpssetup.png",
|
||||
"version":"0.02",
|
||||
"description": "Configure the GPS power options and store them in the GPS nvram",
|
||||
"tags": "gps, tools, outdoors",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"gpssetup","url":"gpssetup.js"},
|
||||
{"name":"gpssetup.settings.js","url":"settings.js"},
|
||||
{"name":"gpssetup.settings.json","url":"settings.json"},
|
||||
{"name":"gpssetup.app.js","url":"app.js"},
|
||||
{"name":"gpssetup.img","url":"icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "walkersclock",
|
||||
"name": "Walkers Clock",
|
||||
"shortName":"Walkers Clock",
|
||||
"icon": "walkersclock48.png",
|
||||
"version":"0.01",
|
||||
"description": "A larg font watch, displays steps, can switch GPS on/off, displays grid reference",
|
||||
"type":"clock",
|
||||
"tags": "clock, gps, tools, outdoors",
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"walkersclock.app.js","url":"app.js"},
|
||||
{"name":"walkersclock.img","url":"icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
// TODO: "no-undef": "warn",
|
||||
"no-undef": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-useless-escape": "off"
|
||||
"no-useless-escape": "off",
|
||||
"no-control-regex" : "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.04: Actual pixels as of 9 Mar 2020
|
||||
0.05: Actual pixels as of 27 Apr 2020
|
||||
0.06: Actual pixels as of 12 Jun 2020
|
||||
0.07: Pressing a button now exits immediately (fix #618)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,19 @@
|
|||
# Acceleration Logger
|
||||
|
||||
Logs XYZ acceleration data (at the normal 12.5Hz) to a CSV file that can be downloaded to your PC.
|
||||
|
||||
## Usage
|
||||
|
||||
* Run the app 'Accel Log' from Bangle.js menu
|
||||
* Optionally choose a file number if you want to record to multiple different files.
|
||||
* Choose `Start`
|
||||
* Acceleration data will now be recording
|
||||
* When you're done, press `BTN2`
|
||||
|
||||
## Downloading Data
|
||||
|
||||
* Go to the Bangle.js App Loader
|
||||
* Connect to your Bangle
|
||||
* Under `My Apps` look for `Acceleration Logger`
|
||||
* You'll see a download arrow next to it - click that
|
||||
* You can now choose to Save or Delete each track you have recorded
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("oFAwhC/AH4A2xAedhGIwA+dAAI+dAAJAcEAJ/fD/4f5hAJIYSo6JIihaKxBATxAACC4YnBAAQ+TD7o/CFRJfTP5a/eb6pEOD/7JFwczAA0ybgwfUkUjD4QaDD6syiMSD4ZABCIa8JD547BCIY/ZHQQ+LD6Z/cHZYf/f6E4D6uCD4gACD6wgBkQACBAYfWABYf/D/4fPwf/ABgf/D6czABBf/P/5f/P/5f/D+WIABwfuAH4A/ADo="))
|
|
@ -0,0 +1,132 @@
|
|||
var fileNumber = 0;
|
||||
var MAXLOGS = 9;
|
||||
|
||||
function getFileName(n) {
|
||||
return "accellog."+n+".csv";
|
||||
}
|
||||
|
||||
function showMenu() {
|
||||
var menu = {
|
||||
"" : { title : "Accel Logger" },
|
||||
"File No" : {
|
||||
value : fileNumber,
|
||||
min : 0,
|
||||
max : MAXLOGS,
|
||||
onchange : v => { fileNumber=v; }
|
||||
},
|
||||
"Start" : function() {
|
||||
E.showMenu();
|
||||
startRecord();
|
||||
},
|
||||
"View Logs" : function() {
|
||||
viewLogs();
|
||||
},
|
||||
"Exit" : function() {
|
||||
load();
|
||||
},
|
||||
};
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function viewLog(n) {
|
||||
E.showMessage("Loading...");
|
||||
var f = require("Storage").open(getFileName(n), "r");
|
||||
var records = 0, l = "", ll="";
|
||||
while ((l=f.readLine())!==undefined) {records++;ll=l;}
|
||||
var length = 0;
|
||||
if (ll) length = (ll.split(",")[0]|0)/1000;
|
||||
|
||||
var menu = {
|
||||
"" : { title : "Log "+n }
|
||||
};
|
||||
menu[records+" Records"] = "";
|
||||
menu[length+" Seconds"] = "";
|
||||
menu["DELETE"] = function() {
|
||||
E.showPrompt("Delete Log "+n).then(ok=>{
|
||||
if (ok) {
|
||||
E.showMessage("Erasing...");
|
||||
f.erase();
|
||||
viewLogs();
|
||||
} else viewLog(n);
|
||||
});
|
||||
};
|
||||
menu["< Back"] = function() {
|
||||
viewLogs();
|
||||
};
|
||||
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function viewLogs() {
|
||||
var menu = {
|
||||
"" : { title : "Logs" }
|
||||
};
|
||||
|
||||
var hadLogs = false;
|
||||
for (var i=0;i<=MAXLOGS;i++) {
|
||||
var f = require("Storage").open(getFileName(i), "r");
|
||||
if (f.readLine()!==undefined) {
|
||||
(function(i) {
|
||||
menu["Log "+i] = () => viewLog(i);
|
||||
})(i);
|
||||
hadLogs = true;
|
||||
}
|
||||
}
|
||||
if (!hadLogs)
|
||||
menu["No Logs Found"] = function(){};
|
||||
menu["< Back"] = function() { showMenu(); };
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function startRecord(force) {
|
||||
if (!force) {
|
||||
// check for existing file
|
||||
var f = require("Storage").open(getFileName(fileNumber), "r");
|
||||
if (f.readLine()!==undefined)
|
||||
return E.showPrompt("Overwrite Log "+fileNumber+"?").then(ok=>{
|
||||
if (ok) startRecord(true); else showMenu();
|
||||
});
|
||||
}
|
||||
// display
|
||||
g.clear(1);
|
||||
Bangle.drawWidgets();
|
||||
var w = g.getWidth();
|
||||
var h = g.getHeight();
|
||||
g.setColor("#ff0000").fillRect(0,h-48,w,h);
|
||||
g.setColor("#ffffff").setFont("6x8",2).setFontAlign(0,0).drawString("RECORDING", w/2,h-24);
|
||||
g.setFont("6x8").drawString("Samples:",w/2,h/3 - 20);
|
||||
g.setFont("6x8").drawString("Time:",w/2,h*2/3 - 20);
|
||||
g.setFont("6x8",2).setFontAlign(0,0,1).drawString("STOP",w-10,h/2);
|
||||
|
||||
// now start writing
|
||||
f = require("Storage").open(getFileName(fileNumber), "w");
|
||||
f.write("Time (ms),X,Y,Z\n");
|
||||
var start = getTime();
|
||||
var sampleCount = 0;
|
||||
|
||||
function accelHandler(accel) {
|
||||
var t = getTime()-start;
|
||||
f.write([
|
||||
t*1000,
|
||||
accel.x*8192,
|
||||
accel.y*8192,
|
||||
accel.z*8192].map(n=>Math.round(n)).join(",")+"\n");
|
||||
|
||||
sampleCount++;
|
||||
g.reset().setFont("6x8",2).setFontAlign(0,0);
|
||||
g.drawString(" "+sampleCount+" ",w/2,h/3,true);
|
||||
g.drawString(" "+Math.round(t)+"s ",w/2,h*2/3,true);
|
||||
}
|
||||
|
||||
Bangle.setPollInterval(80); // 12.5 Hz
|
||||
Bangle.on('accel', accelHandler);
|
||||
setWatch(()=>{
|
||||
Bangle.removeListener('accel', accelHandler);
|
||||
showMenu();
|
||||
}, BTN2);
|
||||
}
|
||||
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
showMenu();
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,107 @@
|
|||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="data"></div>
|
||||
|
||||
<script src="../../core/lib/interface.js"></script>
|
||||
<script>
|
||||
var dataElement = document.getElementById("data");
|
||||
|
||||
function getData() {
|
||||
// show loading window
|
||||
Util.showModal("Loading...");
|
||||
// get the data
|
||||
dataElement.innerHTML = "";
|
||||
var promise = Promise.resolve();
|
||||
Puck.eval('require("Storage").list(/accellog\\..\\.csv\\x01/)',files=>{
|
||||
if (files.length==0) {
|
||||
dataElement.innerHTML = "<p>No saved data</p>";
|
||||
} else {
|
||||
files.forEach(fn => {
|
||||
fn = fn.slice(0,-1);
|
||||
dataElement.innerHTML += `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">${fn}</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary" fn="${fn}" act="save">Save</button>
|
||||
<button class="btn" fn="${fn}" act="delete">Delete</button>
|
||||
</div>
|
||||
</div>`;
|
||||
promise = promise.then(function() {
|
||||
document.querySelector(`.btn[fn='${fn}'][act='save']`).addEventListener("click", function() {
|
||||
Util.readStorageFile(fn, function(data) {
|
||||
Util.saveCSV(fn.slice(0,-4), data);
|
||||
});
|
||||
});
|
||||
document.querySelector(`.btn[fn='${fn}'][act='delete']`).addEventListener("click", function() {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorageFile(fn, function() {
|
||||
Util.hideModal();
|
||||
getData();
|
||||
});
|
||||
});
|
||||
return new Promise(resolve=>{
|
||||
Puck.eval(`require("Storage").read(${JSON.stringify(fn)})`,csv=>{
|
||||
fileData[fn] = csv.trim();
|
||||
var el = document.querySelector(`.card-body[fn='${fn}']`);
|
||||
el.innerHTML = '<canvas width="400" height="100"></canvas>';
|
||||
var c = el.firstChild;
|
||||
var ctx = c.getContext("2d");
|
||||
var lines = csv.split("\n");
|
||||
var y = 50, sx = 400/lines.length, sy = 50/8;
|
||||
function plot(n) {
|
||||
var last;
|
||||
ctx.beginPath();
|
||||
lines.map((l,x)=>{
|
||||
l = l.split(",");
|
||||
var yc = y + parseFloat(l[n])*sy;
|
||||
if (!last) {
|
||||
ctx.moveTo(0, yc);
|
||||
} else {
|
||||
ctx.lineTo(x*sx, yc);
|
||||
}
|
||||
last = l;
|
||||
});
|
||||
ctx.stroke();
|
||||
};
|
||||
ctx.strokeStyle = 'red';
|
||||
plot(0);
|
||||
ctx.strokeStyle = 'green';
|
||||
plot(1);
|
||||
ctx.strokeStyle = 'blue';
|
||||
plot(2);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
// remove window
|
||||
Util.hideModal();
|
||||
});
|
||||
}
|
||||
|
||||
// You can call a utility function to save the data
|
||||
/*document.getElementById("btnSave").addEventListener("click", function() {
|
||||
Util.saveCSV("gpsdata", csvData);
|
||||
});
|
||||
// Or you can also delete the file
|
||||
document.getElementById("btnDelete").addEventListener("click", function() {
|
||||
Util.showModal("Deleting...");
|
||||
Util.eraseStorageFile("gpspoilog.csv", function() {
|
||||
Util.hideModal();
|
||||
getData();
|
||||
});
|
||||
});*/
|
||||
// Called when app starts
|
||||
function onInit() {
|
||||
getData();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,7 +1,8 @@
|
|||
# Acceleration Recorder
|
||||
|
||||
This app records a short period of acceleration data from the accelerometer
|
||||
and
|
||||
This app records a short period of acceleration data from the accelerometer at
|
||||
100Hz (starting when acceleration happens) and graphs it, working out max acceleration
|
||||
and max velocity. Data can also be downloaded to your PC.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -4,3 +4,6 @@
|
|||
0.04: Steps are set to 0 in log on new day
|
||||
0.05: Fix default step/distance display if it hasn't been set up first
|
||||
0.06: Added WIDGETS.activepedom.getSteps()
|
||||
0.07: Added settings to be able to hide line1 and line2 so there is no visible widget
|
||||
0.08: Fixed zero steps issue caused by 0.07
|
||||
0.09: Prettied up user interface, decluttered graphs
|
||||
|
|
|
@ -31,6 +31,7 @@ Steps are saved to a datafile every 5 minutes. You can watch a graph using the a
|
|||
* Step detection sensitivity from firmware can be configured
|
||||
* Steps are saved to a file and read-in at start (to not lose step progress)
|
||||
* Settings can be changed in Settings - App/widget settings - Active Pedometer
|
||||
* Can hide the widget display if required using settings
|
||||
|
||||
## Features App
|
||||
|
||||
|
|
|
@ -88,28 +88,40 @@
|
|||
times = undefined;
|
||||
|
||||
//steps
|
||||
var csvFile = storage.open(filename, "r");
|
||||
csvFile = storage.open(filename, "r");
|
||||
steps = getArrayFromCSV(csvFile, 1);
|
||||
first = first + " " + steps[0] + "/" + setting('stepGoal');
|
||||
last = last + " " + steps[steps.length-1] + "/" + setting('stepGoal');
|
||||
|
||||
//define y-axis grid labels
|
||||
stepsLastEntry = steps[steps.length-1];
|
||||
if (stepsLastEntry < 1000) gridyValue = 100;
|
||||
if (stepsLastEntry >= 1000 && stepsLastEntry < 10000) gridyValue = 1000;
|
||||
if (stepsLastEntry > 10000) gridyValue = 5000;
|
||||
// the labels on the y axis are fairly unreadable so minimise them
|
||||
if (stepsLastEntry < 1000) gridyValue = 500;
|
||||
if (stepsLastEntry >= 1000 && stepsLastEntry < 2000) gridyValue = 1000;
|
||||
if (stepsLastEntry >= 2000 && stepsLastEntry < 5000) gridyValue = 2000;
|
||||
if (stepsLastEntry >= 5000 && stepsLastEntry < 10000) gridyValue = 5000;
|
||||
if (stepsLastEntry >= 10000 && stepsLastEntry < 20000) gridyValue = 10000;
|
||||
if (stepsLastEntry > 20000) gridyValue = 20000;
|
||||
|
||||
//draw
|
||||
drawMenu();
|
||||
g.drawString("First: " + first, 10, 30);
|
||||
g.drawString(" Last: " + last, 10, 40);
|
||||
// draw the chart
|
||||
g.clear();
|
||||
g.setFont("6x8", 2);
|
||||
g.setColor(1,1,1);
|
||||
require("graph").drawLine(g, steps, {
|
||||
//title: "Steps Counted",
|
||||
//title: "Steps",
|
||||
axes : true,
|
||||
gridy : gridyValue,
|
||||
y : 60, //offset on screen
|
||||
x : 5, //offset on screen
|
||||
});
|
||||
|
||||
// show steps and duration of the chart
|
||||
g.setFont("6x8", 2);
|
||||
g.setColor(0,1,0);
|
||||
g.drawString("steps", 30, 24);
|
||||
g.drawString(stepsLastEntry, 30, 44);
|
||||
g.drawString((history/3600000) + " hrs", 30, 64);
|
||||
|
||||
//free memory from big variables
|
||||
allData = undefined;
|
||||
allDataFile = undefined;
|
||||
|
@ -117,11 +129,46 @@
|
|||
times = undefined;
|
||||
}
|
||||
|
||||
function getImage() {
|
||||
return require("heatshrink").decompress(atob("mEwwIGDvAEDgP+ApMD/4FVEZY1FABcP8AFDn/wAod/AocB//4AoUHAokPAokf5/8AocfAoc+j5HDvgFEvEf7+AAoP4AoJCC+E/54qCsE/wYkDn+AAos8AohZDj/AAohrEp4FEs5xEuJfDgF5Aon4GgYFBGgZOBnyJD+EeYgfgj4FEh6VD4AFDh+AAIJMCBoIFFLQQtBgYFCHIIFDjA3BC4I="));
|
||||
}
|
||||
|
||||
function drawMenu() {
|
||||
var x = 100;
|
||||
var y = 24;
|
||||
var stps ="-";
|
||||
var y_inc = 25;
|
||||
|
||||
g.clear();
|
||||
g.setFont("6x8", 1);
|
||||
g.drawString("BTN1:Timespan | BTN2:Draw", 20, 10);
|
||||
g.drawString("Timespan: " + history/1000/60/60 + " hours", 20, 20);
|
||||
g.setColor(1,1,1);
|
||||
g.drawImage(getImage(),0 ,60 , {scale:2} );
|
||||
g.setFont("6x8",2);
|
||||
|
||||
// timespan
|
||||
g.setColor('#7f8c8d');
|
||||
g.setFontAlign(-1,0);
|
||||
g.drawString("Timespan", x, y, true);
|
||||
y += y_inc;
|
||||
g.setColor('#bdc3c7');
|
||||
g.drawString(history/1000/60/60 + " hrs" , x, y, true);
|
||||
|
||||
// BTN1 info
|
||||
y += 2*y_inc;
|
||||
g.setColor('#7f8c8d');
|
||||
g.setFontAlign(-1,0);
|
||||
g.drawString("BTN1", x, y, true);
|
||||
y += y_inc;
|
||||
g.setColor('#bdc3c7');
|
||||
g.drawString("Timespan", x, y, true);
|
||||
|
||||
// BTN2 info
|
||||
y += 2*y_inc;
|
||||
g.setColor('#7f8c8d');
|
||||
g.setFontAlign(-1,0);
|
||||
g.drawString("BTN2", x, y, true);
|
||||
y += y_inc;
|
||||
g.setColor('#bdc3c7');
|
||||
g.drawString("Draw", x, y, true);
|
||||
}
|
||||
|
||||
setWatch(function() { //BTN1
|
||||
|
@ -140,7 +187,9 @@
|
|||
}, BTN1, {edge:"rising", debounce:50, repeat:true});
|
||||
|
||||
setWatch(function() { //BTN2
|
||||
g.setFont("6x8", 2);
|
||||
g.clear();
|
||||
g.setColor(1,1,1);
|
||||
g.setFont("6x8", 3);
|
||||
g.drawString ("Drawing...",30,60);
|
||||
drawGraph();
|
||||
}, BTN2, {edge:"rising", debounce:50, repeat:true});
|
||||
|
@ -161,5 +210,4 @@
|
|||
}
|
||||
|
||||
drawMenu();
|
||||
|
||||
})();
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
(function(back) {
|
||||
const SETTINGS_FILE = 'activepedom.settings.json';
|
||||
const LINES = ['Steps', 'Distance'];
|
||||
const LINES = ['Steps', 'Distance', 'Hide'];
|
||||
|
||||
// initialize with default settings...
|
||||
let s = {
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
|
||||
function draw() {
|
||||
var height = 23; //width is deined globally
|
||||
|
||||
distance = (stepsCounted * setting('stepLength')) / 100 /1000; //distance in km
|
||||
|
||||
//Check if same day
|
||||
|
@ -155,6 +156,12 @@
|
|||
}
|
||||
lastUpdate = date;
|
||||
|
||||
// not everyone likes a widget, having refreshed lastUpdate we can exit
|
||||
if (setting('lineOne') == 'Hide' && setting('lineTwo') == 'Hide') {
|
||||
settings = 0; //reset settings to save memory
|
||||
return;
|
||||
}
|
||||
|
||||
g.reset();
|
||||
g.clearRect(this.x, this.y, this.x+width, this.y+height);
|
||||
|
||||
|
|
|
@ -5,3 +5,5 @@
|
|||
0.05: Complete rewrite. New UI, GPS & HRM Kalman filters, activity logging
|
||||
0.06: Reading HDOP directly from the GPS event (needs Espruino 2v07 or above)
|
||||
0.07: Fixed GPS update, added guards against NaN values
|
||||
0.08: Fix issue with GPS coordinates being wrong after the first one
|
||||
0.09: Another GPS fix (log raw coordinates - not filtered ones)
|
||||
|
|
|
@ -1 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwMB/4ACx4ED/0DApP8AqAXB84GDg/DAgXj/+DCAUABgIFB4EAv4FCwEAj0PAoJPBgwFEgEfDgMOAoM/AoMegFAAoP8jkA8F/AoM8gP4DgP4nBvD/F4KQfwuAFE+A/CAoPgAofx8A/CKYRwELIIFDLII6BAoZSBLIYeC/0BwAFDgfAGAQFBHgf8g4BBIIUH/wFBSYMPAoXwAog/Bj4FEv4FDDQQCBQoQFCZYYFi/6KE/+P/4A="))
|
||||
require("heatshrink").decompress(atob("mEwwIHEuAEDgP8ApMDAqAXBjAGD/E8AgUcgF8CAX/BgIFBn//wAFCv//8PwAoP///5Aon/8AcB+IFB4AFB8P/34FBgfj/8fwAFB4f+g4cBg/H/w/Cg+HKQcPx4FEh4/CAoMfAocOj4/CKYRwELIIFDLII6BAoZSBLIYeCgP+v4FD/k/GAQFBHgcD/ABBIIX4gIFBSYPwAoUPAog/B8AFEwAFDDQQCBQoQFCZYYFigCKEgFwgAA=="))
|
||||
|
|
|
@ -1 +1 @@
|
|||
!function(){"use strict";const t={STOP:63488,PAUSE:65504,RUN:2016};function n(t,n,r){g.setColor(0),g.fillRect(n-60,r,n+60,r+30),g.setColor(65535),g.drawString(t,n,r)}function r(r){var e;g.setFontVector(30),g.setFontAlign(0,-1,0),n((r.distance/1e3).toFixed(2),60,55),n(function(t){const n=Math.round(t),r=Math.floor(n/3600),e=Math.floor(n/60)%60,o=n%60;return(r?r+":":"")+("0"+e).substr(-2)+":"+("0"+o).substr(-2)}(r.duration),180,55),n(function(t){if(t<.1667)return"__'__\"";const n=Math.round(1e3/t),r=Math.floor(n/60),e=n%60;return("0"+r).substr(-2)+"'"+("0"+e).substr(-2)+'"'}(r.speed),60,115),n(r.hr.toFixed(0),180,115),n(r.steps.toFixed(0),60,175),n(r.cadence.toFixed(0),180,175),g.setFont("6x8",2),g.setColor(r.gpsValid?2016:63488),g.fillRect(0,216,80,240),g.setColor(0),g.drawString("GPS",40,220),g.setColor(65535),g.fillRect(80,216,160,240),g.setColor(0),g.drawString(("0"+(e=new Date).getHours()).substr(-2)+":"+("0"+e.getMinutes()).substr(-2),120,220),g.setColor(t[r.status]),g.fillRect(160,216,240,240),g.setColor(0),g.drawString(r.status,200,220)}function e(t){g.clear(),g.setColor(50712),g.setFont("6x8",2),g.setFontAlign(0,-1,0),g.drawString("DIST (KM)",60,32),g.drawString("TIME",180,32),g.drawString("PACE",60,92),g.drawString("HEART",180,92),g.drawString("STEPS",60,152),g.drawString("CADENCE",180,152),r(t),Bangle.drawWidgets()}var o;function a(t){t.status===o.Stopped&&function(t){const n=(new Date).toISOString().replace(/[-:]/g,""),r=`banglerun_${n.substr(2,6)}_${n.substr(9,6)}`;t.file=require("Storage").open(r,"w"),t.file.write(["timestamp","latitude","longitude","altitude","duration","distance","heartrate","steps"].join(",")+"\n")}(t),t.status===o.Running?t.status=o.Paused:t.status=o.Running,r(t)}!function(t){t.Stopped="STOP",t.Paused="PAUSE",t.Running="RUN"}(o||(o={}));const s={fix:NaN,lat:NaN,lon:NaN,alt:NaN,vel:NaN,dop:NaN,gpsValid:!1,x:NaN,y:NaN,z:NaN,v:NaN,t:NaN,dt:NaN,pError:NaN,vError:NaN,hr:60,hrError:100,file:null,drawing:!1,status:o.Stopped,duration:0,distance:0,speed:0,steps:0,cadence:0};var i;i=s,Bangle.on("GPS",t=>function(t,n){t.lat=n.lat,t.lon=n.lon,t.alt=n.alt,t.vel=n.speed/3.6,t.fix=n.fix,t.dop=n.hdop,t.gpsValid=t.fix>0&&t.dop<=5,function(t){const n=Date.now(),r=(n-t.t)/1e3;if(t.t=n,t.dt+=r,t.status===o.Running&&(t.duration+=r),!t.gpsValid)return;const e=6371008.8+t.alt,a=e*Math.cos(t.lat)*Math.cos(t.lon),s=e*Math.cos(t.lat)*Math.sin(t.lon),i=e*Math.sin(t.lat),d=t.vel;if(!t.x)return t.x=a,t.y=s,t.z=i,t.v=d,t.pError=2.5*t.dop,void(t.vError=.05*t.dop);const u=a-t.x,g=s-t.y,l=i-t.z,c=d-t.v,p=Math.sqrt(u*u+g*g+l*l),f=Math.abs(c);t.pError+=t.v*t.dt,t.dt=0;const N=p+2.5*t.dop,h=f+.05*t.dop,S=t.pError/(t.pError+N)||0,x=t.vError/(t.vError+h)||0;t.x+=u*S,t.y+=g*S,t.z+=l*S,t.v+=c*x,t.pError+=(N-t.pError)*S,t.vError+=(h-t.vError)*x;const E=Math.sqrt(t.x*t.x+t.y*t.y+t.z*t.z);t.lat=180*Math.asin(t.z/E)/Math.PI||0,t.lon=180*Math.atan2(t.y,t.x)/Math.PI||0,t.alt=E-6371008.8,t.status===o.Running&&(t.distance+=p*S,t.speed=t.distance/t.duration||0,t.cadence=60*t.steps/t.duration||0)}(t),r(t),t.gpsValid&&t.status===o.Running&&function(t){t.file.write([Date.now().toFixed(0),t.lat.toFixed(6),t.lon.toFixed(6),t.alt.toFixed(2),t.duration.toFixed(0),t.distance.toFixed(2),t.hr.toFixed(0),t.steps.toFixed(0)].join(",")+"\n")}(t)}(i,t)),Bangle.setGPSPower(1),function(t){Bangle.on("HRM",n=>function(t,n){if(0===n.confidence)return;const r=n.bpm-t.hr,e=Math.abs(r)+101-n.confidence,o=t.hrError/(t.hrError+e)||0;t.hr+=r*o,t.hrError+=(e-t.hrError)*o}(t,n)),Bangle.setHRMPower(1)}(s),function(t){Bangle.on("step",()=>function(t){t.status===o.Running&&(t.steps+=1)}(t))}(s),function(t){Bangle.loadWidgets(),Bangle.on("lcdPower",n=>{t.drawing=n,n&&e(t)}),e(t)}(s),setWatch(()=>a(s),BTN1,{repeat:!0,edge:"falling"}),setWatch(()=>function(t){t.status===o.Paused&&function(t){t.duration=0,t.distance=0,t.speed=0,t.steps=0,t.cadence=0}(t),t.status===o.Running?t.status=o.Paused:t.status=o.Stopped,r(t)}(s),BTN3,{repeat:!0,edge:"falling"})}();
|
||||
!function(){"use strict";const t={STOP:63488,PAUSE:65504,RUN:2016};function n(t,n,r){g.setColor(0),g.fillRect(n-60,r,n+60,r+30),g.setColor(65535),g.drawString(t,n,r)}function r(r){var e;g.setFontVector(30),g.setFontAlign(0,-1,0),n((r.distance/1e3).toFixed(2),60,55),n(function(t){const n=Math.round(t),r=Math.floor(n/3600),e=Math.floor(n/60)%60,o=n%60;return(r?r+":":"")+("0"+e).substr(-2)+":"+("0"+o).substr(-2)}(r.duration),180,55),n(function(t){if(t<.1667)return"__'__\"";const n=Math.round(1e3/t),r=Math.floor(n/60),e=n%60;return("0"+r).substr(-2)+"'"+("0"+e).substr(-2)+'"'}(r.speed),60,115),n(r.hr.toFixed(0),180,115),n(r.steps.toFixed(0),60,175),n(r.cadence.toFixed(0),180,175),g.setFont("6x8",2),g.setColor(r.gpsValid?2016:63488),g.fillRect(0,216,80,240),g.setColor(0),g.drawString("GPS",40,220),g.setColor(65535),g.fillRect(80,216,160,240),g.setColor(0),g.drawString(("0"+(e=new Date).getHours()).substr(-2)+":"+("0"+e.getMinutes()).substr(-2),120,220),g.setColor(t[r.status]),g.fillRect(160,216,240,240),g.setColor(0),g.drawString(r.status,200,220)}function e(t){g.clear(),g.setColor(50712),g.setFont("6x8",2),g.setFontAlign(0,-1,0),g.drawString("DIST (KM)",60,32),g.drawString("TIME",180,32),g.drawString("PACE",60,92),g.drawString("HEART",180,92),g.drawString("STEPS",60,152),g.drawString("CADENCE",180,152),r(t),Bangle.drawWidgets()}var o;function a(t){t.status===o.Stopped&&function(t){const n=(new Date).toISOString().replace(/[-:]/g,""),r=`banglerun_${n.substr(2,6)}_${n.substr(9,6)}`;t.file=require("Storage").open(r,"w"),t.file.write(["timestamp","latitude","longitude","altitude","duration","distance","heartrate","steps"].join(",")+"\n")}(t),t.status===o.Running?t.status=o.Paused:t.status=o.Running,r(t)}!function(t){t.Stopped="STOP",t.Paused="PAUSE",t.Running="RUN"}(o||(o={}));const s={fix:NaN,lat:NaN,lon:NaN,alt:NaN,vel:NaN,dop:NaN,gpsValid:!1,x:NaN,y:NaN,z:NaN,v:NaN,t:NaN,dt:NaN,pError:NaN,vError:NaN,hr:60,hrError:100,file:null,drawing:!1,status:o.Stopped,duration:0,distance:0,speed:0,steps:0,cadence:0};var i;i=s,Bangle.on("GPS",t=>function(t,n){t.lat=n.lat,t.lon=n.lon,t.alt=n.alt,t.vel=n.speed/3.6,t.fix=n.fix,t.dop=n.hdop,t.gpsValid=t.fix>0&&t.dop<=5,function(t){const n=Date.now();let r=(n-t.t)/1e3;if(isFinite(r)||(r=0),t.t=n,t.dt+=r,t.status===o.Running&&(t.duration+=r),!t.gpsValid)return;const e=6371008.8+t.alt,a=t.lat*Math.PI/180,s=t.lon*Math.PI/180,i=e*Math.cos(a)*Math.cos(s),d=e*Math.cos(a)*Math.sin(s),u=e*Math.sin(a),g=t.vel;if(!t.x)return t.x=i,t.y=d,t.z=u,t.v=g,t.pError=2.5*t.dop,void(t.vError=.05*t.dop);const l=i-t.x,c=d-t.y,p=u-t.z,f=g-t.v,N=Math.sqrt(l*l+c*c+p*p),h=Math.abs(f);t.pError+=t.v*t.dt,t.dt=0;const S=N+2.5*t.dop,E=h+.05*t.dop,w=t.pError/(t.pError+S)||0,x=t.vError/(t.vError+E)||0;t.x+=l*w,t.y+=c*w,t.z+=p*w,t.v+=f*x,t.pError+=(S-t.pError)*w,t.vError+=(E-t.vError)*x,t.status===o.Running&&(t.distance+=N*w,t.speed=t.distance/t.duration||0,t.cadence=60*t.steps/t.duration||0)}(t),r(t),t.gpsValid&&t.status===o.Running&&function(t){t.file.write([Date.now().toFixed(0),t.lat.toFixed(6),t.lon.toFixed(6),t.alt.toFixed(2),t.duration.toFixed(0),t.distance.toFixed(2),t.hr.toFixed(0),t.steps.toFixed(0)].join(",")+"\n")}(t)}(i,t)),Bangle.setGPSPower(1),function(t){Bangle.on("HRM",n=>function(t,n){if(0===n.confidence)return;const r=n.bpm-t.hr,e=Math.abs(r)+101-n.confidence,o=t.hrError/(t.hrError+e)||0;t.hr+=r*o,t.hrError+=(e-t.hrError)*o}(t,n)),Bangle.setHRMPower(1)}(s),function(t){Bangle.on("step",()=>function(t){t.status===o.Running&&(t.steps+=1)}(t))}(s),function(t){Bangle.loadWidgets(),Bangle.on("lcdPower",n=>{t.drawing=n,n&&e(t)}),e(t)}(s),setWatch(()=>a(s),BTN1,{repeat:!0,edge:"falling"}),setWatch(()=>function(t){t.status===o.Paused&&function(t){t.duration=0,t.distance=0,t.speed=0,t.steps=0,t.cadence=0}(t),t.status===o.Running?t.status=o.Paused:t.status=o.Stopped,r(t)}(s),BTN3,{repeat:!0,edge:"falling"})}();
|
||||
|
|
|
@ -111,6 +111,7 @@ function trackLineToObject(l, hasFileName) {
|
|||
var t = l.trim().split(",");
|
||||
var n = hasFileName ? 1 : 0;
|
||||
var o = {
|
||||
invalid : t.length < 8,
|
||||
date : new Date(parseInt(t[n+0])),
|
||||
lat : parseFloat(t[n+1]),
|
||||
lon : parseFloat(t[n+2]),
|
||||
|
@ -140,7 +141,7 @@ function downloadTrack(trackid, callback) {
|
|||
function getTrackList() {
|
||||
Util.showModal("Loading Tracks...");
|
||||
domTracks.innerHTML = "";
|
||||
Puck.eval(`require("Storage").list(/banglerun_.*\\1/).map(fn=>{fn=fn.slice(0,-1);var f=require("Storage").open(fn,"r");f.readLine();return fn+","+f.readLine()})`,trackLines=>{
|
||||
Puck.eval(`require("Storage").list(/banglerun_.*\\x01/).map(fn=>{fn=fn.slice(0,-1);var f=require("Storage").open(fn,"r");f.readLine();return fn+","+f.readLine()})`,trackLines=>{
|
||||
var html = `<div class="container">
|
||||
<div class="columns">\n`;
|
||||
trackLines.forEach(l => {
|
||||
|
@ -149,9 +150,9 @@ function getTrackList() {
|
|||
<div class="column col-12">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">Track ${track.filename}</div>
|
||||
<div class="card-subtitle text-gray">${track.date.toString().substr(0,24)}</div>
|
||||
<div class="card-subtitle text-gray">${track.invalid ? "No Data":track.date.toString().substr(0,24)}</div>
|
||||
</div>
|
||||
<div class="card-image">
|
||||
${track.invalid?``:`<div class="card-image">
|
||||
<iframe
|
||||
width="100%"
|
||||
height="250"
|
||||
|
@ -159,10 +160,10 @@ function getTrackList() {
|
|||
src="https://www.google.com/maps/embed/v1/place?key=AIzaSyBxTcwrrVOh2piz7EmIs1Xn4FsRxJWeVH4&q=${track.lat},${track.lon}&zoom=10" allowfullscreen>
|
||||
</iframe>
|
||||
</div>
|
||||
<div class="card-body"></div>
|
||||
<div class="card-footer">
|
||||
<div class="card-body"></div>`}
|
||||
<div class="card-footer">${track.invalid?``:`
|
||||
<button class="btn btn-primary" trackid="${track.filename}" task="downloadkml">Download KML</button>
|
||||
<button class="btn btn-primary" trackid="${track.filename}" task="downloadgpx">Download GPX</button>
|
||||
<button class="btn btn-primary" trackid="${track.filename}" task="downloadgpx">Download GPX</button>`}
|
||||
<button class="btn btn-default" trackid="${track.filename}" task="delete">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,13 +22,6 @@ function initGps(state: AppState): void {
|
|||
Bangle.setGPSPower(1);
|
||||
}
|
||||
|
||||
function parseCoordinate(coordinate: string): number {
|
||||
const pivot = coordinate.indexOf('.') - 2;
|
||||
const degrees = parseInt(coordinate.substr(0, pivot));
|
||||
const minutes = parseFloat(coordinate.substr(pivot)) / 60;
|
||||
return (degrees + minutes) * Math.PI / 180;
|
||||
}
|
||||
|
||||
function readGps(state: AppState, gps: GpsEvent): void {
|
||||
state.lat = gps.lat;
|
||||
state.lon = gps.lon;
|
||||
|
@ -49,7 +42,8 @@ function readGps(state: AppState, gps: GpsEvent): void {
|
|||
|
||||
function updateGps(state: AppState): void {
|
||||
const t = Date.now();
|
||||
const dt = (t - state.t) / 1000;
|
||||
let dt = (t - state.t) / 1000;
|
||||
if (!isFinite(dt)) dt=0;
|
||||
|
||||
state.t = t;
|
||||
state.dt += dt;
|
||||
|
@ -63,9 +57,11 @@ function updateGps(state: AppState): void {
|
|||
}
|
||||
|
||||
const r = EARTH_RADIUS + state.alt;
|
||||
const x = r * Math.cos(state.lat) * Math.cos(state.lon);
|
||||
const y = r * Math.cos(state.lat) * Math.sin(state.lon);
|
||||
const z = r * Math.sin(state.lat);
|
||||
const lat = state.lat * Math.PI / 180;
|
||||
const lon = state.lon * Math.PI / 180;
|
||||
const x = r * Math.cos(lat) * Math.cos(lon);
|
||||
const y = r * Math.cos(lat) * Math.sin(lon);
|
||||
const z = r * Math.sin(lat);
|
||||
const v = state.vel;
|
||||
|
||||
if (!state.x) {
|
||||
|
@ -101,11 +97,14 @@ function updateGps(state: AppState): void {
|
|||
state.pError += (pError - state.pError) * pGain;
|
||||
state.vError += (vError - state.vError) * vGain;
|
||||
|
||||
/*// we're not currently updating lat/lon with the kalman filter
|
||||
// as it seems not to update them correctly at the moment
|
||||
// and we only use them for logging (where it makes sense to use
|
||||
// raw GPS coordinates)
|
||||
const pMag = Math.sqrt(state.x * state.x + state.y * state.y + state.z * state.z);
|
||||
|
||||
state.lat = (Math.asin(state.z / pMag) * 180 / Math.PI) || 0;
|
||||
state.lon = (Math.atan2(state.y, state.x) * 180 / Math.PI) || 0;
|
||||
state.alt = pMag - EARTH_RADIUS;
|
||||
state.alt = pMag - EARTH_RADIUS;*/
|
||||
|
||||
if (state.status === ActivityStatus.Running) {
|
||||
state.distance += dpMag * pGain;
|
||||
|
@ -114,4 +113,4 @@ function updateGps(state: AppState): void {
|
|||
}
|
||||
}
|
||||
|
||||
export { initGps, parseCoordinate, readGps, updateGps };
|
||||
export { initGps, readGps, updateGps };
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
0.07: Submitted to App Loader
|
||||
0.08: Fixes issue where face would redraw on wake leading to all memory being used and watch crashing.
|
||||
0.09: Add BTN1 status line with ID,Fw ver, mem %, battery %
|
||||
0.10: Icon fixed for transparency
|
||||
0.11: added Heart Rate Monitor status and ability to turn on/off
|
||||
|
|
|
@ -9,6 +9,14 @@ A retro VT100 command line style clock
|
|||
|
||||
### With BTN1 pressed
|
||||
|
||||
* Successive presses of BTN1 will show id, FW version, battery %, memory %
|
||||
* Successive presses of BTN1 will show Heart rate, Steps, id, FW version, battery %, memory %
|
||||
|
||||

|
||||
|
||||
* BTN2 shows a functional menu that enables the Heart rate monitor to be turned on / off using BTN1
|
||||
|
||||
Once the heart rate monitor is ON, you can cycle through the displays to show the heart rate.
|
||||
|
||||
## Future Enhancements
|
||||
* Ability to turn on the GPS and show, lat long, grid ref
|
||||
* Maybe a simple stopwatch capability
|
||||
|
|
|
@ -1 +1 @@
|
|||
require("heatshrink").decompress(atob("kEgwkBiIA/ACBhLB6gqKB6g//B6I4DiDqCB40QB4MBAoIXDB40BAIIPNG44PLAoQvMB5RPEB5JvEBAav1f7wA/ABoA=="))
|
||||
require("heatshrink").decompress(atob("mEwgRC/AH4Ae/4AEBaPwAgcPBaIvvBZkL8ED6ALHl/4+XgBY89vnw+ALHngDB+gLK3AjKng7JBwJTJgEfO76/iAH4A/ADAA="))
|
||||
|
|
|
@ -4,13 +4,21 @@ var marginTop = 40;
|
|||
var flag = false;
|
||||
var WeekDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
|
||||
|
||||
var hrtOn = false;
|
||||
var hrtStr = "Hrt: ??? bpm";
|
||||
|
||||
const NONE_MODE = "none";
|
||||
const ID_MODE = "id";
|
||||
const VER_MODE = "ver";
|
||||
const BATT_MODE = "batt";
|
||||
const MEM_MODE = "mem";
|
||||
const STEPS_MODE = "step";
|
||||
const HRT_MODE = "hrt";
|
||||
const NONE_FN_MODE = "no_fn";
|
||||
const HRT_FN_MODE = "fn_hrt";
|
||||
|
||||
let infoMode = NONE_MODE;
|
||||
let functionMode = NONE_FN_MODE;
|
||||
|
||||
function drawAll(){
|
||||
updateTime();
|
||||
|
@ -54,11 +62,29 @@ function drawInfo(line) {
|
|||
let str = "";
|
||||
let col = 0x07E0; // green
|
||||
|
||||
//console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode);
|
||||
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
col = 0x07FF; // cyan
|
||||
str = "HRM: " + (hrtOn ? "ON" : "OFF");
|
||||
drawModeLine(line,str,col);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case NONE_MODE:
|
||||
col = 0x0000;
|
||||
str = "";
|
||||
break;
|
||||
case HRT_MODE:
|
||||
str = hrtStr;
|
||||
break;
|
||||
case STEPS_MODE:
|
||||
str = "Steps: " + stepsWidget().getSteps();
|
||||
break;
|
||||
case ID_MODE:
|
||||
val = NRF.getAddress().split(":");
|
||||
str = "Id: " + val[4] + val[5];
|
||||
|
@ -75,6 +101,10 @@ function drawInfo(line) {
|
|||
str = "Battery: " + E.getBattery() + "%";
|
||||
}
|
||||
|
||||
drawModeLine(line,str,col);
|
||||
}
|
||||
|
||||
function drawModeLine(line, str, col) {
|
||||
g.setColor(col);
|
||||
g.fillRect(0, marginTop-3+line*30, 239, marginTop+25+line*30);
|
||||
g.setColor(0,0,0);
|
||||
|
@ -83,8 +113,31 @@ function drawInfo(line) {
|
|||
}
|
||||
|
||||
function changeInfoMode() {
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
hrtOn = !hrtOn;
|
||||
Bangle.buzz();
|
||||
Bangle.setHRMPower(hrtOn ? 1 : 0);
|
||||
if (hrtOn) infoMode = HRT_MODE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case NONE_MODE:
|
||||
if (stepsWidget() !== undefined)
|
||||
infoMode = hrtOn ? HRT_MODE : STEPS_MODE;
|
||||
else
|
||||
infoMode = VER_MODE;
|
||||
break;
|
||||
case HRT_MODE:
|
||||
if (stepsWidget() !== undefined)
|
||||
infoMode = STEPS_MODE;
|
||||
else
|
||||
infoMode = VER_MODE;
|
||||
break;
|
||||
case STEPS_MODE:
|
||||
infoMode = ID_MODE;
|
||||
break;
|
||||
case ID_MODE:
|
||||
|
@ -102,6 +155,37 @@ function changeInfoMode() {
|
|||
}
|
||||
}
|
||||
|
||||
function changeFunctionMode() {
|
||||
//console.log("changeFunctionMode()");
|
||||
switch(functionMode) {
|
||||
case NONE_FN_MODE:
|
||||
functionMode = HRT_FN_MODE;
|
||||
break;
|
||||
case HRT_FN_MODE:
|
||||
default:
|
||||
functionMode = NONE_FN_MODE;
|
||||
}
|
||||
//console.log(functionMode);
|
||||
|
||||
}
|
||||
|
||||
function stepsWidget() {
|
||||
if (WIDGETS.activepedom !== undefined) {
|
||||
return WIDGETS.activepedom;
|
||||
} else if (WIDGETS.wpedom !== undefined) {
|
||||
return WIDGETS.wpedom;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Bangle.on('HRM', function(hrm) {
|
||||
if(hrm.confidence > 90){
|
||||
hrtStr = "Hrt: " + hrm.bpm + " bpm";
|
||||
} else {
|
||||
hrtStr = "Hrt: ??? bpm";
|
||||
}
|
||||
});
|
||||
|
||||
g.clear();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
@ -113,3 +197,4 @@ Bangle.on('lcdPower',function(on) {
|
|||
var click = setInterval(updateTime, 1000);
|
||||
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
|
||||
setWatch(() => { changeInfoMode(); drawAll(); }, BTN1, {repeat: true});
|
||||
setWatch(() => { changeFunctionMode(); drawAll(); }, BTN3, {repeat: true});
|
||||
|
|
Before Width: | Height: | Size: 305 B After Width: | Height: | Size: 348 B |
|
@ -1,2 +1,3 @@
|
|||
0.01: New app!
|
||||
0.02: Improve handling of large amounts of files (fix #579)
|
||||
0.03: Update RegExp use (Was using backreference instead of character code)
|
||||
|
|
|
@ -91,8 +91,8 @@ function drawMenu() {
|
|||
|
||||
function get_pruned_file_list() {
|
||||
// get storagefile list
|
||||
var sf = STOR.list(/\1$/).map(s=>s.slice(0,-1));
|
||||
var sffilter = f=>!sf.includes(f.slice(0,-1)) || f.endsWith("\1");
|
||||
var sf = STOR.list(/\x01$/).map(s=>s.slice(0,-1));
|
||||
var sffilter = f=>!sf.includes(f.slice(0,-1)) || f.endsWith("\x01");
|
||||
// get files - put '.' last
|
||||
var fl = STOR.list(/^[^\.]/).filter(sffilter);
|
||||
fl.sort();
|
||||
|
|
|
@ -18,3 +18,5 @@
|
|||
Nicer display of alarm clock notifications
|
||||
0.17: Modified music notification for updated 'notify' library
|
||||
0.18: Added reporting of step count and HRM (new Gadgetbridges can now log this)
|
||||
0.19: Support for call incoming/start/end
|
||||
0.20: Reduce memory usage
|
||||
|
|
|
@ -2,13 +2,11 @@
|
|||
// Music handling
|
||||
const state = {
|
||||
music: "stop",
|
||||
|
||||
musicInfo: {
|
||||
artist: "",
|
||||
album: "",
|
||||
track: ""
|
||||
},
|
||||
|
||||
scrollPos: 0
|
||||
};
|
||||
// activity reporting
|
||||
|
@ -43,14 +41,6 @@
|
|||
return event;
|
||||
}
|
||||
}
|
||||
function handleNotificationEvent(event) {
|
||||
if (event.t === "notify") {
|
||||
require("notify").show(prettifyNotificationEvent(event));
|
||||
Bangle.buzz();
|
||||
} else { // notify-
|
||||
require("notify").hide(event);
|
||||
}
|
||||
}
|
||||
|
||||
function updateMusic(options){
|
||||
if (state.music === "play") {
|
||||
|
@ -117,37 +107,6 @@
|
|||
require("notify").hide("music");
|
||||
}
|
||||
}
|
||||
function handleMusicStateUpdate(event) {
|
||||
if (state.music !== event.state) {
|
||||
state.music = event.state
|
||||
updateMusic({on: true});
|
||||
}
|
||||
}
|
||||
function handleMusicInfoUpdate(event) {
|
||||
state.musicInfo = event;
|
||||
updateMusic({on: false});
|
||||
}
|
||||
|
||||
function handleCallEvent(event) {
|
||||
if (event.cmd === "accept") {
|
||||
require("notify").show({
|
||||
size: 55, title: event.name, id: "call",
|
||||
body: event.number, icon:require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw="))});
|
||||
Bangle.buzz();
|
||||
}
|
||||
}
|
||||
|
||||
function handleFindEvent(event) {
|
||||
if (state.find) {
|
||||
clearInterval(state.find);
|
||||
delete state.find;
|
||||
}
|
||||
if (event.n)
|
||||
state.find = setInterval(_=>{
|
||||
Bangle.buzz();
|
||||
setTimeout(_=>Bangle.beep(), 1000);
|
||||
},2000);
|
||||
}
|
||||
|
||||
function handleActivityEvent(event) {
|
||||
var s = settings();
|
||||
|
@ -193,19 +152,52 @@
|
|||
switch (event.t) {
|
||||
case "notify":
|
||||
case "notify-":
|
||||
handleNotificationEvent(event);
|
||||
if (event.t === "notify") {
|
||||
require("notify").show(prettifyNotificationEvent(event));
|
||||
Bangle.buzz();
|
||||
} else { // notify-
|
||||
require("notify").hide(event);
|
||||
}
|
||||
break;
|
||||
case "musicinfo":
|
||||
handleMusicInfoUpdate(event);
|
||||
state.musicInfo = event;
|
||||
updateMusic({on: false});
|
||||
break;
|
||||
case "musicstate":
|
||||
handleMusicStateUpdate(event);
|
||||
if (state.music !== event.state) {
|
||||
state.music = event.state
|
||||
updateMusic({on: true});
|
||||
}
|
||||
break;
|
||||
case "call":
|
||||
handleCallEvent(event);
|
||||
var note = { size: 55, title: event.name, id: "call",
|
||||
body: event.number, icon:require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw="))}
|
||||
if (event.cmd === "incoming") {
|
||||
require("notify").show(note);
|
||||
Bangle.buzz();
|
||||
} else if (event.cmd === "start") {
|
||||
require("notify").show(Object.assign(note, {
|
||||
bgColor : "#008000", titleBgColor : "#00C000",
|
||||
body: "In progress: "+event.number}));
|
||||
} else if (event.cmd === "end") {
|
||||
require("notify").show(Object.assign(note, {
|
||||
bgColor : "#800000", titleBgColor : "#C00000",
|
||||
body: "Ended: "+event.number}));
|
||||
setTimeout(function() {
|
||||
require("notify").hide({ id: "call" });
|
||||
}, 2000);
|
||||
}
|
||||
break;
|
||||
case "find":
|
||||
handleFindEvent(event);
|
||||
if (state.find) {
|
||||
clearInterval(state.find);
|
||||
delete state.find;
|
||||
}
|
||||
if (event.n)
|
||||
state.find = setInterval(_=>{
|
||||
Bangle.buzz();
|
||||
setTimeout(_=>Bangle.beep(), 1000);
|
||||
},2000);
|
||||
break;
|
||||
case "act":
|
||||
handleActivityEvent(event);
|
||||
|
|
|
@ -18,3 +18,4 @@
|
|||
0.14: Now use the openstmap lib for map plotting
|
||||
0.15: Add plotTrack method to allow current track to be plotted on a map (#395)
|
||||
0.16: Add gpsrec app to Settings menu
|
||||
0.17: Disable recording if storage is full (fix #574)
|
||||
|
|
|
@ -29,12 +29,21 @@
|
|||
periodCtr--;
|
||||
if (periodCtr<=0) {
|
||||
periodCtr = settings.period;
|
||||
try {
|
||||
if (gpsTrack) gpsTrack.write([
|
||||
fix.time.getTime(),
|
||||
fix.lat.toFixed(6),
|
||||
fix.lon.toFixed(6),
|
||||
fix.alt
|
||||
].join(",")+"\n");
|
||||
} catch(e) {
|
||||
// If storage.write caused an error, disable
|
||||
// GPS recording so we don't keep getting errors!
|
||||
console.log("gpsrec: write error", e);
|
||||
settings.recording = false;
|
||||
require("Storage").write("gpsrec.json", settings);
|
||||
reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: New App
|
||||
0.02: Restore to SuperE mode on power off.
|
||||
0.03: dont reset to SuperE mode on power, as it prevents its general use
|
||||
0.04: Only turn GPS off if it was previously on (stops other apps/widgets that use GPS getting broken)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
var fixToggle = false; // toggles once for each reading
|
||||
var have_fix = false;
|
||||
var debug = false;
|
||||
var gpsPowerEnabled = false;
|
||||
|
||||
var last_fix = {
|
||||
fix: 0,
|
||||
|
@ -68,7 +69,10 @@
|
|||
|
||||
function gps_power_off() {
|
||||
//setupSuperE(); // return to expected setup for other apps
|
||||
if (gpsPowerEnabled) {
|
||||
gpsPowerEnabled = false;
|
||||
Bangle.setGPSPower(0);
|
||||
}
|
||||
have_fix = false;
|
||||
fixToggle = false;
|
||||
last_fix.fix = 0;
|
||||
|
@ -86,6 +90,7 @@
|
|||
|
||||
function setupGPS() {
|
||||
Bangle.setGPSPower(1);
|
||||
gpsPowerEnabled = true;
|
||||
|
||||
if (settings.power_mode === "PSMOO") {
|
||||
setupPSMOO();
|
||||
|
@ -280,4 +285,3 @@
|
|||
reload();
|
||||
|
||||
})();
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
0.01: First version of GPS Setup app
|
||||
0.02: Created gppsetup module
|
|
@ -0,0 +1,109 @@
|
|||
# GPS Setup
|
||||
|
||||
An App and module to enable the GPS to be configured into low power mode.
|
||||
|
||||
## Goals
|
||||
|
||||
To develop an app that configures the GPS to run with the lowest
|
||||
possible power consumption.
|
||||
|
||||
Example power consumption of the GPS while powered on:
|
||||
|
||||
* An app that turns on the GPS and constantly displays the screen
|
||||
will use around 75mA, the battery will last between 3-4 hours.
|
||||
|
||||
* Using the GPS with Super-E Power Saving Mode (PSM) with the screen
|
||||
off most of the time, will consume around 35mA and you might get
|
||||
10hrs before a recharge.
|
||||
|
||||
* Using the GPS in Power Saving Mode On/Off (PSMOO) with suitable
|
||||
settings can reduce the average consumption to around 15mA. A
|
||||
simple test using a 120s update period, 6s search period was still
|
||||
running with 45% battery 20 hours after it started.
|
||||
|
||||
|
||||
## Settings App
|
||||
|
||||
The Settings App enables you set the options below. Either start the
|
||||
App from the launcher or go to Settings, select App/Widgets and then
|
||||
'GPS Setup'.
|
||||
|
||||
When you exit the setup app, the settings will be stored in the
|
||||
gpssetup.settings.json file, the GPS will be switched on and the
|
||||
necessary commands sent to the GPS to configure it. The GPS is then
|
||||
powered off. The GPS configuration is stored in the GPS non-volatile
|
||||
memory so that next time the GPS is powered, that configuration is
|
||||
used. These settings will remain for all apps that use the GPS.
|
||||
|
||||
|
||||
- Power Mode:
|
||||
|
||||
- **SuperE** - the factory default setup for the GPS. The recommended
|
||||
power saving mode. If you need frequent (every second) updates on
|
||||
position, then this is the mode for you.
|
||||
|
||||
- **PSMOO** - On/Off power saving mode. Configured by interval and
|
||||
search time. Choose this mode if you are happy to get a GPS
|
||||
position update less often (say every 1 or 2 minutes). The longer
|
||||
the interval the more time the GPS will spend sleeping in low
|
||||
power mode (7mA) between obtaining fixes (35mA). For walking in
|
||||
open country an update once every 60 seconds is adequate to put
|
||||
you within a 6 digit grid refernce sqaure.
|
||||
|
||||
- update - the time between two position fix attempts.
|
||||
|
||||
- search - the time between two acquisition attempts if the receiver
|
||||
is unable to get a position fix.
|
||||
|
||||
## Module
|
||||
|
||||
A module is provided that'll allow you to set GPS configuration from your own
|
||||
app. To use it:
|
||||
|
||||
```
|
||||
// This will set up the GPS to current saved defaults. It's not normally
|
||||
// needed unless the watch's battery has run down
|
||||
require("gpssetup").setPowerMode();
|
||||
|
||||
// This sets up the PSMOO mode. update/search are optional in seconds
|
||||
require("gpssetup").setPowerMode({
|
||||
power_mode:"PSMOO",
|
||||
update:optional (default 120),
|
||||
search:optional (default 5)})
|
||||
|
||||
// This sets up SuperE
|
||||
require("gpssetup").setPowerMode({power_mode:"SuperE"})
|
||||
```
|
||||
|
||||
`setPowerMode` returns a promise, which is completed when the GPS is set up.
|
||||
|
||||
So you can for instance do the following to turn the GPS off once it
|
||||
has been configured:
|
||||
|
||||
```
|
||||
require("gpssetup").setPowerMode().then(function() {
|
||||
Bangle.setGPSPower(0);
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** It's not guaranteed that the user will have installed the `gpssetup`
|
||||
app/module. It might be worth checking for its existence by surrounding the
|
||||
`require` call with `try...catch` block.
|
||||
|
||||
```
|
||||
var gpssetup;
|
||||
try {
|
||||
gpssetup = require("gpssetup")
|
||||
} catch(e) {
|
||||
E.showMessage("gpssetup\nnot installed");
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
* [UBLOX M8 Receiver Data Sheet](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29.pdf)
|
||||
|
||||
* [UBLOX Power Management App Note](https://www.u-blox.com/sites/default/files/products/documents/PowerManagement_AppNote_%28UBX-13005162%29.pdf)
|
||||
|
||||
* Some useful code on Github can be found [here](https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control)
|
||||
and [here](https://github.com/thasti/utrak/blob/master/gps.c)
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* GPS Setup app, hughbarney AT googlemail DOT com
|
||||
* With thanks to Gordon Williams for support and advice
|
||||
*
|
||||
* UBLOX power modes:
|
||||
* SuperE - will provide updates every second and consume 35mA, 75mA with LCD on
|
||||
* PSMOO - will sleep for update time and consume around 7mA during that period
|
||||
* after acquiring satelite fixes the GPS will settle into a cycle of
|
||||
* obtaining fix, sleeping for update seconds, wake up, get fix and sleep.
|
||||
*
|
||||
* See README file for more details
|
||||
*
|
||||
*/
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
function log_debug(o) {
|
||||
//let timestamp = new Date().getTime();
|
||||
//console.log(timestamp + " : " + o);
|
||||
}
|
||||
|
||||
const SETTINGS_FILE = "gpssetup.settings.json";
|
||||
let settings = undefined;
|
||||
let settings_changed = false;
|
||||
|
||||
function updateSettings() {
|
||||
require("Storage").write(SETTINGS_FILE, settings);
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
log_debug("loadSettings()");
|
||||
settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
|
||||
settings.update = settings.update||120;
|
||||
settings.search = settings.search||5;
|
||||
settings.power_mode = settings.power_mode||"SuperE";
|
||||
log_debug(settings);
|
||||
}
|
||||
|
||||
/*********** GPS Power and Setup Functions ******************/
|
||||
|
||||
function setupGPS() {
|
||||
Bangle.setGPSPower(1);
|
||||
setTimeout(function() {
|
||||
require("gpssetup").setPowerMode().then(function() {
|
||||
Bangle.setGPSPower(0);
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/*********** GPS Setup Menu App *****************************/
|
||||
|
||||
function showMainMenu() {
|
||||
var power_options = ["SuperE","PSMOO"];
|
||||
|
||||
const mainmenu = {
|
||||
'': { 'title': 'GPS Setup' },
|
||||
'< Back': ()=>{exitSetup();},
|
||||
'Power Mode': {
|
||||
value: 0 | power_options.indexOf(settings.power_mode),
|
||||
min: 0, max: 1,
|
||||
format: v => power_options[v],
|
||||
onchange: v => {
|
||||
settings.power_mode = power_options[v];
|
||||
updateSettings();
|
||||
},
|
||||
},
|
||||
'Update (s)': {
|
||||
value: settings.update,
|
||||
min: 10,
|
||||
max: 1800,
|
||||
step: 10,
|
||||
onchange: v => {
|
||||
settings.update = v;
|
||||
updateSettings();
|
||||
}
|
||||
},
|
||||
'Search (s)': {
|
||||
value: settings.search,
|
||||
min: 1,
|
||||
max: 65,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
settings.search = v;
|
||||
updateSettings();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return E.showMenu(mainmenu);
|
||||
}
|
||||
|
||||
function exitSetup() {
|
||||
log_debug("exitSetup()");
|
||||
if (settings_changed) {
|
||||
log_debug(settings);
|
||||
E.showMessage("Configuring GPS");
|
||||
setTimeout(function() {
|
||||
setupGPS();
|
||||
setTimeout(function() { load() }, 750);
|
||||
}, 500);
|
||||
} else {
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
showMainMenu();
|
|
@ -0,0 +1,179 @@
|
|||
const SETTINGS_FILE = "gpssetup.settings.json";
|
||||
|
||||
function log_debug(o) {
|
||||
//let timestamp = new Date().getTime();
|
||||
//console.log(timestamp + " : " + o);
|
||||
}
|
||||
|
||||
function writeGPScmd(cmd) {
|
||||
var d = [0xB5,0x62]; // sync chars
|
||||
d = d.concat(cmd);
|
||||
var a=0,b=0;
|
||||
for (var i=2;i<d.length;i++) {
|
||||
a += d[i];
|
||||
b += a;
|
||||
}
|
||||
d.push(a&255,b&255);
|
||||
Serial1.write(d);
|
||||
}
|
||||
|
||||
// UBX-CFG-PMS - enable power management - Super-E
|
||||
function UBX_CFG_PMS() {
|
||||
log_debug("UBX_CFG_PMS()");
|
||||
writeGPScmd([0x06,0x86, // msg class + type
|
||||
8,0,//length
|
||||
0x00,0x03, 0,0, 0,0, 0,0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extended Power Management
|
||||
* update and search are in milli seconds
|
||||
* settings are loaded little endian, lsb first
|
||||
*
|
||||
* https://github.com/thasti/utrak/blob/master/gps.c
|
||||
*/
|
||||
function UBX_CFG_PM2(update,search) {
|
||||
log_debug("UBX_CFG_PM2()");
|
||||
|
||||
// convert an integer to an array of bytes
|
||||
function int_2_bytes( x ){
|
||||
var bytes = [];
|
||||
var i = 4;
|
||||
do {
|
||||
bytes[--i] = x & (255);
|
||||
x = x>>8;
|
||||
} while (i);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
var u = int_2_bytes(update*1000);
|
||||
var s = int_2_bytes(search*1000);
|
||||
|
||||
writeGPScmd([0x06, 0x3B, /* class id */
|
||||
44, 0, /* length */
|
||||
0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */
|
||||
0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */
|
||||
u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
|
||||
s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
|
||||
0x00, 0x00, 0x00, 0x00, /* grid offset */
|
||||
0x00, 0x00, /* on-time after first fix */
|
||||
0x01, 0x00, /* minimum acquisition time */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 6 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 7 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */
|
||||
0x00, 0x00, 0x00, 0x00]); /* reserved 11 */
|
||||
}
|
||||
|
||||
// enable power saving mode, after configured with PM2
|
||||
function UBX_CFG_RXM() {
|
||||
log_debug("UBX_CFG_RXM()");
|
||||
writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */
|
||||
2, 0, /* length */
|
||||
0x08, 0x01]); /* reserved, enable power save mode */
|
||||
}
|
||||
|
||||
/*
|
||||
* Save configuration otherwise it will reset when the GPS wakes up
|
||||
*/
|
||||
function UBX_CFG_SAVE() {
|
||||
log_debug("UBX_CFG_SAVE()");
|
||||
writeGPScmd([0x06, 0x09, // class id
|
||||
0x0D, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, // clear mask
|
||||
0xFF, 0xFF, 0x00, 0x00, // save mask
|
||||
0x00, 0x00, 0x00, 0x00, // load mask
|
||||
0x07]); // b2=eeprom b1=flash b0=bat backed ram
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset to factory settings using clear mask in UBX_CFG_CFG
|
||||
* https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control
|
||||
*/
|
||||
function UBX_CFG_RESET() {
|
||||
log_debug("UBX_CFG_RESET()");
|
||||
writeGPScmd([0x06, 0x09, // class id
|
||||
0x0D, 0x00,
|
||||
0xFF, 0xFB, 0x00, 0x00, // clear mask
|
||||
0x00, 0x00, 0x00, 0x00, // save mask
|
||||
0xFF, 0xFF, 0x00, 0x00, // load mask
|
||||
0x17]);
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function setupSuperE() {
|
||||
log_debug("setupGPS() Super-E");
|
||||
return Promise.resolve().then(function() {
|
||||
UBX_CFG_RESET();
|
||||
return delay(100);
|
||||
}).then(function() {
|
||||
UBX_CFG_PMS();
|
||||
return delay(20);
|
||||
}).then(function() {
|
||||
UBX_CFG_SAVE();
|
||||
return delay(20);
|
||||
}).then(function() {
|
||||
log_debug("Powering GPS Off");
|
||||
/*
|
||||
* must be part of the promise chain to ensure that
|
||||
* setup does not return and powerOff before config functions
|
||||
* have run
|
||||
*/
|
||||
return delay(20);
|
||||
});
|
||||
}
|
||||
|
||||
function setupPSMOO(settings) {
|
||||
log_debug("setupGPS() PSMOO");
|
||||
return Promise.resolve().then(function() {
|
||||
UBX_CFG_RESET();
|
||||
return delay(100);
|
||||
}).then(function() {
|
||||
UBX_CFG_PM2(settings.update, settings.search);
|
||||
return delay(20);
|
||||
}).then(function() {
|
||||
UBX_CFG_RXM();
|
||||
return delay(20);
|
||||
}).then(function() {
|
||||
UBX_CFG_SAVE();
|
||||
return delay(20);
|
||||
}).then(function() {
|
||||
log_debug("Powering GPS Off");
|
||||
/*
|
||||
* must be part of the promise chain to ensure that
|
||||
* setup does not return and powerOff before config functions
|
||||
* have run
|
||||
*/
|
||||
return delay(20);
|
||||
});
|
||||
}
|
||||
|
||||
/** Set GPS power mode (assumes GPS on), returns a promise.
|
||||
Either:
|
||||
|
||||
require("gpssetup").setPowerMode() // <-- set up GPS to current saved defaults
|
||||
require("gpssetup").setPowerMode({power_mode:"PSMOO", update:optional, search:optional}) // <-- PSMOO mode
|
||||
require("gpssetup").setPowerMode({power_mode:"SuperE"}) // <-- Super E mode
|
||||
|
||||
See the README for more information
|
||||
*/
|
||||
exports.setPowerMode = function(options) {
|
||||
settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
|
||||
if (options) {
|
||||
if (options.update) settings.update = options.update;
|
||||
if (options.search) settings.search = options.search;
|
||||
if (options.power_mode) settings.power_mode = options.power_mode;
|
||||
}
|
||||
settings.update = settings.update||120;
|
||||
settings.search = settings.search||5;
|
||||
settings.power_mode = settings.power_mode||"SuperE";
|
||||
if (options) require("Storage").write(SETTINGS_FILE, settings);
|
||||
if (settings.power_mode === "PSMOO") {
|
||||
return setupPSMOO(settings);
|
||||
} else {
|
||||
return setupSuperE();
|
||||
}
|
||||
};
|
After Width: | Height: | Size: 2.6 KiB |
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/ACmsAAIss1mBwIfZqwABFpwuYC4IADGBYuaDQwuDF5ouYLo4vJIYousCYQOIHJIuUCo4uIHJIuUf4wlGEIQaHFywvHGAguiF5GBEIgbHFzAvJDwwuRvV6F6xLJFxmkAAQuKqwtKPQ4RKFwgwICgobHVRJAJFQOr0owIE5AtNDIYRI0ulGBAuNapYABCRGkGBAuGAoIpNGBIIFGBF6FwuBFygAKGBAulGBgujGBWAF0jpBehIvlqwws1jnCGFOs1heBGFQuBFoYwoFxFWwAwjFw+BAAIMBGEIuMGEIuIeQIQFGDouJ1gSHGDYuSGDYuUGDSzBFYP+dAQuNGBN6F6RcBFyAwHwAvQGAYuSGAheCF54wCAAYuRGAQABwGAC6QuWGAV6FyYA/AH4A2A="))
|
|
@ -0,0 +1,4 @@
|
|||
(function(back) {
|
||||
// just go right to our app
|
||||
load("gpssetup.app.js");
|
||||
})();
|
|
@ -0,0 +1 @@
|
|||
{"power_mode":"SuperE", "update":120, "search":6}
|
|
@ -8,3 +8,4 @@
|
|||
Ensure 'on' is always supplied for translations
|
||||
0.07: Improve handling of non-ASCII characters (fix #469)
|
||||
0.08: Added Mavigation units and en_NAV
|
||||
0.09: Added New Zealand en_NZ
|
||||
|
|
|
@ -245,6 +245,24 @@ var locales = {
|
|||
day: "söndag,måndag,tisdag,onsdag,torsdag,fredag,lördag",
|
||||
trans: { yes: "ja", Yes: "Ja", no: "nej", No: "Nej", ok: "ok", on: "on", off: "off" }
|
||||
},
|
||||
"en_NZ": {
|
||||
lang: "en_NZ",
|
||||
decimal_point: ".",
|
||||
thousands_sep: ",",
|
||||
currency_symbol: "$",
|
||||
int_curr_symbol: "NZD",
|
||||
speed: "kph",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
temperature: "°C",
|
||||
ampm: { 0: "am", 1: "pm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%y" }, // Sunday, 1 March 2020 // 1/3/20
|
||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||
abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat",
|
||||
day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",
|
||||
// No translation for english...
|
||||
},
|
||||
"en_AU": {
|
||||
lang: "en_AU",
|
||||
decimal_point: ".",
|
||||
|
|
|
@ -9,3 +9,4 @@
|
|||
0.09: Added Pedometer clock
|
||||
0.10: Added GPS and Grid Ref clock faces
|
||||
0.11: Updated Pedometer clock to retrieve steps from either wpedom or activepedom
|
||||
0.12: Removed GPS and Grid Ref clock faces, superceded by GPS setup and Walkers Clock
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
{"name":"digi.face.js","url":"digi.min.js"},
|
||||
{"name":"txt.face.js","url":"txt.min.js"},
|
||||
{"name":"ped.face.js","url":"ped.js"},
|
||||
{"name":"osref.face.js","url":"osref.js"},
|
||||
{"name":"gps.face.js","url":"pgs.js"},
|
||||
{"name":"multiclock.img","url":"multiclock-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
(() => {
|
||||
|
||||
function getFace(){
|
||||
|
||||
//var img = require("heatshrink").decompress(atob("mEwghC/AH4AKg9wC6t3u4uVC6wWBI6t3uJeVuMQCqcBLisAi4XLxAABFxAXKgc4DBAuBRhQXEDAq7MmYXEwBHEXZYXFGAOqAAKDMmczC4mIC62CC50PC4JIBkQABiIvRmURAAUSjQXSFwMoxGKC6CRFwUSVYgXLPIgXXwMYegoXLJAYXCGBnzGA0hPQIwMgYwGC6gwCC4ZIMC4gYBC604C4ZISmcRVgapQAAMhC6GIJIwXCMBcIxGDDBAuLC4IwGAARGMAAQWGmAXPJQoWMC4pwCCpoXJAB4XXAH4A/ABQA="));
|
||||
var nofix = 0;
|
||||
|
||||
function formatTime(now) {
|
||||
var fd = now.toUTCString().split(" ");
|
||||
return fd[4];
|
||||
}
|
||||
|
||||
|
||||
function timeSince(t) {
|
||||
var hms = t.split(":");
|
||||
var now = new Date();
|
||||
|
||||
var sn = 3600*(now.getHours()) + 60*(now.getMinutes()) + 1*(now.getSeconds());
|
||||
var st = 3600*(hms[0]) + 60*(hms[1]) + 1*(hms[2]);
|
||||
|
||||
return (sn - st);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
var gps_on = false;
|
||||
|
||||
var fix = {
|
||||
fix: 0,
|
||||
alt: 0,
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
speed: 0,
|
||||
time: 0,
|
||||
satellites: 0
|
||||
};
|
||||
|
||||
var y_line = 26;
|
||||
var y_start = 46;
|
||||
var x_start = 10;
|
||||
|
||||
// only attempt to get gps fix if gpsservuce is loaded
|
||||
if (WIDGETS.gpsservice !== undefined) {
|
||||
fix = WIDGETS.gpsservice.gps_get_fix();
|
||||
gps_on = WIDGETS.gpsservice.gps_get_status();
|
||||
}
|
||||
|
||||
g.reset();
|
||||
g.clearRect(0,24,239,239);
|
||||
|
||||
if (fix.fix) {
|
||||
var time = formatTime(fix.time);
|
||||
var age = timeSince(time);
|
||||
|
||||
g.setFontAlign(-1, -1);
|
||||
g.setFont("6x8");
|
||||
g.setFontVector(22);
|
||||
g.drawString("Alt: " + fix.alt +" m", x_start, y_start, true);
|
||||
g.drawString("Lat: "+ fix.lat, x_start, y_start + y_line, true);
|
||||
g.drawString("Lon: " + fix.lon, x_start, y_start + 2*y_line, true);
|
||||
g.drawString("Time: " + time, x_start, y_start + 3*y_line, true);
|
||||
g.drawString("Age(s): " + age, x_start, y_start + 4*y_line, true);
|
||||
g.drawString("Satellites: " + fix.satellites, x_start, y_start + 5*y_line, true);
|
||||
|
||||
} else if (gps_on) {
|
||||
|
||||
g.setFontAlign(0, 1);
|
||||
g.setFont("6x8", 2);
|
||||
g.drawString("GPS Watch", 120, 60);
|
||||
g.drawString("Waiting for GPS", 120, 80);
|
||||
nofix = (nofix+1) % 4;
|
||||
g.drawString(".".repeat(nofix) + " ".repeat(4-nofix), 120, 120);
|
||||
g.setFontAlign(0,0);
|
||||
g.drawString(fix.satellites + " satellites", 120, 100);
|
||||
|
||||
} else if (!gps_on) {
|
||||
|
||||
g.setFontAlign(0, 0);
|
||||
g.setFont("6x8", 3);
|
||||
g.drawString("GPS Watch", 120, 80);
|
||||
g.drawString("GPS is off",120, 160);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function onSecond(){
|
||||
var t = new Date();
|
||||
if ((t.getSeconds() % 5) === 0) draw();
|
||||
}
|
||||
|
||||
return {init:draw, tick:onSecond};
|
||||
}
|
||||
|
||||
return getFace;
|
||||
|
||||
})();
|
|
@ -1,202 +0,0 @@
|
|||
(() => {
|
||||
|
||||
function getFace(){
|
||||
var nofix = 0;
|
||||
|
||||
function formatTime(now) {
|
||||
var fd = now.toUTCString().split(" ");
|
||||
return fd[4];
|
||||
}
|
||||
|
||||
function timeSince(t) {
|
||||
var hms = t.split(":");
|
||||
var now = new Date();
|
||||
|
||||
var sn = 3600*(now.getHours()) + 60*(now.getMinutes()) + 1*(now.getSeconds());
|
||||
var st = 3600*(hms[0]) + 60*(hms[1]) + 1*(hms[2]);
|
||||
|
||||
return (sn - st);
|
||||
}
|
||||
|
||||
|
||||
Number.prototype.toRad = function() { return this*Math.PI/180; };
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
/* Ordnance Survey Grid Reference functions (c) Chris Veness 2005-2014 */
|
||||
/* - www.movable-type.co.uk/scripts/gridref.js */
|
||||
/* - www.movable-type.co.uk/scripts/latlon-gridref.html */
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
function OsGridRef(easting, northing) {
|
||||
this.easting = 0|easting;
|
||||
this.northing = 0|northing;
|
||||
}
|
||||
OsGridRef.latLongToOsGrid = function(point) {
|
||||
var lat = point.lat.toRad();
|
||||
var lon = point.lon.toRad();
|
||||
|
||||
var a = 6377563.396, b = 6356256.909; // Airy 1830 major & minor semi-axes
|
||||
var F0 = 0.9996012717; // NatGrid scale factor on central meridian
|
||||
var lat0 = (49).toRad(), lon0 = (-2).toRad(); // NatGrid true origin is 49�N,2�W
|
||||
var N0 = -100000, E0 = 400000; // northing & easting of true origin, metres
|
||||
var e2 = 1 - (b*b)/(a*a); // eccentricity squared
|
||||
var n = (a-b)/(a+b), n2 = n*n, n3 = n*n*n;
|
||||
|
||||
var cosLat = Math.cos(lat), sinLat = Math.sin(lat);
|
||||
var nu = a*F0/Math.sqrt(1-e2*sinLat*sinLat); // transverse radius of curvature
|
||||
var rho = a*F0*(1-e2)/Math.pow(1-e2*sinLat*sinLat, 1.5); // meridional radius of curvature
|
||||
var eta2 = nu/rho-1;
|
||||
|
||||
var Ma = (1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0);
|
||||
var Mb = (3*n + 3*n*n + (21/8)*n3) * Math.sin(lat-lat0) * Math.cos(lat+lat0);
|
||||
var Mc = ((15/8)*n2 + (15/8)*n3) * Math.sin(2*(lat-lat0)) * Math.cos(2*(lat+lat0));
|
||||
var Md = (35/24)*n3 * Math.sin(3*(lat-lat0)) * Math.cos(3*(lat+lat0));
|
||||
var M = b * F0 * (Ma - Mb + Mc - Md); // meridional arc
|
||||
|
||||
var cos3lat = cosLat*cosLat*cosLat;
|
||||
var cos5lat = cos3lat*cosLat*cosLat;
|
||||
var tan2lat = Math.tan(lat)*Math.tan(lat);
|
||||
var tan4lat = tan2lat*tan2lat;
|
||||
|
||||
var I = M + N0;
|
||||
var II = (nu/2)*sinLat*cosLat;
|
||||
var III = (nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2);
|
||||
var IIIA = (nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat);
|
||||
var IV = nu*cosLat;
|
||||
var V = (nu/6)*cos3lat*(nu/rho-tan2lat);
|
||||
var VI = (nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2);
|
||||
|
||||
var dLon = lon-lon0;
|
||||
var dLon2 = dLon*dLon, dLon3 = dLon2*dLon, dLon4 = dLon3*dLon, dLon5 = dLon4*dLon, dLon6 = dLon5*dLon;
|
||||
|
||||
var N = I + II*dLon2 + III*dLon4 + IIIA*dLon6;
|
||||
var E = E0 + IV*dLon + V*dLon3 + VI*dLon5;
|
||||
|
||||
return new OsGridRef(E, N);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* converts northing, easting to standard OS grid reference.
|
||||
*
|
||||
* [digits=10] - precision (10 digits = metres)
|
||||
* to_map_ref(8, 651409, 313177); => 'TG 5140 1317'
|
||||
* to_map_ref(0, 651409, 313177); => '651409,313177'
|
||||
*
|
||||
*/
|
||||
function to_map_ref(digits, easting, northing) {
|
||||
if (![ 0,2,4,6,8,10,12,14,16 ].includes(Number(digits))) throw new RangeError(`invalid precision '${digits}'`); // eslint-disable-line comma-spacing
|
||||
|
||||
let e = easting;
|
||||
let n = northing;
|
||||
|
||||
// use digits = 0 to return numeric format (in metres) - note northing may be >= 1e7
|
||||
if (digits == 0) {
|
||||
const format = { useGrouping: false, minimumIntegerDigits: 6, maximumFractionDigits: 3 };
|
||||
const ePad = e.toLocaleString('en', format);
|
||||
const nPad = n.toLocaleString('en', format);
|
||||
return `${ePad},${nPad}`;
|
||||
}
|
||||
|
||||
// get the 100km-grid indices
|
||||
const e100km = Math.floor(e / 100000), n100km = Math.floor(n / 100000);
|
||||
|
||||
// translate those into numeric equivalents of the grid letters
|
||||
let l1 = (19 - n100km) - (19 - n100km) % 5 + Math.floor((e100km + 10) / 5);
|
||||
let l2 = (19 - n100km) * 5 % 25 + e100km % 5;
|
||||
|
||||
// compensate for skipped 'I' and build grid letter-pairs
|
||||
if (l1 > 7) l1++;
|
||||
if (l2 > 7) l2++;
|
||||
const letterPair = String.fromCharCode(l1 + 'A'.charCodeAt(0), l2 + 'A'.charCodeAt(0));
|
||||
|
||||
// strip 100km-grid indices from easting & northing, and reduce precision
|
||||
e = Math.floor((e % 100000) / Math.pow(10, 5 - digits / 2));
|
||||
n = Math.floor((n % 100000) / Math.pow(10, 5 - digits / 2));
|
||||
|
||||
// pad eastings & northings with leading zeros
|
||||
e = e.toString().padStart(digits/2, '0');
|
||||
n = n.toString().padStart(digits/2, '0');
|
||||
|
||||
return `${letterPair} ${e} ${n}`;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
var gps_on = false;
|
||||
|
||||
var fix = {
|
||||
fix: 0,
|
||||
alt: 0,
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
speed: 0,
|
||||
time: 0,
|
||||
satellites: 0
|
||||
};
|
||||
|
||||
var y_line = 26;
|
||||
var y_start = 46;
|
||||
var x_start = 10;
|
||||
|
||||
// only attempt to get gps fix if gpsservuce is loaded
|
||||
if (WIDGETS.gpsservice !== undefined) {
|
||||
fix = WIDGETS.gpsservice.gps_get_fix();
|
||||
gps_on = WIDGETS.gpsservice.gps_get_status();
|
||||
}
|
||||
|
||||
g.reset();
|
||||
g.clearRect(0,24,239,239);
|
||||
|
||||
if (fix.fix) {
|
||||
var time = formatTime(fix.time);
|
||||
var age = timeSince(time);
|
||||
var os = OsGridRef.latLongToOsGrid(fix);
|
||||
var ref = to_map_ref(6, os.easting, os.northing);
|
||||
age = age >=0 ? age : 0; // avoid -1 etc
|
||||
|
||||
g.reset();
|
||||
g.clearRect(0,24,239,239);
|
||||
g.setFontAlign(0,0);
|
||||
g.setFont("Vector");
|
||||
g.setColor(1,1,1);
|
||||
g.setFontVector(40);
|
||||
g.drawString(time, 120, 80);
|
||||
|
||||
g.setFontVector(40);
|
||||
g.setColor(0xFFC0);
|
||||
g.drawString(ref, 120,140, true);
|
||||
|
||||
g.setFont("6x8",2);
|
||||
g.setColor(1,1,1);
|
||||
g.drawString(age, 120, 194);
|
||||
|
||||
} else if (gps_on) {
|
||||
|
||||
g.setFontAlign(0, 1);
|
||||
g.setFont("6x8", 2);
|
||||
g.drawString("Gridref Watch", 120, 60);
|
||||
g.drawString("Waiting for GPS", 120, 80);
|
||||
nofix = (nofix+1) % 4;
|
||||
g.drawString(".".repeat(nofix) + " ".repeat(4-nofix), 120, 120);
|
||||
g.setFontAlign(0,0);
|
||||
g.drawString(fix.satellites + " satellites", 120, 100);
|
||||
|
||||
} else if (!gps_on) {
|
||||
|
||||
g.setFontAlign(0, 0);
|
||||
g.setFont("6x8", 3);
|
||||
g.drawString("Gridref Watch", 120, 80);
|
||||
g.drawString("GPS is off", 120, 160);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function onSecond(){
|
||||
var t = new Date();
|
||||
if ((t.getSeconds() % 5) === 0) draw();
|
||||
}
|
||||
|
||||
return {init:draw, tick:onSecond};
|
||||
}
|
||||
|
||||
return getFace;
|
||||
|
||||
})();
|
|
@ -2,3 +2,4 @@
|
|||
0.02: Add notification ID option
|
||||
0.03: Pass `area{x,y,w,h}` to render callback instead of just `y`
|
||||
0.05: Adjust position of notification src text
|
||||
0.06: Support background color
|
||||
|
|
|
@ -41,7 +41,9 @@ function fitWords(text,rows,width) {
|
|||
src : string // optional source name
|
||||
body : string // optional body text
|
||||
icon : string // optional icon (image string)
|
||||
render function(y) // function callback to render
|
||||
render : function(y) // function callback to render
|
||||
bgColor : int/string // optional background color (default black)
|
||||
titleBgColor : int/string // optional background color for title (default black)
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
@ -83,13 +85,13 @@ exports.show = function(options) {
|
|||
b = y+h-1, r = x+w-1; // bottom,right
|
||||
g.setClipRect(x,y, r,b);
|
||||
// clear area
|
||||
g.setColor(0).fillRect(x,y, r,b);
|
||||
g.setColor(options.bgColor||0).fillRect(x,y, r,b);
|
||||
// bottom border
|
||||
g.setColor(0x39C7).fillRect(0,b-1, r,b);
|
||||
b -= 2;h -= 2;
|
||||
// title bar
|
||||
if (options.title || options.src) {
|
||||
g.setColor(0x39C7).fillRect(x,y, r,y+20);
|
||||
g.setColor(options.titleBgColor||0x39C7).fillRect(x,y, r,y+20);
|
||||
const title = options.title||options.src;
|
||||
g.setColor(-1).setFontAlign(-1, -1, 0).setFont("6x8", 2);
|
||||
g.drawString(title.trim().substring(0, 13), x+25,y+3);
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.04: Pass `area{x,y,w,h}` to render callback instead of just `y`
|
||||
0.05: Fix `g` corruption issue if .hide gets called twice
|
||||
0.06: Adjust position of notification src text and notifications without title
|
||||
0.07: Support background color
|
||||
|
|
|
@ -37,7 +37,9 @@ function fitWords(text,rows,width) {
|
|||
src : string // optional source name
|
||||
body : string // optional body text
|
||||
icon : string // optional icon (image string)
|
||||
render function(y) // function callback to render
|
||||
render : function(y) // function callback to render
|
||||
bgColor : int/string // optional background color (default black)
|
||||
titleBgColor : int/string // optional background color for title (default black)
|
||||
}
|
||||
*/
|
||||
exports.show = function(options) {
|
||||
|
@ -53,11 +55,11 @@ exports.show = function(options) {
|
|||
w = 240,
|
||||
h = size;
|
||||
// clear screen
|
||||
g.clear(1);
|
||||
g.setColor(options.bgColor||0).fillRect(0,0,g.getWidth(),g.getHeight());
|
||||
// top bar
|
||||
if (options.title||options.src) {
|
||||
const title = options.title || options.src
|
||||
g.setColor(0x39C7).fillRect(x, y, x+w-1, y+30);
|
||||
g.setColor(options.titleBgColor||0x39C7).fillRect(x, y, x+w-1, y+30);
|
||||
g.setColor(-1).setFontAlign(-1, -1, 0).setFont("6x8", 3);
|
||||
g.drawString(title.trim().substring(0, 13), x+5, y+3);
|
||||
if (options.title && options.src) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkE/4A///zmfzn4fbDhQqBAAQMHj4XJ+SQGh4MDl4vKgMRAAgXEF5X/iAXWkEQIoQ0BC4kTC5UwC4cAC4sSC5XxgIXJkJwDPBAXJiCQCmbEGC5kTn7PBC4vzkMRC5UQgUikYuFmILBC5SwCVYMikMSmf/gaPLEYMBMQMwW4fzgUyL5YwCkQLBAATKBmJfMiIlBB4Q1BBYPwC5oZCiMSOgKUB+RHMkQlBN4MjCYMDC50jiMzgMiYgMBgQXMTYMziM/a4QXBgLvM+MBmcSiYIDkAXBHgQXI+cj+ciOQQABkMibIIXKAAMzmYqBDAUBkEAkRHKLQcgiBJB+bBBgZTBC5MvC4apBU4UAl53Lj4XCbYUCCYIzCC5RsBWwakCQYYXKAAUxBwMRYYUykUyC5swLwMBiESUQM/O5a/COwQYBAIIyBmAXLZ4IsBBoYABgUwBAYXHmUABogFCl4XL/8yiINESIMjNAIvLLoYWDQAYXLLoh1Ckc//7fBC5LUCC4gCBgUQBQoXFWYp1BRwIsBQAoXNn5JBNAgXHdgIAEiH/C4QAGC4kgEgsD+YHFAAYXEEY0v+QuIiMfa4gAh+cz/8z+c/AIIXQAQIVBAwQYQABI="))
|
|
@ -0,0 +1,29 @@
|
|||
const strategies = ['Abandon normal instruments', 'Accept advice', 'Accretion', 'A line has two sides', 'Allow an easement (an easement is the abandonment of a stricture)', 'Are there sections? Consider transitions', 'Ask people to work against their better judgement', 'Ask your body', 'Assemble some of the instruments in a group and treat the group', 'Balance the consistency principle with the inconsistency principle', 'Be dirty', 'Breathe more deeply', 'Bridges -build -burn', 'Cascades', 'Change instrument roles', 'Change nothing and continue with immaculate consistency', "Children's voices -speaking -singing", 'Cluster analysis', 'Consider different fading systems', 'Consult other sources -promising -unpromising', 'Convert a melodic element into a rhythmic element', 'Courage!', 'Cut a vital connection', 'Decorate, decorate', "Define an area as `safe' and use it as an anchor", 'Destroy -nothing -the most important thing', 'Discard an axiom', 'Disconnect from desire', 'Discover the recipes you are using and abandon them', 'Distorting time', 'Do nothing for as long as possible', "Don't be afraid of things because they're easy to do", "Don't be frightened of cliches", "Don't be frightened to display your talents", "Don't break the silence", "Don't stress one thing more than another", 'Do something boring', 'Do the washing up', 'Do the words need changing?', 'Do we need holes?', 'Emphasize differences', 'Emphasize repetitions', 'Emphasize the flaws', 'Faced with a choice, do both (given by Dieter Rot)', 'Feedback recordings into an acoustic situation', 'Fill every beat with something', 'Get your neck massaged', 'Ghost echoes', 'Give the game away', 'Give way to your worst impulse', 'Go slowly all the way round the outside', 'Honor thy error as a hidden intention', 'How would you have done it?', 'Humanize something free of error', 'Imagine the music as a moving chain or caterpillar', 'Imagine the music as a set of disconnected events', 'Infinitesimal gradations', 'Intentions -credibility of -nobility of -humility of', 'Into the impossible', 'Is it finished?', 'Is there something missing?', 'Is the tuning appropriate?', 'Just carry on', 'Left channel, right channel, centre channel', 'Listen in total darkness, or in a very large room, very quietly', 'Listen to the quiet voice', 'Look at a very small object, look at its centre', 'Look at the order in which you do things', 'Look closely at the most embarrassing details and amplify them', 'Lowest common denominator check -single beat -single note -single', 'riff', 'Make a blank valuable by putting it in an exquisite frame', 'Make an exhaustive list of everything you might do and do the last', 'thing on the list', 'Make a sudden, destructive unpredictable action; incorporate', 'Mechanicalize something idiosyncratic', 'Mute and continue', 'Only one element of each kind', '(Organic) machinery', 'Overtly resist change', 'Put in earplugs', 'Remember those quiet evenings', 'Remove ambiguities and convert to specifics', 'Remove specifics and convert to ambiguities', 'Repetition is a form of change', 'Reverse', 'Short circuit (example: a man eating peas with the idea that they will', 'improve his virility shovels them straight into his lap)', 'Shut the door and listen from outside', 'Simple subtraction', 'Spectrum analysis', 'Take a break', 'Take away the elements in order of apparent non-importance', 'Tape your mouth (given by Ritva Saarikko)', 'The inconsistency principle', 'The tape is now the music', 'Think of the radio', 'Tidy up', 'Trust in the you of now', 'Turn it upside down', 'Twist the spine', 'Use an old idea', 'Use an unacceptable color', 'Use fewer notes', 'Use filters', 'Use "unqualified" people', 'Water', 'What are you really thinking about just now? Incorporate', 'What is the reality of the situation?', 'What mistakes did you make last time?', 'What would your closest friend do?', "What wouldn't you do?", 'Work at a different speed', 'You are an engineer', 'You can only make one dot at a time', "You don't have to be ashamed of using your own ideas", '[blank white card]']
|
||||
|
||||
const spentStrategies = []
|
||||
|
||||
function chooseObliqueness() {
|
||||
const strategy = strategies[Math.floor(Math.random() * strategies.length)];
|
||||
spentStrategies.push(strategy);
|
||||
return strategy
|
||||
}
|
||||
|
||||
// app intro
|
||||
E.showMessage('oblique strategies\n\ncopied from\nbrian eno\n\nclick btn2');
|
||||
|
||||
setWatch(() => {
|
||||
// beep!
|
||||
Bangle.beep();
|
||||
|
||||
// get the strategy
|
||||
const strategy = chooseObliqueness();
|
||||
|
||||
// configure font
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
// show the oblique strategy
|
||||
E.showMessage(strategy.replace(/\s/g, '\n'));
|
||||
|
||||
// clear the screen
|
||||
setTimeout(() => g.clear(), 10000);
|
||||
}, BTN2, { repeat: true });
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Major speed improvement. Added more stars. Up to 500!
|
||||
0.03: Added more stars and constellations. Now it shows 20 constellations.
|
|
@ -0,0 +1,32 @@
|
|||
# Planetarium
|
||||
|
||||
This planetarium takes your position and time and plots the sky as it is.
|
||||
|
||||
No planets, or moon, only stars. It can show the 500 most brilliant stars in the sky.
|
||||
|
||||
It shows also constellations. Now it has 20 constellations but this is work in progress. Only northern hemisphere covered now.
|
||||
|
||||
I think code is quite optimized already. It runs as fast as I could make it run. If someone has some ideas to speed it up, I could plot more stars.
|
||||
|
||||
Basic equations to compute declination and right ascension for stars where taken from this [github repo](https://github.com/Michi83/planetarium). Thanks!
|
||||
|
||||
## How to use
|
||||
The planetarium plots the stars as if you are looking to the sky (with your watch screen pointing downwards). This means, if you have the watch in your wrist, you have to look south to see the stars matching. If you want to look north, just take out the watch from your wrist and make a 180º turn.
|
||||
|
||||
## Improvements
|
||||
I plan to add more constellations as soon as I have time. I am adding the constellations that I know of, but the plan is to add all the main ones (at least for North Hemisphere).
|
||||
|
||||
Please note that the watch hardware is limited and computing the stars positions is a quite intensive task for this little processor. This is why it plots only stars and no planets or the moon. For plotting the planets, storage will be a limiting factor as well as computing the position for planets needs more initial data compared with stars.
|
||||
|
||||
## Do you want to contribute?
|
||||
Maybe you want to add some more constellations to the planetarium. As you can see I didn't cover constellations in the south hemisphere. How to do it? It is a bit tedious but it can be done and you will learn the constellations pretty well at the end of it. Steps:
|
||||
- Open the file `plantearium.data.csv`. There you have the 500 stars that we have in the planetarium. The number of each star is the line number. For instance for Sirius, the star number will be 1.
|
||||
- Find the two stars that you want to join in your constellation (a constellation line). For identifying a star you have to have a look at the name, usually something like `AL UMA` (alpha star of constellation ursa major). Lets say that you want to join stars 155 and 8 (this is constellation canis menor, that only has a line joining two stars).
|
||||
- Go to file `planetarium.const.csv` and add two lines for your new constellation. The first one will be the name of the constellation, the second one the pair of stars that you want to join, separated by coma (see the file for examples).
|
||||
- Do not forget to add a break line after the last constellation.
|
||||
- Upload the new `planetarium.const.csv` to your bangle (or emulator) and test it out.
|
||||
|
||||
What is a constellation star is not in the 500 star list in `planetarium.data.csv`? If you need another star to draw the constellation you can find that star in the full star list (`starinfo/planetarium.stars.csv`) and put it in `planetarium.extra.csv`. That stars will be loaded only when constellations are shown. In order to refer to these extra stars in the `planetarium.const.csv` you have to use the code `e_linenumber`, in order to differentiate them from the stars in the normal file. For instance, to refer to the first star in the file `planetarium.extra.csv`, you will refer it as `e_1`. Do not forget to add an extra line at the end as in the other files.
|
||||
|
||||
## Development version
|
||||
Please check the latest development version [here](https://github.com/pglez82/BangleApps)
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwgkhiIAECp8BCwoABiAWVDBoWKDBgWLMZQuMGBQWNGBAuHjtBGBomHjvRGBhdI7vUMJgLGilE7vdohJHC5MUCoIADDAxGKpoWDJI5ICC44wESJS1IGAR4IJAQXgI4YXJXpAXBoJiBBhEQC5JzCigXTABgXeIBJODC5MdaA4hB6IXLpoNFEIbDFC4zRJboIXJojRC6lEBwdEegXdBIYXDZwIAEeY4ABNgQvEEgfdMIkdBIZTDC4gwELwouGC4MABoyQGHQSCEgAXHSAxSDC7pgDKQJiBL4xcBBIZeBC4cUNIUUC4oJGC4RIEAB4WCC7BgDABxGDGCYWEGCIuFGCIWGGB4uHGB4WIGBouJDBgWLDBQWNMZAVPACAA=="))
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Degrees to radians
|
||||
*/
|
||||
function toRadians(degrees)
|
||||
{
|
||||
return Math.PI * degrees / 180;
|
||||
}
|
||||
|
||||
/*
|
||||
* Julian day number
|
||||
* Assumes a proleptic gregorian calendar where the year 1 is preceded by the
|
||||
* year 0.
|
||||
*/
|
||||
function toJulianDay(year, month, day, hours, minutes, seconds)
|
||||
{
|
||||
day += hours / 24 + minutes / 1440 + seconds / 86400;
|
||||
|
||||
if(month <= 2)
|
||||
{
|
||||
year -= 1;
|
||||
month += 12;
|
||||
}
|
||||
|
||||
var A = Math.floor(year / 100);
|
||||
var B = 2 - A + Math.floor(A / 4);
|
||||
return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidereal time in Greenwich
|
||||
*/
|
||||
function siderealTime(julianDay)
|
||||
{
|
||||
var T = (julianDay - 2451545.0) / 36525;
|
||||
return toRadians(280.46061837 + 360.98564736629 * (julianDay - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws a single star in the sky.
|
||||
* starPositions is a dictionary that gets modified and it is used later for ploting the constelations
|
||||
*/
|
||||
function drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,starNumber,starPositions){
|
||||
let starRA = parseFloat(starInfo[0]);
|
||||
let starDE = parseFloat(starInfo[1]);
|
||||
let starMag = parseFloat(starInfo[2]);
|
||||
var dec = Math.asin(Math.sin(theta) * Math.cos(starDE) * Math.cos(starRA + zeta) + Math.cos(theta) * Math.sin(starDE));
|
||||
var ascen = Math.atan2(Math.cos(starDE) * Math.sin(starRA + zeta), Math.cos(theta) * Math.cos(starDE) * Math.cos(starRA + zeta) - Math.sin(theta) * Math.sin(starDE)) + z;
|
||||
var H = siderealTime(julianDay) - longitude - ascen;
|
||||
//Compute altitude
|
||||
var alt = Math.asin(Math.sin(latitude) * Math.sin(dec) + Math.cos(latitude) * Math.cos(dec) * Math.cos(H));
|
||||
if(alt >= 0)
|
||||
{
|
||||
//Compute azimuth
|
||||
var azi = Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(latitude) - Math.tan(dec) * Math.cos(latitude));
|
||||
var x = size / 2 + size / 2 * Math.cos(alt) * Math.sin(azi);
|
||||
var y = size / 2 + size / 2 * Math.cos(alt) * Math.cos(azi);
|
||||
starPositions[starNumber] = [x,y];
|
||||
var magnitude = starMag<1?2:1;
|
||||
//Stars between 1.5 and 4 magnitude should get a different colour
|
||||
var col=1;
|
||||
if (starMag<=1.5)
|
||||
col=1;
|
||||
else if (starMag>1.5 && starMag<2)
|
||||
col=0.9;
|
||||
else if (starMag>=2 && starMag<3)
|
||||
col=0.7;
|
||||
else if (starMag>=3 && starMag<3.5)
|
||||
col=0.5;
|
||||
else
|
||||
col=0.3;
|
||||
|
||||
g.setColor(col,col,col);
|
||||
g.fillCircle(x, y, magnitude);
|
||||
if (starMag<1 && settings.starnames)
|
||||
g.drawString(starInfo[3],x,y+2);
|
||||
g.flip();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function plotSky(lat,lon,date){
|
||||
var longitude = toRadians(-lon);
|
||||
var latitude = toRadians(lat);
|
||||
|
||||
var julianDay = toJulianDay(date.getFullYear(), date.getMonth()+1,date.getDate(),
|
||||
date.getHours() + date.getTimezoneOffset() / 60,
|
||||
date.getMinutes(), date.getSeconds());
|
||||
|
||||
|
||||
storage = require('Storage');
|
||||
f=storage.read("planetarium.data.csv","r");
|
||||
g.clear();
|
||||
|
||||
//Common calculations based only on time
|
||||
var t = (julianDay - 2451545.0) / 36525;
|
||||
var zeta = toRadians((2306.2181 * t + 0.30188 * t * t + 0.017998 * t * t * t) / 3600);
|
||||
var theta = toRadians((2004.3109 * t - 0.42665 * t * t - 0.041833 * t * t * t) / 3600);
|
||||
var z = toRadians((2306.2181 * t + 1.09468 * t * t + 0.018203 * t * t * t) / 3600);
|
||||
|
||||
|
||||
let starNumber = 0;
|
||||
var starPositions = {};
|
||||
|
||||
var line,linestart = 0;
|
||||
lineend = f.indexOf("\n");
|
||||
while (lineend>=0) {
|
||||
line = f.substring(linestart,lineend);
|
||||
starNumber++;
|
||||
//Process the star
|
||||
starInfo = line.split(',');
|
||||
drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,starNumber,starPositions);
|
||||
linestart = lineend+1;
|
||||
lineend = f.indexOf("\n",linestart);
|
||||
}
|
||||
|
||||
|
||||
if (settings.constellations){
|
||||
//First plot the extra stars for the constellations
|
||||
fe=storage.read("planetarium.extra.csv","r");
|
||||
linenum=linestart = 0;
|
||||
lineend = fe.indexOf("\n");
|
||||
let starNumber = 0;
|
||||
while (lineend>=0) {
|
||||
line = fe.substring(linestart,lineend);
|
||||
starNumber++;
|
||||
starInfo = line.split(',');
|
||||
drawStar(zeta,theta,z,julianDay,latitude,longitude,starInfo,"e_"+starNumber,starPositions);
|
||||
linestart = lineend+1;
|
||||
lineend = fe.indexOf("\n",linestart);
|
||||
}
|
||||
//End of ploting extra stars
|
||||
|
||||
linenum=linestart = 0;
|
||||
fc=storage.read("planetarium.const.csv","r");
|
||||
lineend = fc.indexOf("\n");
|
||||
while (lineend>=0) {
|
||||
linenum++;
|
||||
//In this file, each constelation are two lines. The first one the name, the second the lines joining stars
|
||||
var name = fc.substring(linestart,lineend);
|
||||
linestart = lineend+1;
|
||||
lineend = fc.indexOf("\n",linestart);
|
||||
var lines = fc.substring(linestart,lineend).split(',');
|
||||
linestart = lineend+1;
|
||||
lineend = fc.indexOf("\n",linestart);
|
||||
g.setColor(0,255,0);
|
||||
|
||||
constelationShowing=false;
|
||||
|
||||
for (j=0;j<lines.length;j++){
|
||||
positions = lines[j].split(' ');
|
||||
positionStar1=starPositions[positions[0]];
|
||||
positionStar2=starPositions[positions[1]];
|
||||
//Both stars need to be visible
|
||||
if (positionStar1 && positionStar2)
|
||||
{
|
||||
g.drawLine(positionStar1[0],positionStar1[1],positionStar2[0],positionStar2[1]);
|
||||
constelationShowing=true;
|
||||
}
|
||||
else
|
||||
constelationShowing=false;
|
||||
g.flip();
|
||||
}
|
||||
|
||||
//Write the name
|
||||
if (constelationShowing && settings.consnames)
|
||||
g.drawString(name,positionStar2[0]+10,positionStar2[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const size = 240; //Bangle size screen
|
||||
|
||||
Bangle.setGPSPower(1);
|
||||
|
||||
var gps = { fix : 0};
|
||||
var prevSats = 0;
|
||||
g.clear();
|
||||
|
||||
var settings = require('Storage').readJSON('planetarium.json',1)||
|
||||
{ starnames:false,constellations:true,consnames:false};
|
||||
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
Bangle.on('GPS',function(gp) {
|
||||
date = new Date();
|
||||
gps = gp;
|
||||
if (gp.fix) {
|
||||
lat = gp.lat;
|
||||
lon = gp.lon;
|
||||
Bangle.setGPSPower(0);
|
||||
setTimeout(function() {
|
||||
plotSky(lat,lon,new Date());},0);
|
||||
} else {
|
||||
g.setFont("Vector",20);
|
||||
g.drawString("Waiting for position",120,120);
|
||||
g.setFont("Vector",15);
|
||||
if (gp.satellites>prevSats || prevSats===0){
|
||||
prevSats = gp.satellites;
|
||||
g.clearRect(0,150,240,180);
|
||||
g.drawString("Got "+gp.satellites+" satellites",120,160);
|
||||
}
|
||||
g.clearRect(0,180,240,220);
|
||||
g.drawString("GMT:"+(date.getHours()+date.getTimezoneOffset() / 60)+":"+date.getMinutes()+":"+date.getSeconds(),120,200);
|
||||
g.drawString(date.getDate()+'/'+date.getMonth()+1+"/"+date.getFullYear(),120,215);
|
||||
g.flip();
|
||||
}
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
Orion
|
||||
7 68,10 53,53 56,28 68
|
||||
Taurus
|
||||
13 172,13 340,293 340,29 293,340 276
|
||||
Canis Menor
|
||||
155 8
|
||||
Ursa Major
|
||||
36 81,87 81,235 87,33 235,33 75,75 40,36 235
|
||||
Cassiopeia
|
||||
67 91,74 67,91 110,110 252
|
||||
Gemini
|
||||
23 166,16 294,294 44,166 149,230 149,16 23
|
||||
Cepheus
|
||||
88 218,215 292,218 292,245 88,292 245,215 218
|
||||
Perseus
|
||||
150 62,150 175,175 35,403 62,487 158,384 487,384 158,35 158,487 e_3,e_3 403
|
||||
Cygnus
|
||||
19 65,65 90,65 147,466 65,466 189,147 401,213 90
|
||||
Auriga
|
||||
6 42,168 6,168 113,113 29,104 29,104 42
|
||||
Can Maior
|
||||
1 37,22 178,37 435,435 89,1 e_18,e_18 e_19,e_19 e_20,e_20 e_18,37 277,277 22,450 488,277 488,488 47,1 488,e_21 488,22 495
|
||||
Bootes
|
||||
3 118,118 279,279 286,286 180,180 316,316 3
|
||||
Lupus
|
||||
140 210,322 140,322 410,410 98,98 234,234 210,98 302,302 362,234 e_1,234 e_2
|
||||
Leo
|
||||
21 291,102 270,102 291,96 63,63 241,241 96,96 102,21 241,457 270,457 167
|
||||
Lyra
|
||||
5 e_4,e_4 e_5,e_5 221,221 274,274 e_4
|
||||
Corona Borealis
|
||||
69 353,353 e_6,69 429,429 e_7,e_7 e_8,e_8 e_9
|
||||
Herculis
|
||||
296 135,135 477,477 203,203 296,443 203,443 408,135 127,127 380,e_10 477,464 296,265 e_10,e_10 202
|
||||
Ursa Minor
|
||||
50 e_11,e_11 e_14,e_14 e_13,e_13 e_12,e_12 186,186 58,58 e_13
|
||||
Draco
|
||||
e_15 131,131 70,70 382,382 e_15,382 187,187 423,423 e_16,e_16 207,207 122,122 e_17,e_17 232,232 342,342 452,452 428
|
||||
Pegasus
|
||||
92 85,138 54,54 85,138 92,283 85,283 389,160 85,92 258,258 297,297 83
|
|
|
@ -0,0 +1,500 @@
|
|||
1.768,-0.292,-1.5,Sirius
|
||||
1.675,-0.920,-0.7,AL CAR
|
||||
3.734,0.335,-0.0,Arcturus
|
||||
3.838,-1.062,-0.0,AL1 CEN
|
||||
4.874,0.677,0.0,Vega
|
||||
1.382,0.803,0.1,Capella
|
||||
1.372,-0.143,0.1,Rigel
|
||||
2.004,0.091,0.4,Procyion
|
||||
0.426,-0.999,0.5,AL ERI
|
||||
1.550,0.129,0.5,Betelgeuse
|
||||
3.682,-1.054,0.6,BE CEN
|
||||
5.196,0.155,0.8,AL AQL
|
||||
1.204,0.288,0.8,Aldebaran
|
||||
4.317,-0.461,1.0,AL SCO
|
||||
3.513,-0.195,1.0,AL VIR
|
||||
2.030,0.489,1.1,Pollux
|
||||
6.011,-0.517,1.2,AL PSA
|
||||
3.350,-1.042,1.2,BE CRU
|
||||
5.417,0.790,1.2,Deneb
|
||||
3.838,-1.062,1.3,AL2 CEN
|
||||
2.655,0.209,1.4,AL LEO
|
||||
1.827,-0.506,1.5,EP CMA
|
||||
1.984,0.557,1.6,Castor
|
||||
3.258,-1.101,1.6,AL1 CRU
|
||||
1.984,0.557,1.6,AL GEM
|
||||
3.278,-0.997,1.6,GA CRU
|
||||
4.597,-0.648,1.6,LA SCO
|
||||
1.419,0.111,1.6,Bellatrix
|
||||
1.424,0.499,1.6,BE TAU
|
||||
2.414,-1.217,1.7,BE CAR
|
||||
1.467,-0.021,1.7,EP ORI
|
||||
5.796,-0.820,1.7,AL GRU
|
||||
3.377,0.977,1.8,EP UMA
|
||||
2.136,-0.826,1.8,GA2 VEL
|
||||
0.892,0.870,1.8,AL PER
|
||||
2.896,1.078,1.8,AL UMA
|
||||
1.869,-0.461,1.8,DE CMA
|
||||
4.818,-0.600,1.9,EP SGR
|
||||
2.193,-1.039,1.9,EP CAR
|
||||
3.611,0.861,1.9,ET UMA
|
||||
4.613,-0.750,1.9,TH SCO
|
||||
1.569,0.784,1.9,BE AUR
|
||||
4.401,-1.205,1.9,AL TRA
|
||||
1.735,0.286,1.9,GA GEM
|
||||
5.348,-0.990,1.9,AL PAV
|
||||
2.289,-0.955,2.0,DE VEL
|
||||
1.670,-0.313,2.0,BE CMA
|
||||
2.477,-0.151,2.0,AL HYA
|
||||
0.555,0.409,2.0,AL ARI
|
||||
0.663,1.558,2.0,Polaris
|
||||
4.954,-0.459,2.0,SI SGR
|
||||
0.190,-0.314,2.0,BE CET
|
||||
1.487,-0.034,2.0,ZE ORI
|
||||
0.037,0.508,2.1,AL AND
|
||||
0.304,0.622,2.1,BE AND
|
||||
1.517,-0.169,2.1,KA ORI
|
||||
3.694,-0.635,2.1,TH CEN
|
||||
3.886,1.294,2.1,BE UMI
|
||||
4.603,0.219,2.1,AL OPH
|
||||
3.258,-1.101,2.1,AL2 CRU
|
||||
5.946,-0.818,2.1,BE GRU
|
||||
0.821,0.715,2.1,BE PER
|
||||
3.094,0.254,2.1,BE LEO
|
||||
3.323,-0.855,2.2,GA CEN
|
||||
5.333,0.703,2.2,GA CYG
|
||||
2.391,-0.758,2.2,LA VEL
|
||||
0.177,0.987,2.2,AL CAS
|
||||
1.449,-0.005,2.2,DE ORI
|
||||
4.078,0.466,2.2,AL CRB
|
||||
4.698,0.899,2.2,GA DRA
|
||||
2.110,-0.698,2.2,ZE PUP
|
||||
2.431,-1.035,2.2,JO CAR
|
||||
0.541,0.739,2.3,GA1 AND
|
||||
0.040,1.032,2.3,BE CAS
|
||||
3.508,0.959,2.3,ZE UMA
|
||||
4.408,-0.599,2.3,EP SCO
|
||||
3.577,-0.933,2.3,EP CEN
|
||||
3.848,-0.827,2.3,AL LUP
|
||||
3.820,-0.736,2.3,ET CEN
|
||||
4.190,-0.395,2.3,DE SCO
|
||||
2.888,0.984,2.4,BE UMA
|
||||
0.115,-0.738,2.4,AL PHE
|
||||
5.691,0.172,2.4,EP PEG
|
||||
4.636,-0.681,2.4,KA SCO
|
||||
6.038,0.490,2.4,BE PEG
|
||||
4.496,-0.274,2.4,ET OPH
|
||||
3.115,0.937,2.4,GA UMA
|
||||
5.579,1.092,2.4,AL CEP
|
||||
1.938,-0.511,2.5,ET CMA
|
||||
5.438,0.593,2.5,EP CYG
|
||||
0.247,1.060,2.5,GA CAS
|
||||
6.042,0.265,2.5,AL PEG
|
||||
2.453,-0.960,2.5,KA VEL
|
||||
0.795,0.071,2.5,AL CET
|
||||
3.646,-0.825,2.5,ZE CEN
|
||||
2.941,0.358,2.6,DE LEO
|
||||
4.351,-0.184,2.6,ZE OPH
|
||||
1.452,-0.311,2.6,AL LEP
|
||||
3.211,-0.306,2.6,GA CRV
|
||||
3.178,-0.885,2.6,DE CEN
|
||||
4.986,-0.522,2.6,ZE SGR
|
||||
2.705,0.346,2.6,GA1 LEO
|
||||
4.001,-0.164,2.6,BE LIB
|
||||
1.570,0.649,2.6,TH AUR
|
||||
4.213,-0.346,2.6,BE1 SCO
|
||||
0.500,0.363,2.6,BE ARI
|
||||
1.482,-0.595,2.6,AL COL
|
||||
3.292,-0.408,2.6,BE CRV
|
||||
4.120,0.112,2.6,AL SER
|
||||
0.374,1.051,2.7,DE CAS
|
||||
3.642,0.321,2.7,ET BOO
|
||||
3.921,-0.753,2.7,BE LUP
|
||||
1.296,0.579,2.7,JO AUR
|
||||
2.822,-0.863,2.7,MY VEL
|
||||
3.304,-1.207,2.7,AL MUS
|
||||
4.585,-0.651,2.7,YP SCO
|
||||
1.907,-0.647,2.7,PI PUP
|
||||
3.861,0.473,2.7,EP BOO
|
||||
4.804,-0.521,2.7,DE SGR
|
||||
5.176,0.185,2.7,GA AQL
|
||||
4.251,-0.064,2.7,DE OPH
|
||||
4.293,1.074,2.7,ET DRA
|
||||
3.493,-0.641,2.8,JO CEN
|
||||
3.887,-0.280,2.8,AL2 LIB
|
||||
2.805,-1.124,2.8,TH CAR
|
||||
1.464,-0.103,2.8,JO ORI
|
||||
4.321,0.375,2.8,BE HER
|
||||
4.640,0.080,2.8,BE OPH
|
||||
4.080,-0.718,2.8,GA LUP
|
||||
1.343,-0.089,2.8,BE ERI
|
||||
4.583,0.913,2.8,BE DRA
|
||||
0.112,-1.348,2.8,BE HYI
|
||||
3.208,-1.025,2.8,DE CRU
|
||||
2.127,-0.424,2.8,RH PUP
|
||||
4.369,0.552,2.8,ZE HER
|
||||
4.834,-0.444,2.8,LA SGR
|
||||
4.345,-0.492,2.8,TA SCO
|
||||
0.058,0.265,2.8,GA PEG
|
||||
3.413,0.191,2.8,EP VIR
|
||||
1.432,-0.362,2.8,BE LEP
|
||||
1.022,0.556,2.9,ZE PER
|
||||
4.168,-1.107,2.9,BE TRA
|
||||
4.561,-0.969,2.9,BE ARA
|
||||
0.518,-1.075,2.9,AL HYI
|
||||
5.840,-1.052,2.9,AL TUC
|
||||
0.993,0.421,2.9,ET TAU
|
||||
5.170,0.788,2.9,DE CYG
|
||||
5.703,-0.281,2.9,DE CAP
|
||||
1.671,0.393,2.9,MY GEM
|
||||
1.038,0.698,2.9,EP PER
|
||||
4.010,-1.199,2.9,GA TRA
|
||||
4.184,-0.456,2.9,PI SCO
|
||||
4.281,-0.447,2.9,SI SCO
|
||||
5.017,-0.367,2.9,PI SGR
|
||||
1.951,0.145,2.9,BE CMI
|
||||
3.386,0.669,2.9,AL2 CVN
|
||||
5.635,-0.097,2.9,BE AQR
|
||||
0.806,0.934,2.9,GA PER
|
||||
1.789,-0.883,2.9,TA PUP
|
||||
5.947,0.527,2.9,ET PEG
|
||||
1.039,-0.236,3.0,GA ERI
|
||||
3.272,-0.288,3.0,DE CRV
|
||||
4.590,-0.871,3.0,AL ARA
|
||||
2.562,-1.136,3.0,YP CAR
|
||||
5.785,-0.006,3.0,AL AQR
|
||||
1.762,0.439,3.0,EP GEM
|
||||
2.556,0.415,3.0,EP LEO
|
||||
1.318,0.765,3.0,EP AUR
|
||||
4.738,-0.531,3.0,GA2 SGR
|
||||
4.998,0.242,3.0,ZE AQL
|
||||
0.565,0.611,3.0,BE TRI
|
||||
1.473,0.369,3.0,ZE TAU
|
||||
3.186,-0.395,3.0,EP CRV
|
||||
3.486,-0.404,3.0,GA HYA
|
||||
0.973,0.834,3.0,DE PER
|
||||
2.922,0.777,3.0,PS UMA
|
||||
5.733,-0.652,3.0,GA GRU
|
||||
1.659,-0.525,3.0,ZE CMA
|
||||
1.846,-0.416,3.0,OK2 CMA
|
||||
3.805,0.669,3.0,GA BOO
|
||||
4.658,-0.700,3.0,JO1 SCO
|
||||
0.608,-0.052,3.0,OK CET
|
||||
3.620,-0.741,3.0,MY CEN
|
||||
2.715,0.724,3.0,MY UMA
|
||||
3.344,-1.189,3.0,BE MUS
|
||||
4.017,1.254,3.0,GA UMI
|
||||
5.029,1.181,3.1,DE DRA
|
||||
4.415,-0.664,3.1,MY1 SCO
|
||||
5.108,0.488,3.1,BE1 CYG
|
||||
5.328,-0.258,3.1,BE CAP
|
||||
2.336,0.104,3.1,ZE HYA
|
||||
2.835,-0.283,3.1,NY HYA
|
||||
4.789,-0.642,3.1,ET SGR
|
||||
5.400,-0.825,3.1,AL IND
|
||||
1.531,-0.624,3.1,BE COL
|
||||
2.448,0.600,3.1,AL LYN
|
||||
2.492,-0.995,3.1,_
|
||||
3.036,-1.100,3.1,LA CEN
|
||||
3.923,-0.735,3.1,KA CEN
|
||||
4.445,-0.977,3.1,ZE ARA
|
||||
2.353,0.838,3.1,JO UMA
|
||||
4.516,0.434,3.1,DE HER
|
||||
4.516,0.642,3.2,PI HER
|
||||
1.337,0.720,3.2,ET AUR
|
||||
1.736,-0.754,3.2,NY PUP
|
||||
2.500,0.902,3.2,TH UMA
|
||||
4.489,1.147,3.2,ZE DRA
|
||||
4.912,-0.471,3.2,PH SGR
|
||||
1.265,0.121,3.2,PI3 ORI
|
||||
1.333,-0.390,3.2,EP LEP
|
||||
3.851,-1.134,3.2,AL CIR
|
||||
4.440,0.164,3.2,KA OPH
|
||||
5.554,0.528,3.2,ZE CYG
|
||||
4.668,-0.647,3.2,_
|
||||
6.193,1.355,3.2,GA CEP
|
||||
4.020,-0.709,3.2,DE LUP
|
||||
5.285,-0.014,3.2,TH AQL
|
||||
5.623,1.232,3.2,BE CEP
|
||||
0.992,-1.296,3.2,GA HYI
|
||||
4.269,-0.082,3.2,EP OPH
|
||||
4.970,0.571,3.2,GA LYR
|
||||
1.960,-0.756,3.2,SI PUP
|
||||
4.805,-0.051,3.3,ET SER
|
||||
0.172,0.539,3.3,DE AND
|
||||
1.196,-0.961,3.3,AL DOR
|
||||
1.781,-1.081,3.3,AL PIC
|
||||
3.693,-0.466,3.3,PI HYA
|
||||
4.547,-0.436,3.3,TH OPH
|
||||
5.998,-0.276,3.3,DE AQR
|
||||
1.636,0.393,3.3,ET GEM
|
||||
3.945,-0.441,3.3,SI LIB
|
||||
4.036,1.029,3.3,JO DRA
|
||||
0.288,-0.815,3.3,BE PHE
|
||||
1.365,-0.283,3.3,MY LEP
|
||||
3.209,0.995,3.3,DE UMA
|
||||
2.678,-1.222,3.3,OM CAR
|
||||
2.758,-1.077,3.3,_
|
||||
5.004,-0.483,3.3,TA SGR
|
||||
4.504,-0.755,3.3,ET SCO
|
||||
2.048,-0.434,3.3,XI PUP
|
||||
2.942,0.269,3.3,TH LEO
|
||||
4.561,-0.984,3.3,GA ARA
|
||||
4.708,-0.171,3.3,NY OPH
|
||||
1.110,-1.090,3.4,AL RET
|
||||
5.807,1.016,3.4,ZE CEP
|
||||
1.416,-0.042,3.4,ET ORI
|
||||
1.768,0.225,3.4,XI GEM
|
||||
2.226,1.060,3.4,OK UMA
|
||||
5.085,0.054,3.4,DE AQL
|
||||
3.555,-0.010,3.4,ZE VIR
|
||||
4.026,-0.780,3.4,EP LUP
|
||||
0.499,1.111,3.4,EP CAS
|
||||
2.298,0.112,3.4,EP HYA
|
||||
3.384,0.059,3.4,DE VIR
|
||||
0.808,0.678,3.4,RH PER
|
||||
1.172,0.277,3.4,TH2 TAU
|
||||
2.693,-1.070,3.4,_
|
||||
5.940,0.189,3.4,ZE PEG
|
||||
0.386,-0.756,3.4,GA PHE
|
||||
0.493,0.516,3.4,AL TRI
|
||||
3.619,-0.728,3.4,NY CEN
|
||||
3.981,-0.909,3.4,ZE LUP
|
||||
4.189,-0.670,3.4,ET LUP
|
||||
0.778,-0.703,3.4,TH1 ERI
|
||||
4.653,0.484,3.4,MY HER
|
||||
5.432,-1.155,3.4,BE PAV
|
||||
5.434,1.079,3.4,ET CEP
|
||||
0.214,1.009,3.4,ET CAS
|
||||
2.404,-1.029,3.4,_
|
||||
2.691,0.409,3.4,ZE LEO
|
||||
5.001,-0.085,3.4,LA AQL
|
||||
0.299,-0.178,3.5,ET CET
|
||||
2.693,0.749,3.5,LA UMA
|
||||
4.931,0.582,3.5,BE LYR
|
||||
0.713,0.056,3.5,GA CET
|
||||
1.050,0.218,3.5,LA TAU
|
||||
1.840,-0.488,3.5,SI CMA
|
||||
2.080,-0.925,3.5,CH CAR
|
||||
3.995,0.581,3.5,DE BOO
|
||||
5.231,0.340,3.5,GA SGE
|
||||
2.960,0.578,3.5,NY UMA
|
||||
4.514,0.251,3.5,AL1 HER
|
||||
5.978,0.429,3.5,MY PEG
|
||||
5.971,-0.896,3.5,EP GRU
|
||||
0.454,-0.278,3.5,TA CET
|
||||
3.935,0.705,3.5,BE BOO
|
||||
4.830,-0.802,3.5,AL TEL
|
||||
4.964,-0.368,3.5,XI2 SGR
|
||||
2.166,0.160,3.5,BE CNC
|
||||
2.536,0.173,3.5,OK LEO
|
||||
2.650,0.293,3.5,ET LEO
|
||||
5.976,1.155,3.5,JO CEP
|
||||
1.172,0.335,3.5,EP TAU
|
||||
1.920,0.384,3.5,DE GEM
|
||||
4.143,-0.060,3.5,MY SER
|
||||
4.376,0.679,3.5,ET HER
|
||||
5.804,0.108,3.5,TH PEG
|
||||
0.974,-0.170,3.5,DE ERI
|
||||
2.604,-0.952,3.5,PH VEL
|
||||
3.024,-0.556,3.5,XI HYA
|
||||
4.615,-0.269,3.5,XI SER
|
||||
1.514,-0.259,3.5,ZE LEP
|
||||
3.750,-0.804,3.5,JO LUP
|
||||
0.085,-0.154,3.6,JO CET
|
||||
0.596,-0.899,3.6,PH ERI
|
||||
1.125,-0.590,3.6,YP4 ERI
|
||||
2.964,-0.258,3.6,DE CRT
|
||||
4.022,-0.633,3.6,PH1 LUP
|
||||
5.274,-1.155,3.6,DE PAV
|
||||
0.428,0.849,3.6,51 AND
|
||||
2.027,0.426,3.6,KA GEM
|
||||
4.417,-0.664,3.6,MY2 SCO
|
||||
4.804,1.269,3.6,CH DRA
|
||||
5.315,-0.219,3.6,AL2 CAP
|
||||
1.912,0.289,3.6,LA GEM
|
||||
3.804,0.530,3.6,RH BOO
|
||||
4.089,-0.491,3.6,YP LIB
|
||||
3.235,-1.054,3.6,EP CRU
|
||||
0.367,-0.143,3.6,TH CET
|
||||
0.894,0.158,3.6,OK TAU
|
||||
1.386,-0.119,3.6,TA ORI
|
||||
1.503,-0.392,3.6,GA LEP
|
||||
1.801,0.593,3.6,TH GEM
|
||||
2.372,0.823,3.6,KA UMA
|
||||
2.490,-0.706,3.6,PS VEL
|
||||
2.030,-0.663,3.6,_
|
||||
2.664,-0.216,3.6,LA HYA
|
||||
3.101,0.031,3.6,BE VIR
|
||||
0.399,0.268,3.6,ET PSC
|
||||
2.270,-0.924,3.6,OK VEL
|
||||
3.413,-1.249,3.6,DE MUS
|
||||
4.427,-0.739,3.6,ZE2 SCO
|
||||
4.586,-1.059,3.6,DE ARA
|
||||
4.650,-1.130,3.6,ET PAV
|
||||
6.030,0.739,3.6,OK AND
|
||||
0.742,0.476,3.6,41 ARI
|
||||
1.000,0.420,3.6,27 TAU
|
||||
5.400,0.255,3.6,BE DEL
|
||||
3.079,-1.165,3.6,LA MUS
|
||||
1.134,0.273,3.6,GA TAU
|
||||
3.323,-0.025,3.6,GA VIR
|
||||
3.684,1.124,3.6,AL DRA
|
||||
5.475,-1.020,3.6,BE IND
|
||||
0.161,0.941,3.7,ZE CAS
|
||||
1.462,0.173,3.7,LA ORI
|
||||
4.096,-0.520,3.7,TA LIB
|
||||
4.741,-0.874,3.7,TH ARA
|
||||
6.063,-0.370,3.7,88 AQR
|
||||
2.494,1.101,3.7,23 UMA
|
||||
4.129,0.269,3.7,BE SER
|
||||
2.285,-0.579,3.7,AL PYX
|
||||
3.323,-0.025,3.7,GA VIR
|
||||
4.048,0.508,3.7,BE CRB
|
||||
5.673,-0.291,3.7,GA CAP
|
||||
0.871,-0.380,3.7,TA4 ERI
|
||||
1.271,0.098,3.7,PI4 ORI
|
||||
2.554,-1.091,3.7,_
|
||||
6.096,0.057,3.7,GA PSC
|
||||
0.506,-0.901,3.7,CH ERI
|
||||
0.981,0.421,3.7,17 TAU
|
||||
4.703,0.510,3.7,XI HER
|
||||
1.555,-0.247,3.7,ET LEP
|
||||
3.081,0.834,3.7,CH UMA
|
||||
4.149,0.078,3.7,EP SER
|
||||
5.216,0.112,3.7,BE AQL
|
||||
1.284,0.043,3.7,PI5 ORI
|
||||
1.569,0.947,3.7,DE AUR
|
||||
3.867,0.033,3.7,109 VIR
|
||||
5.519,0.767,3.7,XI CYG
|
||||
5.562,0.664,3.7,TA CYG
|
||||
0.486,-0.180,3.7,ZE CET
|
||||
0.929,-0.165,3.7,EP ERI
|
||||
2.060,-0.708,3.7,_
|
||||
4.744,0.167,3.7,72 OPH
|
||||
0.904,0.170,3.7,XI TAU
|
||||
5.614,-0.391,3.7,ZE CAP
|
||||
5.989,-0.132,3.7,LA AQR
|
||||
1.320,0.717,3.8,ZE AUR
|
||||
2.374,-0.822,3.8,_
|
||||
4.284,0.334,3.8,GA HER
|
||||
4.660,0.047,3.8,GA OPH
|
||||
4.684,0.993,3.8,XI DRA
|
||||
5.887,1.020,3.8,DE CEP
|
||||
0.745,0.976,3.8,ET PER
|
||||
1.147,0.306,3.8,DE1 TAU
|
||||
1.456,-1.091,3.8,BE DOR
|
||||
4.406,-1.030,3.8,ET ARA
|
||||
5.679,-1.351,3.8,NY OCT
|
||||
5.790,0.442,3.8,JO PEG
|
||||
0.983,0.743,3.8,NY PER
|
||||
2.207,-1.154,3.8,BE VOL
|
||||
4.995,-0.379,3.8,OK SGR
|
||||
5.049,0.931,3.8,KA CYG
|
||||
5.409,0.278,3.8,AL DEL
|
||||
5.444,-0.166,3.8,EP AQR
|
||||
5.896,0.878,3.8,AL LAC
|
||||
1.871,-1.230,3.8,GA2 VOL
|
||||
2.851,-1.027,3.8,_
|
||||
1.851,0.359,3.8,ZE GEM
|
||||
1.945,0.485,3.8,JO GEM
|
||||
5.104,0.903,3.8,JO2 CYG
|
||||
5.295,0.816,3.8,31 CYG
|
||||
0.827,0.783,3.8,KA PER
|
||||
2.579,1.030,3.8,YP UMA
|
||||
2.705,0.346,3.8,GA2 LEO
|
||||
4.079,0.184,3.8,DE SER
|
||||
4.079,0.184,3.8,DE SER
|
||||
4.623,0.803,3.8,JO HER
|
||||
1.478,-0.045,3.8,SI ORI
|
||||
1.533,-0.364,3.8,DE LEP
|
||||
2.732,-0.294,3.8,MY HYA
|
||||
1.202,-0.533,3.8,YP2 ERI
|
||||
2.438,0.642,3.8,38 LYN
|
||||
2.740,-1.025,3.8,_
|
||||
4.324,0.035,3.8,LA OPH
|
||||
5.181,0.323,3.8,DE SGE
|
||||
6.185,0.811,3.8,LA AND
|
||||
0.979,0.564,3.8,OK PER
|
||||
2.851,0.597,3.8,46 LMI
|
||||
3.658,-0.735,3.8,PH CEN
|
||||
3.874,-1.380,3.8,AL APS
|
||||
4.745,0.502,3.8,OK HER
|
||||
5.184,1.226,3.8,EP DRA
|
||||
1.172,0.279,3.8,TH1 TAU
|
||||
2.272,-0.814,3.8,_
|
||||
2.335,-1.058,3.8,_
|
||||
2.781,-0.842,3.8,_
|
||||
3.017,1.210,3.8,LA DRA
|
||||
4.113,0.459,3.8,GA CRB
|
||||
4.816,0.380,3.8,109 HER
|
||||
5.854,-0.024,3.8,GA AQR
|
||||
0.978,-1.131,3.8,BE RET
|
||||
1.515,-0.891,3.8,BE PIC
|
||||
1.667,-0.584,3.8,DE COL
|
||||
1.897,-0.467,3.8,OM CMA
|
||||
2.682,-0.735,3.8,_
|
||||
2.761,0.162,3.8,RH LEO
|
||||
4.173,0.273,3.8,GA SER
|
||||
4.256,-1.112,3.8,DE TRA
|
||||
4.866,-0.144,3.8,AL SCT
|
||||
1.108,-0.738,3.9,AL HOR
|
||||
3.306,-0.847,3.9,TA CEN
|
||||
4.696,0.650,3.9,TH HER
|
||||
4.772,-0.368,3.9,MY SGR
|
||||
0.248,0.672,3.9,MY AND
|
||||
0.838,-0.506,3.9,AL FOR
|
||||
0.985,0.425,3.9,20 TAU
|
||||
1.214,-0.250,3.9,53 ERI
|
||||
1.445,-0.619,3.9,EP COL
|
||||
1.807,-0.422,3.9,OK1 CMA
|
||||
3.283,-1.259,3.9,GA MUS
|
||||
3.288,1.218,3.9,KA DRA
|
||||
3.659,-0.782,3.9,YP1 CEN
|
||||
3.979,-0.851,3.9,KA1 LUP
|
||||
0.041,-0.798,3.9,EP PHE
|
||||
2.419,0.040,3.9,TH HYA
|
||||
2.586,0.454,3.9,MY LEO
|
||||
3.539,-0.688,3.9,_
|
||||
3.853,-0.099,3.9,MY VIR
|
||||
4.175,-0.510,3.9,RH SCO
|
||||
0.770,-0.155,3.9,ET ERI
|
||||
2.971,-0.951,3.9,PI CEN
|
||||
3.228,-0.012,3.9,ET VIR
|
||||
4.275,0.808,3.9,TA HER
|
||||
4.335,-1.377,3.9,GA APS
|
||||
5.220,0.612,3.9,ET CYG
|
||||
2.206,-0.068,3.9,_
|
||||
5.203,0.018,3.9,ET AQL
|
||||
6.067,-0.790,3.9,JO GRU
|
||||
1.061,0.105,3.9,NY TAU
|
||||
2.295,-0.804,3.9,_
|
||||
2.530,-0.020,3.9,JO HYA
|
||||
2.917,-1.029,3.9,_
|
||||
3.264,-0.877,3.9,SI CEN
|
||||
4.082,-0.258,3.9,GA LIB
|
||||
0.298,-0.964,3.9,ZE PHE
|
||||
4.452,0.540,3.9,EP HER
|
||||
5.567,0.092,3.9,AL EQU
|
||||
1.206,-0.059,3.9,NY ERI
|
||||
2.013,-0.167,3.9,AL MON
|
||||
5.069,-0.311,3.9,RH1 SGR
|
||||
0.114,-0.762,3.9,KA PHE
|
||||
2.289,0.317,3.9,DE CNC
|
||||
2.984,0.184,3.9,JO LEO
|
||||
5.485,0.719,3.9,NY CYG
|
||||
0.398,-0.856,4.0,DE PHE
|
||||
0.760,0.921,4.0,TA PER
|
||||
1.731,-0.336,4.0,NY2 CMA
|
||||
2.015,-1.267,4.0,ZE VOL
|
||||
3.508,0.959,4.0,ZE UMA
|
||||
4.149,-0.587,4.0,CH LUP
|
||||
5.963,0.411,4.0,LA PEG
|
||||
1.152,-0.594,4.0,43 ERI
|
||||
1.567,-0.747,4.0,ET COL
|
||||
1.788,-0.567,4.0,KA CMA
|
||||
2.024,-0.505,4.0,3 PUP
|
||||
3.192,-0.914,4.0,RH CEN
|
||||
4.218,-0.361,4.0,OM1 SCO
|
||||
5.239,-1.273,4.0,EP PAV
|
||||
1.534,0.683,4.0,NY AUR
|
|
|
@ -0,0 +1,21 @@
|
|||
1.394,-0.230,4.3,LA LEP
|
||||
1.367,-0.226,4.4,KA LEP
|
||||
0.825,0.866,4.0,JO PER
|
||||
4.950,0.644,4.3,DE2 LYR
|
||||
5.046,0.666,4.4,TH LYR
|
||||
4.071,0.547,4.1,TH CRB
|
||||
4.143,0.455,4.6,DE CRB
|
||||
4.178,0.469,4.2,EP CRB
|
||||
4.195,0.521,5.0,JO CRB
|
||||
4.585,0.456,4.4,LA HER
|
||||
4.591,1.511,4.4,DE UMI
|
||||
4.265,1.322,5.0,ET UMI
|
||||
4.119,1.358,4.3,ZE UMI
|
||||
4.389,1.432,4.2,EP UMI
|
||||
4.591,0.963,4.9,NY2 DRA
|
||||
5.042,1.280,4.5,TA DRA
|
||||
4.197,1.022,4.0,TH DRA
|
||||
1.816,-0.298,4.4,JO CMA
|
||||
1.849,-0.273,4.1,GA CMA
|
||||
1.807,-0.210,4.1,TH CMA
|
||||
1.724,-0.401,4.5,XI2 CMA
|
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,31 @@
|
|||
// make sure to enclose the function in parentheses
|
||||
(function(back) {
|
||||
let settings = require('Storage').readJSON('planetarium.json',1)||{"starnames":false,"constellations":true,"consnames":false};
|
||||
function save(key, value) {
|
||||
settings[key] = value;
|
||||
require('Storage').write('planetarium.json',settings);
|
||||
}
|
||||
const appMenu = {
|
||||
'': {'title': 'Planetarium Settings'},
|
||||
'< Back': back,
|
||||
'Star names': {
|
||||
value: !!settings.starnames,
|
||||
format: v =>v?'On':'Off',
|
||||
onchange: v => {
|
||||
save('starnames',v);
|
||||
}},
|
||||
'Constellations': {
|
||||
value: !!settings.constellations,
|
||||
format: v =>v?'On':'Off',
|
||||
onchange: v => {
|
||||
save('constellations',v);
|
||||
}},
|
||||
'Const. names': {
|
||||
value: !!settings.consnames,
|
||||
format: v =>v?'On':'Off',
|
||||
onchange: v => {
|
||||
save('consnames',v);
|
||||
}},
|
||||
};
|
||||
E.showMenu(appMenu)
|
||||
})
|
|
@ -0,0 +1,38 @@
|
|||
'''
|
||||
* This information is from the Yale Bright Star Catalog. First number is the RA (Right ascension) in radians. Careful because in all
|
||||
* the catalogs this is in Hour angle. We have to convert it to degrees and then to radians.
|
||||
* The second number is the DE (declination) in radians. In this case in the catalogs is in degrees, just convert to radians.
|
||||
* Third number is the aparent magnitude
|
||||
'''
|
||||
|
||||
import csv
|
||||
import math
|
||||
|
||||
with open('starsoriginal.csv') as csv_file:
|
||||
csv_reader = csv.reader(csv_file, delimiter=',')
|
||||
for row in csv_reader:
|
||||
data_read = [row for row in csv_reader]
|
||||
|
||||
stars=[]
|
||||
for row in data_read:
|
||||
hours = float(row[0])
|
||||
min = float(row[1])
|
||||
seg = float(row[2])
|
||||
rahours = hours+(min+seg/60)/60
|
||||
radegress = rahours*360/24
|
||||
radradians = math.radians(radegress)
|
||||
deg = float(row[3])
|
||||
dem = float(row[4])
|
||||
des = float(row[5])
|
||||
if (deg<0):
|
||||
desex = deg-(dem+des/60)/60
|
||||
else:
|
||||
desex = deg+(dem+des/60)/60
|
||||
derad = math.radians(desex)
|
||||
|
||||
stars.append(['{:.3f}'.format(radradians),'{:.3f}'.format(derad),'{:.1f}'.format(float(row[6])),row[7].strip()])
|
||||
|
||||
with open("planetarium.stars.csv", "wt") as fp:
|
||||
writer = csv.writer(fp, delimiter=",")
|
||||
# writer.writerow(["your", "header", "foo"]) # write header
|
||||
writer.writerows(stars)
|
|
@ -1,3 +1,4 @@
|
|||
0.01: First published version of app
|
||||
0.02: Added support for locale and 12H clock
|
||||
0.03: Added HR indication to clock
|
||||
0.04: Update font size and alignment
|
|
@ -23,31 +23,29 @@
|
|||
// Ssettings
|
||||
const settings = {
|
||||
time: {
|
||||
color: '#f0af00',
|
||||
shadow: '#CF7500',
|
||||
color: 0xD6ED17,
|
||||
font: 'Vector',
|
||||
size: 60,
|
||||
middle: screen.middle - 30,
|
||||
middle: screen.middle,
|
||||
center: screen.center,
|
||||
},
|
||||
date: {
|
||||
color: '#f0af00',
|
||||
shadow: '#CF7500',
|
||||
color: 0xD6ED17,
|
||||
font: 'Vector',
|
||||
size: 15,
|
||||
middle: screen.height - 20, // at bottom of screen
|
||||
middle: screen.height-17, // at bottom of screen
|
||||
center: screen.center,
|
||||
},
|
||||
circle: {
|
||||
colormin: '#eeeeee',
|
||||
colorsec: '#bbbbbb',
|
||||
colormin: 0x606060,
|
||||
colorsec: 0x656565,
|
||||
width: 10,
|
||||
middle: screen.middle,
|
||||
center: screen.center,
|
||||
height: screen.height
|
||||
},
|
||||
hr: {
|
||||
color: '#333333',
|
||||
color: 0x333333,
|
||||
size: 10,
|
||||
x: screen.center,
|
||||
y: screen.middle + 45
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
0.05: Add setting to turn vibrate on/off.
|
||||
0.06: Tweaks to vibration settings.
|
||||
0.07: Switch to BTN1 for Max toggle and reset function.
|
||||
1.00 : New features. Added waypoints file and distance to selected waypoint display. Added integration with Low Power GPS service. Save display settings and restore when app restarted.
|
||||
1.00: New features. Added waypoints file and distance to selected waypoint display. Added integration with GPS Setup module to switch GPS to low power mode when screen off. Save display settings and restore when app restarted.
|
|
@ -1,66 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name":"NONE"
|
||||
},
|
||||
{
|
||||
"name":"Omori",
|
||||
"lat":-38.9058670,
|
||||
"lon":175.7613350
|
||||
},
|
||||
{
|
||||
"name":"DeltaW",
|
||||
"lat":-38.9438550,
|
||||
"lon":175.7676930
|
||||
},
|
||||
{
|
||||
"name":"DeltaE",
|
||||
"lat":-38.9395240,
|
||||
"lon":175.7814420
|
||||
},
|
||||
{
|
||||
"name":"BtClub",
|
||||
"lat":-38.9446020,
|
||||
"lon":175.8475720
|
||||
},
|
||||
{
|
||||
"name":"Hapua",
|
||||
"lat":-38.8177750,
|
||||
"lon":175.8088720
|
||||
},
|
||||
{
|
||||
"name":"MotuTa",
|
||||
"lat":-38.85454,
|
||||
"lon":175.94199
|
||||
},
|
||||
{
|
||||
"name":"Nook",
|
||||
"lat":-38.7848090,
|
||||
"lon":175.7839440
|
||||
},
|
||||
{
|
||||
"name":"ChryBy",
|
||||
"lat":-38.7975050,
|
||||
"lon":175.7551960
|
||||
},
|
||||
{
|
||||
"name":"Waiha",
|
||||
"lat":-38.7219630,
|
||||
"lon":175.7481520
|
||||
},
|
||||
{
|
||||
"name":"KwaKwa",
|
||||
"lat":-38.6632310,
|
||||
"lon":175.8670320
|
||||
},
|
||||
{
|
||||
"name":"Hatepe",
|
||||
"lat":-38.8547420,
|
||||
"lon":176.0089124
|
||||
},
|
||||
{
|
||||
"name":"Kinloc",
|
||||
"lat":-38.6614442,
|
||||
"lon":175.9161607
|
||||
}
|
||||
|
||||
]
|
|
@ -0,0 +1,2 @@
|
|||
0.01: Initial version
|
||||
0.02: Fixed issues with entry in apps.json
|
|
@ -0,0 +1,17 @@
|
|||
# The Tape App Launcher
|
||||
|
||||
Reminiscent of a Telegram or Turing machine tape.
|
||||
|
||||

|
||||
|
||||
## Controls
|
||||
|
||||
**BTN1** - move backward to the previous app icon
|
||||
|
||||
**BTN2** - run the selected app
|
||||
|
||||
**BTN3** - move forward to the next app icon
|
||||
|
||||
**Swipe Left** - move forward to the next app icon
|
||||
|
||||
**Swipe Right** - move backwards (to the left) to the previous app
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Tape Launcher
|
||||
*
|
||||
*/
|
||||
|
||||
var s = require("Storage");
|
||||
var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type));
|
||||
apps.sort((a,b)=>{
|
||||
var n=(0|a.sortorder)-(0|b.sortorder);
|
||||
if (n) return n; // do sortorder first
|
||||
if (a.name<b.name) return -1;
|
||||
if (a.name>b.name) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
var Napps = apps.length;
|
||||
var selected = 1; // assumes we have at least 2 apps
|
||||
|
||||
function draw_icon(pos, id, select) {
|
||||
var x = ((pos % 3)*80) + 2;
|
||||
var y = 80;
|
||||
|
||||
g.setColor(-1);
|
||||
g.drawImage(s.read(apps[id].icon),x+2,y+11,{scale:1.625});
|
||||
|
||||
if (select) {
|
||||
g.setColor(1,1,1).drawRect(x,y,x+79,y+99); // white bounding box
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
g.setColor(0,0,0).fillRect(0,0,239,239);
|
||||
|
||||
if (selected -1 > -1)
|
||||
draw_icon(0, selected -1, false);
|
||||
|
||||
draw_icon(1, selected, true);
|
||||
|
||||
if (selected + 1 < Napps)
|
||||
draw_icon(2, selected + 1, false);
|
||||
|
||||
g.setColor(-1).setFontAlign(0,-1,0).setFont("6x8",3);
|
||||
|
||||
if (apps[selected].name.length <= 12) {
|
||||
g.drawString(apps[selected].name, 120, 40, true);
|
||||
} else {
|
||||
// some app names are too long for one line
|
||||
var name = apps[selected].name;
|
||||
var first = name.substring(0, name.indexOf(" "));
|
||||
var last = name.substring(name.indexOf(" ") + 1, name.length);
|
||||
g.drawString(first, 120, 40, true);
|
||||
g.drawString(last, 120, 200, true);
|
||||
}
|
||||
}
|
||||
|
||||
Bangle.on("swipe",(dir)=>{
|
||||
(dir<0) ? nextapp(1) : nextapp(-1);
|
||||
});
|
||||
|
||||
function nextapp(dir){
|
||||
selected += dir;
|
||||
|
||||
if (selected > Napps - 1) {
|
||||
selected = Napps - 1;
|
||||
} else if (selected < 0) {
|
||||
selected = 0;
|
||||
}
|
||||
draw();
|
||||
}
|
||||
|
||||
function doselect(){
|
||||
load(apps[selected].src);
|
||||
}
|
||||
|
||||
setWatch(nextapp.bind(null,-1), BTN1, {repeat:true,edge:"falling"});
|
||||
setWatch(doselect, BTN2, {repeat:true,edge:"falling"});
|
||||
setWatch(nextapp.bind(null,1), BTN3, {repeat:true,edge:"falling"});
|
||||
|
||||
draw();
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("AH4A/ACXd7vQC6vUpoBBDaQXEDaQXIDZwXMAIQZHC4R6BAAIZJDAwXIDY4XHAAodJ7oXMDpQXSAAiRHhoWN7zFLDY/e9ve9zeMhvQCIIBFC5ARIC5oVNC5EOCpwABC4vuCZYXPCIwXOCJAAFC5gAJ8AXFCpwuHgDjCFqQXC6lN6gbFf5gXEAInd6AXVDYndhoXKBoIbMC5QZLC44AFDpIXNDpQXdhoYMAAbwIC6oZQbxhOKC5gbKC6BUGC6oA/AHgA=="))
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 98 KiB |
|
@ -0,0 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Tweaks for app loader
|
|
@ -0,0 +1,40 @@
|
|||
# Test User Input
|
||||
|
||||
This very basic app, allows to *test the bangle.js input interface*, and displays the result in text or a switch on/off image.
|
||||
|
||||
|
||||
Launcher icon
|
||||

|
||||
1st screen - Help/Intro
|
||||

|
||||
2nd screen - interface and a result
|
||||

|
||||
3rd screen - interface and a result
|
||||

|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Open and see a "help" screen
|
||||
Interact with buttons or touch screen to print the event or leave the app
|
||||
|
||||
## Features
|
||||
|
||||
Colours, font, user input, image, load widgets
|
||||
|
||||
|
||||
## Controls
|
||||
Press left area - Prints Touch1
|
||||
Press righ area - Prints Touch2
|
||||
Press center area - Prints Touch3
|
||||
Swipe Left - Displays Switch OFF image
|
||||
Swipe Right - Displays Switch ON image
|
||||
BTN1 - Prints Button1
|
||||
BTN2 - Prints Button2
|
||||
BTN3 - Quit to Launcher
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
This app is so basic that probably the easiest is to just edit the code
|
||||
Otherwise you can contact me [here](https://github.com/dapgo)
|
|
@ -0,0 +1 @@
|
|||
E.toArrayBuffer(atob("MDDCAP//Bv7m/RF8AAAAAAAAAAAAAAAAAAAAAP/AAAAAAAAAAAAAD//8AAAAAAAAAAAAP///AAAAAAAAAAAA////wAAAAAAAAAAA////wAAAAAAAAAAD/9X/8AAAAAAAAAAD/1V/8AAAAAAAAAAD/1V/8AAAAAAAAAAD/1V/8AAAAAAAAAAD/1V/8AAAAAAAAAAA/1V/wAAAAAAAAAAA/1V/wAAAAAAAAAAAP1V/AAAAAAAAAAAAD1V8AAAAAAAAAAAAAFVAAAAAAAAAAAAAAFVAAAAAAAAAAAAAAFVAAAAAAAAAAAAAAFVAAAAAAAAAAAAAAFVlQAAAAAAAAAAAAFVlVVQAAAAAAAAAAFVVVVVUAAAAAAAAAFVVVVVVQAAAAAAAAFVVVVVVQAAAAFYAAFVVVVVVUAAAAFWAAFVVVVVVUAAAAFVgAFVVVVVVUAAAAFVaAlVVVVVVUAAAABVWqlVVVVVVUAAAAAVVqlVVVVVVUAAAAAFValVVVVVVYAAAAABVWlVVVVVVoAAAAAAVVlVVVVVWoAAAAAAFVVVVVVVaoAAAAAAFVVVVVVVqoAAAAAABVVVVVVWqoAAAAAAAVVVVVVqqoAAAAAAAFVVVVWqqoAAAAAAABVVVVaqqoAAAAAAAAVVVVqqqgAAAAAAAAFVVWqqqgAAAAAAAABVVaqqqAAAAAAAAAAFVqqqgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
|
@ -0,0 +1,135 @@
|
|||
/* Test bangle.js input interface */
|
||||
var colbackg='#111111';
|
||||
//var coldarkred='#CC3333';
|
||||
var colorange='#e56e06';
|
||||
var colgrey='#f3f3f1'; //'#51504f'; //lighter gray
|
||||
var v_font1size='16';
|
||||
var v_clicks='0';
|
||||
console.log("*** Test input interface ***");
|
||||
|
||||
function ClearActiveArea(){
|
||||
g.setColor(colbackg);
|
||||
g.fillRect(0,32,239,239); //fill all screen except widget area
|
||||
g.flip();
|
||||
}
|
||||
function ClearBannerArea(){
|
||||
g.setColor(colgrey);
|
||||
g.fillRect(50,32,190,85); //fill an specific area
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function PrintUserInput(boton){
|
||||
console.log("Pressed touch/BTN",boton);
|
||||
if (v_clicks=='0') PrintAreas();
|
||||
ClearBannerArea();
|
||||
|
||||
if (boton==' <---') {
|
||||
var img_off = {
|
||||
width : 48, height : 48, bpp : 2,
|
||||
transparent : 0,
|
||||
palette : new Uint16Array([65535,63968,40283,50781]),
|
||||
buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAAAA///9VVVVVVVQAAAD/qq/1VVVVVVVAAAP6qqv9VVVVVVVUAA/qqqv/VVVVVVVVAD+qqq//1VVVVVVVQP6qqq//1VVVVVVVQPqqqr//9VVVVVVVUvqqqr//9VVVVVVVU+qqqv/+uVVVVVVVV+qqqv+quVVVVVVVV+qqq+qqvVVVVVVVV+qqvqqqvVVVVVVVV+qv+qqquVVVVVVVV+r/+qqquVVVVVVVVv//6qqq9VVVVVVVUP//6qqq9VVVVVVVUP//qqqr1VVVVVVVQD//qqqv1VVVVVVVQA/+qqq/VVVVVVVVAAP+qqr9VVVVVVVUAAD/qq/1VVVVVVVAAAA///9VVVVVVVQAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
||||
};
|
||||
g.drawImage(img_off,90,35);
|
||||
}
|
||||
else if (boton==' --->') {
|
||||
var img_on = {
|
||||
width : 48, height : 48, bpp : 2,
|
||||
transparent : 0,
|
||||
palette : new Uint16Array([65535,36361,27879,40283]),
|
||||
buffer : E.toArrayBuffer(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAABVVVVVqqf///AAAAVVVVVWqn////wAAFVVVVVWqf////8AAVVVVVVap//////ABVVVVVVqr//////wBVVVVVVqn//////8FVVVVVVqv//////8FVVVVVWqf///////VVVVVVWq////////VVVVVVWq////////VVVVVVWq////////VVVVVVWq////////VVVVVVWq////////VVVVVVWq////////FVVVVVWqf///////FVVVVVVqv//////8BVVVVVVqn//////8BVVVVVVar//////wAVVVVVVap//////AAFVVVVVWqf////8AAAVVVVVWqn////wAAABVVVVVqqf///AAAAAAAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
||||
};
|
||||
g.drawImage(img_on,90,35);
|
||||
}
|
||||
else
|
||||
{ //no swipe /slide
|
||||
g.setColor(colorange);
|
||||
g.setFontVector(32).drawString(boton, 60, 65);
|
||||
}
|
||||
g.flip();
|
||||
v_clicks++;
|
||||
}
|
||||
function PrintBtn1(boton){
|
||||
console.log("Pressed BTN1");
|
||||
if (v_clicks=='0') PrintAreas();
|
||||
PrintUserInput("Button1");
|
||||
v_clicks++;
|
||||
}
|
||||
|
||||
function PrintBtn2(boton){
|
||||
console.log("Pressed BTN2");
|
||||
if (v_clicks=='0') PrintAreas();
|
||||
PrintUserInput("Button2");
|
||||
v_clicks++;
|
||||
}
|
||||
|
||||
function PrintHelp(){
|
||||
console.log("********************************");
|
||||
console.log("Log: *** Print help in screen");
|
||||
ClearActiveArea();
|
||||
g.setColor(0,1,0); //green
|
||||
g.setFontVector(v_font1size).drawString("To test the input, try :", 30, 90);
|
||||
g.setFontVector(v_font1size).drawString("Swipe right -->", 30, 115);
|
||||
g.setFontVector(v_font1size).drawString("Swipe left <--", 30, 130);
|
||||
g.setFontVector(v_font1size).drawString("Click Left area", 30, 145);
|
||||
g.setFontVector(v_font1size).drawString("Click Right area", 30,160);
|
||||
g.setFontVector(v_font1size).drawString("Click Middle area", 30,175);
|
||||
g.setFontVector(v_font1size).drawString("Press Button1 ", 30,190);
|
||||
g.setFontVector(v_font1size).drawString("Press Button2 ", 30,205);
|
||||
g.setFontVector(v_font1size).drawString("Press Button3 to Quit", 30,220);
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function PrintAreas(){
|
||||
console.log("********************************");
|
||||
console.log("Log: *** Print Areas in screen");
|
||||
ClearActiveArea();
|
||||
g.setColor(0,1,0); //green
|
||||
g.drawLine(1, 140, 1, 200);//side border
|
||||
g.drawLine(239, 140, 239, 200);//side border
|
||||
g.drawLine(120, 140, 120, 200);//middle of areas
|
||||
g.setFontVector(v_font1size).drawString("BTN1", 195,45);
|
||||
g.setFontVector(v_font1size).drawString("BTN2", 195,125);
|
||||
g.setFontVector(v_font1size).drawString("Quit<--", 130,225);
|
||||
g.setFontVector(v_font1size).drawString("BTN3", 195,225);
|
||||
g.setFontVector(v_font1size).drawString("Middle area", 80,120);
|
||||
g.setFontVector(v_font1size).drawString("Left area", 15, 165);
|
||||
g.setFontVector(v_font1size).drawString("Right area", 140,165);
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function UserInput(){
|
||||
Bangle.on('touch', function(button){
|
||||
switch(button){
|
||||
case 1:
|
||||
PrintUserInput("Touch 1");//left
|
||||
break;
|
||||
case 2:
|
||||
PrintUserInput("Touch 2");//right
|
||||
break;
|
||||
case 3:
|
||||
PrintUserInput("Touch 3");//center 1+2
|
||||
break;
|
||||
}
|
||||
});
|
||||
//only the name of the function
|
||||
setWatch(PrintBtn1, BTN1, { repeat: true });
|
||||
setWatch(PrintBtn2, BTN2, { repeat: true });
|
||||
setWatch(Bangle.showLauncher, BTN3, { repeat: true });
|
||||
Bangle.on('swipe', dir => {
|
||||
if(dir == 1) PrintUserInput(" --->");
|
||||
else PrintUserInput(" <---");
|
||||
});
|
||||
console.log("Log: Input conditions loaded");
|
||||
} //end of UserInput
|
||||
|
||||
//Main code
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
//optional line below widgets area
|
||||
g.setColor(0,1,0); //green
|
||||
g.drawLine(60, 30, 180, 30);
|
||||
g.flip();
|
||||
//end optional
|
||||
PrintHelp();
|
||||
UserInput();
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 85 KiB |
|
@ -0,0 +1,63 @@
|
|||
# Walkers Clock
|
||||
|
||||
A larg font watch, displays steps, can switch GPS on/off, displays grid reference
|
||||
|
||||
The watch works well with GPSsetup, the Activepedom or Widpedom
|
||||
wdigets. A tiny GPS power widget is waiting in the wings for when
|
||||
the v2.09 firware is released.
|
||||
|
||||
## Features
|
||||
|
||||
- Displays the time in large font
|
||||
- Uses BTN1 to select modeline display (eg battery status or switch between setting when in a function mode
|
||||
- Uses BTN3 to select the function mode (eg turn on/off GPS, or change GPS display)
|
||||
- two function menus at present
|
||||
GPS Power = On/Off
|
||||
GPS Display = Grid | Speed Alt
|
||||
when the modeline in CYAN use button BTN1 to switch between options
|
||||
- Display the current steps if one of the steps widgets is installed
|
||||
- Ensures that BTN2 requires a 1.5 second press in order to switch to the launcher
|
||||
this is so you dont accidently switch out of the GPS/watch display with you coat sleeve
|
||||
- Displays the timestamp of the last GPS fix when the GPS is on
|
||||
- Buzzes when the GPS aquires a positional satellite fix
|
||||
- Displays the current OS map grid reference in a large font
|
||||
- Displays the age of the current GPS position fix in seconds
|
||||
- Works in tandem with the GPS setup app so that you can reduce the power consumption of the GPS
|
||||
|
||||
## BTN1 cycles the information line
|
||||
|
||||
- By default the modeline is switched off
|
||||
- Click BTN1 once and display your steps (if one of the step widgets is installed)
|
||||
- Click BTN1 again and it will show battery % charge
|
||||
- Click BTN1 again and it will switch the modeline off
|
||||
|
||||
## BTN2 Long press to start the launcher
|
||||
|
||||
BTN2 is confiured to respond to a 1.5 second press in order to switch
|
||||
to the launcher App. Simply press and hold until you hear a buzz and
|
||||
release. This avoids accidently switching out of the watch app when
|
||||
clothing catches it.
|
||||
|
||||
## BTN3 cycles the function mode
|
||||
|
||||
- Click BTN3 once and the GPS ON / OFF menu is displayed
|
||||
- If the GPS is OFF then pressing BTN1 will turn it ON
|
||||
- If the GPS is ON then Clicking BTN1 will turn it OFF
|
||||
|
||||
When the GPS is ON a second function menu can be displayed by
|
||||
pressing BTN3 again. This will show options to change the GPS display
|
||||
on the second line of the watch.
|
||||
|
||||
- Grid - will display the GPS position converted to an OS Grid Ref
|
||||
- Speed - will display the GPS speed inforation supplied in the last GPS fix
|
||||
- Alt - will display the altitude information
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Future Enhancements
|
||||
* Ability to turn on the Heart Rate monitor
|
||||
* Maybe a simple stopwatch capability
|
||||
* Fix the screen flicker
|
||||
|
|
@ -0,0 +1,522 @@
|
|||
/*
|
||||
* Walkers clock, hugh barney AT googlemail DOT com
|
||||
*
|
||||
* A clock that has the following features
|
||||
* - displays the time in large font
|
||||
* - uses BTN1 to select modeline display (eg battery status or switch between setting when in a function mode
|
||||
* - uses BTN3 to select the function mode (eg turn on/off GPS, or change GPS display)
|
||||
* - two function menus at present
|
||||
* GPS Power = On/Off
|
||||
* GPS Display = Grid | Speed Alt
|
||||
* when the modeline in CYAN use button BTN1 to switch between options
|
||||
* - display the current steps if one of the steps widgets is installed
|
||||
* - ensures that BTN2 requires a 1.5 second press in order to switch to the launcher
|
||||
* this is so you dont accidently switch out of the GPS/watch display with you coat sleeve
|
||||
* - displays the timestamp of the last GPS fix when the GPS is on
|
||||
* - buzzes when the GPS aquires a positional satellite fix
|
||||
* - displays the current OS map grid reference in a large font
|
||||
* - displays the age of the current GPS position fix in seconds
|
||||
* - works in tandem with the GPS setup app so that you can reduce the power consumption of the GPS
|
||||
*
|
||||
*/
|
||||
|
||||
const INFO_NONE = "none";
|
||||
const INFO_BATT = "batt";
|
||||
const INFO_STEPS = "step";
|
||||
|
||||
const FN_MODE_OFF = "fn_mode_off";
|
||||
const FN_MODE_GPS = "fn_mode_gps";
|
||||
const FN_MODE_GDISP = "fn_mode_gdisp";
|
||||
|
||||
const GPS_OFF = "gps_off";
|
||||
const GPS_TIME = "gps_time";
|
||||
const GPS_SATS = "gps_sats";
|
||||
const GPS_RUNNING = "gps_running";
|
||||
|
||||
const GDISP_OS = "g_osref";
|
||||
const GDISP_SPEED = "g_speed";
|
||||
const GDISP_ALT = "g_alt";
|
||||
|
||||
const Y_TIME = 40;
|
||||
const Y_ACTIVITY = 120;
|
||||
const Y_MODELINE = 200;
|
||||
|
||||
let gpsState = GPS_OFF;
|
||||
let gpsPowerState = false;
|
||||
let infoMode = INFO_NONE;
|
||||
let functionMode = FN_MODE_OFF;
|
||||
let gpsDisplay = GDISP_OS;
|
||||
|
||||
let last_steps = undefined;
|
||||
let firstPress = 0;
|
||||
|
||||
let last_fix = {
|
||||
fix: 0,
|
||||
alt: 0,
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
speed: 0,
|
||||
time: 0,
|
||||
satellites: 0
|
||||
};
|
||||
|
||||
function drawTime() {
|
||||
var d = new Date();
|
||||
var da = d.toString().split(" ");
|
||||
var time = da[4].substr(0,5);
|
||||
|
||||
g.reset();
|
||||
g.clearRect(0,24,239,239);
|
||||
g.setColor(1,1,1); // white
|
||||
g.setFontAlign(0, -1);
|
||||
|
||||
if (gpsState == GPS_SATS || gpsState == GPS_RUNNING) {
|
||||
time = last_fix.time.toUTCString().split(" ");
|
||||
time = time[4];
|
||||
g.setFont("Vector", 56);
|
||||
} else {
|
||||
g.setFont("Vector", 80);
|
||||
}
|
||||
|
||||
g.drawString(time, g.getWidth()/2, Y_TIME);
|
||||
}
|
||||
|
||||
function drawSteps() {
|
||||
g.setColor(0,255,0); // green
|
||||
g.setFont("Vector", 60);
|
||||
g.drawString(getSteps(), g.getWidth()/2, Y_ACTIVITY);
|
||||
}
|
||||
|
||||
function drawActivity() {
|
||||
if (!gpsPowerState) {
|
||||
drawSteps();
|
||||
return;
|
||||
}
|
||||
|
||||
g.setFont("6x8", 3);
|
||||
g.setColor(1,1,1);
|
||||
g.setFontAlign(0, -1);
|
||||
|
||||
if (gpsState == GPS_TIME) {
|
||||
g.drawString("Waiting for", g.getWidth()/2, Y_ACTIVITY);
|
||||
g.drawString("GPS", g.getWidth()/2, Y_ACTIVITY + 30);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpsState == GPS_SATS) {
|
||||
g.drawString("Satellites", g.getWidth()/2, Y_ACTIVITY);
|
||||
g.drawString(last_fix.satellites, g.getWidth()/2, Y_ACTIVITY + 30);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpsState == GPS_RUNNING) {
|
||||
//console.log("Draw GPS Running");
|
||||
let time = formatTime(last_fix.time);
|
||||
let age = timeSince(time);
|
||||
let os = OsGridRef.latLongToOsGrid(last_fix);
|
||||
let ref = to_map_ref(6, os.easting, os.northing);
|
||||
let speed;
|
||||
|
||||
if (age < 0) age = 0;
|
||||
g.setFontVector(40);
|
||||
g.setColor(0xFFC0);
|
||||
|
||||
switch(gpsDisplay) {
|
||||
case GDISP_OS:
|
||||
g.drawString(ref, 120, Y_ACTIVITY, true);
|
||||
break;
|
||||
case GDISP_SPEED:
|
||||
speed = last_fix.speed;
|
||||
speed = speed.toFixed(1);
|
||||
g.drawString(speed + "kph", 120, Y_ACTIVITY, true);
|
||||
break;
|
||||
case GDISP_ALT:
|
||||
g.drawString(last_fix.alt + "m" , 120, Y_ACTIVITY, true);
|
||||
break;
|
||||
}
|
||||
|
||||
g.setFont("6x8",2);
|
||||
g.setColor(1,1,1);
|
||||
g.drawString(age, 120, Y_ACTIVITY + 46);
|
||||
}
|
||||
}
|
||||
|
||||
function onTick() {
|
||||
if (!Bangle.isLCDOn())
|
||||
return;
|
||||
|
||||
if (gpsPowerState) {
|
||||
drawAll();
|
||||
return;
|
||||
}
|
||||
|
||||
if (last_steps != getSteps()) {
|
||||
last_steps = getSteps();
|
||||
drawAll();
|
||||
return;
|
||||
}
|
||||
|
||||
var t = new Date();
|
||||
|
||||
if (t.getSeconds() === 0 && !gpsPowerState) {
|
||||
drawAll();
|
||||
}
|
||||
}
|
||||
|
||||
function drawAll(){
|
||||
drawTime();
|
||||
drawActivity(); // steps, hrt or gps
|
||||
drawInfo();
|
||||
}
|
||||
|
||||
function drawInfo() {
|
||||
let val;
|
||||
let str = "";
|
||||
let col = 0x07E0; // green
|
||||
|
||||
//console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode);
|
||||
|
||||
switch(functionMode) {
|
||||
case FN_MODE_OFF:
|
||||
break;
|
||||
case FN_MODE_GPS:
|
||||
col = 0x07FF; // cyan
|
||||
str = "GPS: " + (gpsPowerState ? "ON" : "OFF");
|
||||
drawModeLine(str,col);
|
||||
return;
|
||||
case FN_MODE_GDISP:
|
||||
col = 0x07FF; // cyan
|
||||
switch(gpsDisplay) {
|
||||
case GDISP_OS:
|
||||
str = "GPS: Grid";
|
||||
break;
|
||||
case GDISP_SPEED:
|
||||
str = "GPS: Speed";
|
||||
break;
|
||||
case GDISP_ALT:
|
||||
str = "GPS: Alt";
|
||||
break;
|
||||
}
|
||||
drawModeLine(str,col);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case INFO_NONE:
|
||||
col = 0x0000;
|
||||
str = "";
|
||||
break;
|
||||
case INFO_STEPS:
|
||||
str = "Steps: " + getSteps();
|
||||
break;
|
||||
case INFO_BATT:
|
||||
default:
|
||||
str = "Battery: " + E.getBattery() + "%";
|
||||
}
|
||||
|
||||
drawModeLine(str,col);
|
||||
}
|
||||
|
||||
function drawModeLine(str, col) {
|
||||
g.setFont("6x8", 3);
|
||||
g.setColor(col);
|
||||
g.fillRect(0, Y_MODELINE - 3, 239, Y_MODELINE + 25);
|
||||
g.setColor(0,0,0);
|
||||
g.setFontAlign(0, -1);
|
||||
g.drawString(str, g.getWidth()/2, Y_MODELINE);
|
||||
}
|
||||
|
||||
function changeInfoMode() {
|
||||
switch(functionMode) {
|
||||
case FN_MODE_OFF:
|
||||
break;
|
||||
case FN_MODE_GPS:
|
||||
gpsPowerState = !gpsPowerState;
|
||||
Bangle.buzz();
|
||||
Bangle.setGPSPower(gpsPowerState ? 1 : 0);
|
||||
if (gpsPowerState) {
|
||||
gpsState = GPS_TIME; // waiting first response so we can display time
|
||||
Bangle.on('GPS', processFix);
|
||||
} else {
|
||||
Bangle.removeListener("GPS", processFix);
|
||||
gpsState = GPS_OFF;
|
||||
}
|
||||
resetLastFix();
|
||||
|
||||
// poke the gps widget indicator to change
|
||||
if (WIDGETS.gps !== undefined) {
|
||||
WIDGETS.gps.draw();
|
||||
}
|
||||
functionMode = FN_MODE_OFF;
|
||||
infoMode = INFO_NONE;
|
||||
//drawInfo();
|
||||
return;
|
||||
|
||||
case FN_MODE_GDISP:
|
||||
switch (gpsDisplay) {
|
||||
case GDISP_OS:
|
||||
gpsDisplay = GDISP_SPEED;
|
||||
break;
|
||||
case GDISP_SPEED:
|
||||
gpsDisplay = GDISP_ALT;
|
||||
break;
|
||||
case GDISP_ALT:
|
||||
default:
|
||||
gpsDisplay = GDISP_OS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(infoMode) {
|
||||
case INFO_NONE:
|
||||
if (stepsWidget() !== undefined)
|
||||
infoMode = INFO_STEPS;
|
||||
else
|
||||
infoMode = INFO_BATT;
|
||||
break;
|
||||
case INFO_STEPS:
|
||||
infoMode = INFO_BATT;
|
||||
break;
|
||||
case INFO_BATT:
|
||||
default:
|
||||
infoMode = INFO_NONE;
|
||||
}
|
||||
//drawInfo();
|
||||
}
|
||||
|
||||
function changeFunctionMode() {
|
||||
//console.log("changeFunctionMode()");
|
||||
|
||||
if (gpsState != GPS_RUNNING) {
|
||||
switch(functionMode) {
|
||||
case FN_MODE_OFF:
|
||||
functionMode = FN_MODE_GPS;
|
||||
break;
|
||||
case FN_MODE_GPS:
|
||||
default:
|
||||
functionMode = FN_MODE_OFF;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// if GPS is RUNNING then we want the GPS display options first
|
||||
switch(functionMode) {
|
||||
case FN_MODE_OFF:
|
||||
functionMode = FN_MODE_GDISP;
|
||||
break;
|
||||
case FN_MODE_GDISP:
|
||||
functionMode = FN_MODE_GPS;
|
||||
break;
|
||||
case FN_MODE_GPS:
|
||||
default:
|
||||
functionMode = FN_MODE_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
infoMode = INFO_NONE; // function mode overrides info mode
|
||||
}
|
||||
|
||||
function resetLastFix() {
|
||||
last_fix = {
|
||||
fix: 0,
|
||||
alt: 0,
|
||||
lat: 0,
|
||||
lon: 0,
|
||||
speed: 0,
|
||||
time: 0,
|
||||
satellites: 0
|
||||
};
|
||||
}
|
||||
|
||||
function processFix(fix) {
|
||||
last_fix.time = fix.time;
|
||||
|
||||
if (gpsState == GPS_TIME)
|
||||
gpsState = GPS_SATS;
|
||||
|
||||
if (fix.fix) {
|
||||
if (!last_fix.fix) Bangle.buzz(); // buzz on first position
|
||||
gpsState = GPS_RUNNING;
|
||||
last_fix = fix;
|
||||
}
|
||||
}
|
||||
|
||||
function getSteps() {
|
||||
if (stepsWidget() !== undefined)
|
||||
return stepsWidget().getSteps();
|
||||
return "-";
|
||||
}
|
||||
|
||||
function stepsWidget() {
|
||||
if (WIDGETS.activepedom !== undefined) {
|
||||
return WIDGETS.activepedom;
|
||||
} else if (WIDGETS.wpedom !== undefined) {
|
||||
return WIDGETS.wpedom;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/************* GPS / OSREF Code **************************/
|
||||
|
||||
function formatTime(now) {
|
||||
var fd = now.toUTCString().split(" ");
|
||||
return fd[4];
|
||||
}
|
||||
|
||||
function timeSince(t) {
|
||||
var hms = t.split(":");
|
||||
var now = new Date();
|
||||
|
||||
var sn = 3600*(now.getHours()) + 60*(now.getMinutes()) + 1*(now.getSeconds());
|
||||
var st = 3600*(hms[0]) + 60*(hms[1]) + 1*(hms[2]);
|
||||
|
||||
return (sn - st);
|
||||
}
|
||||
|
||||
Number.prototype.toRad = function() { return this*Math.PI/180; };
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
/* Ordnance Survey Grid Reference functions (c) Chris Veness 2005-2014 */
|
||||
/* - www.movable-type.co.uk/scripts/gridref.js */
|
||||
/* - www.movable-type.co.uk/scripts/latlon-gridref.html */
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
function OsGridRef(easting, northing) {
|
||||
this.easting = 0|easting;
|
||||
this.northing = 0|northing;
|
||||
}
|
||||
OsGridRef.latLongToOsGrid = function(point) {
|
||||
var lat = point.lat.toRad();
|
||||
var lon = point.lon.toRad();
|
||||
|
||||
var a = 6377563.396, b = 6356256.909; // Airy 1830 major & minor semi-axes
|
||||
var F0 = 0.9996012717; // NatGrid scale factor on central meridian
|
||||
var lat0 = (49).toRad(), lon0 = (-2).toRad(); // NatGrid true origin is 49�N,2�W
|
||||
var N0 = -100000, E0 = 400000; // northing & easting of true origin, metres
|
||||
var e2 = 1 - (b*b)/(a*a); // eccentricity squared
|
||||
var n = (a-b)/(a+b), n2 = n*n, n3 = n*n*n;
|
||||
|
||||
var cosLat = Math.cos(lat), sinLat = Math.sin(lat);
|
||||
var nu = a*F0/Math.sqrt(1-e2*sinLat*sinLat); // transverse radius of curvature
|
||||
var rho = a*F0*(1-e2)/Math.pow(1-e2*sinLat*sinLat, 1.5); // meridional radius of curvature
|
||||
var eta2 = nu/rho-1;
|
||||
|
||||
var Ma = (1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0);
|
||||
var Mb = (3*n + 3*n*n + (21/8)*n3) * Math.sin(lat-lat0) * Math.cos(lat+lat0);
|
||||
var Mc = ((15/8)*n2 + (15/8)*n3) * Math.sin(2*(lat-lat0)) * Math.cos(2*(lat+lat0));
|
||||
var Md = (35/24)*n3 * Math.sin(3*(lat-lat0)) * Math.cos(3*(lat+lat0));
|
||||
var M = b * F0 * (Ma - Mb + Mc - Md); // meridional arc
|
||||
|
||||
var cos3lat = cosLat*cosLat*cosLat;
|
||||
var cos5lat = cos3lat*cosLat*cosLat;
|
||||
var tan2lat = Math.tan(lat)*Math.tan(lat);
|
||||
var tan4lat = tan2lat*tan2lat;
|
||||
|
||||
var I = M + N0;
|
||||
var II = (nu/2)*sinLat*cosLat;
|
||||
var III = (nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2);
|
||||
var IIIA = (nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat);
|
||||
var IV = nu*cosLat;
|
||||
var V = (nu/6)*cos3lat*(nu/rho-tan2lat);
|
||||
var VI = (nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2);
|
||||
|
||||
var dLon = lon-lon0;
|
||||
var dLon2 = dLon*dLon, dLon3 = dLon2*dLon, dLon4 = dLon3*dLon, dLon5 = dLon4*dLon, dLon6 = dLon5*dLon;
|
||||
|
||||
var N = I + II*dLon2 + III*dLon4 + IIIA*dLon6;
|
||||
var E = E0 + IV*dLon + V*dLon3 + VI*dLon5;
|
||||
|
||||
return new OsGridRef(E, N);
|
||||
};
|
||||
|
||||
/*
|
||||
* converts northing, easting to standard OS grid reference.
|
||||
*
|
||||
* [digits=10] - precision (10 digits = metres)
|
||||
* to_map_ref(8, 651409, 313177); => 'TG 5140 1317'
|
||||
* to_map_ref(0, 651409, 313177); => '651409,313177'
|
||||
*
|
||||
*/
|
||||
function to_map_ref(digits, easting, northing) {
|
||||
if (![ 0,2,4,6,8,10,12,14,16 ].includes(Number(digits))) throw new RangeError(`invalid precision '${digits}'`); // eslint-disable-line comma-spacing
|
||||
|
||||
let e = easting;
|
||||
let n = northing;
|
||||
|
||||
// use digits = 0 to return numeric format (in metres) - note northing may be >= 1e7
|
||||
if (digits == 0) {
|
||||
const format = { useGrouping: false, minimumIntegerDigits: 6, maximumFractionDigits: 3 };
|
||||
const ePad = e.toLocaleString('en', format);
|
||||
const nPad = n.toLocaleString('en', format);
|
||||
return `${ePad},${nPad}`;
|
||||
}
|
||||
|
||||
// get the 100km-grid indices
|
||||
const e100km = Math.floor(e / 100000), n100km = Math.floor(n / 100000);
|
||||
|
||||
// translate those into numeric equivalents of the grid letters
|
||||
let l1 = (19 - n100km) - (19 - n100km) % 5 + Math.floor((e100km + 10) / 5);
|
||||
let l2 = (19 - n100km) * 5 % 25 + e100km % 5;
|
||||
|
||||
// compensate for skipped 'I' and build grid letter-pairs
|
||||
if (l1 > 7) l1++;
|
||||
if (l2 > 7) l2++;
|
||||
const letterPair = String.fromCharCode(l1 + 'A'.charCodeAt(0), l2 + 'A'.charCodeAt(0));
|
||||
|
||||
// strip 100km-grid indices from easting & northing, and reduce precision
|
||||
e = Math.floor((e % 100000) / Math.pow(10, 5 - digits / 2));
|
||||
n = Math.floor((n % 100000) / Math.pow(10, 5 - digits / 2));
|
||||
|
||||
// pad eastings & northings with leading zeros
|
||||
e = e.toString().padStart(digits/2, '0');
|
||||
n = n.toString().padStart(digits/2, '0');
|
||||
|
||||
return `${letterPair} ${e} ${n}`;
|
||||
}
|
||||
|
||||
// start a timer and buzz whenn held long enough
|
||||
function firstPressed() {
|
||||
firstPress = getTime();
|
||||
pressTimer = setInterval(longPressCheck, 1500);
|
||||
}
|
||||
|
||||
// if you release too soon there is no buzz as timer is cleared
|
||||
function thenReleased() {
|
||||
var dur = getTime() - firstPress;
|
||||
if (pressTimer) {
|
||||
clearInterval(pressTimer);
|
||||
pressTimer = undefined;
|
||||
}
|
||||
if ( dur >= 1.5 ) Bangle.showLauncher();
|
||||
}
|
||||
|
||||
// when you feel the buzzer you know you have done a long press
|
||||
function longPressCheck() {
|
||||
Bangle.buzz();
|
||||
if (pressTimer) {
|
||||
clearInterval(pressTimer);
|
||||
pressTimer = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var pressTimer;
|
||||
|
||||
g.clear();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
drawAll();
|
||||
|
||||
Bangle.on('lcdPower',function(on) {
|
||||
functionMode = FN_MODE_OFF;
|
||||
infoMode = INFO_NONE;
|
||||
if (on) drawAll();
|
||||
});
|
||||
|
||||
var click = setInterval(onTick, 5000);
|
||||
|
||||
setWatch(() => { changeInfoMode(); drawAll(); }, BTN1, {repeat: true});
|
||||
setWatch(() => { changeFunctionMode(); drawAll(); }, BTN3, {repeat: true});
|
||||
|
||||
// make BTN require a long press (1.5 seconds) to switch to launcher
|
||||
setWatch(firstPressed, BTN2,{repeat:true,edge:"rising"});
|
||||
setWatch(thenReleased, BTN2,{repeat:true,edge:"falling"});
|
||||
|
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4A/AEcsAAYuuGFIqEF9gFJF/62SACAvvGCgYEwIASqwxVF4mmACQvEGCJcCF65iDF/4vbqwvVd4YeBJgIECAAulq4KDmS/XAAVXJwgvHOAIKCOoQuTGQ1WvYvCvYAGBQdWLwYtUMQwAQGAQuYXgJPCmQEBAAwKDCQKNZlmsAAKECAoQAEX4QQESKh4EDwVXegIvPSKgbBDwMs64ABAoOBAoQAE1gvGTAQwQCINXF4olBFw4KCAAYvCDIQvZABgv/F/4vqCoYvpGAMyF7ICBF6QADEIeBABQuCF4QACFyAwFDwRlCABNWHoUyFyoxEwOIxGBPoIAJMYYvCFyrzEGAIALFwS7TYRYACmQAGSxAtcACaNWwGArizBAwIAININWrgTCF6+GAAYvCA4gACwAKGCQIv/F+qqBAAQvCA4gACXAIKFF67cBAAQvCAwYKFmQGFF6wAZF6YxaFyo1HIBYpcAH4A/AAoA=="))
|
After Width: | Height: | Size: 1.8 KiB |