var Clay = require('pebble-clay');
var clayConfig = require('./config');
var clay = new Clay(clayConfig);
var messageKeys = require('message_keys');
var message;
//var locationInterval;
var locationOptions = {
'enableHighAccuracy': true, // default = false (quick and dirty mode), can be true (more accurate but need more power and time)
'timeout': 5000, //2s timeout
'maximumAge': 0 // no cache
};
var geoloc_id;
// Store location in Pebble app local storage
//
function storeLocation(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var timestamp = position.timestamp;
localStorage.setItem("latitude", latitude);
localStorage.setItem("longitude", longitude);
localStorage.setItem("timestamp", timestamp);
// console.log("Stored location " + position.coords.latitude + ',' + position.coords.longitude);
}
// Get location from Pebble app local storage
//
function getLocation() {
if (localStorage.getItem("latitude") || localStorage.getItem("longitude") || localStorage.getItem("timestamp")) {
var la = localStorage.getItem("latitude");
var lo = localStorage.getItem("longitude");
var ti = localStorage.getItem("timestamp");
var co = { "latitude": la, "longitude": lo };
var pos = { "coords": co, "timestamp": ti };
// console.log("Stored location " + pos.co.la + ',' + pos.co.lo);
return pos;
} else {
return null;
}
}
// Calculate the distance from 2 geoloc in degrees.
// IMPORTANT : this is a calculation from 2D projection, altitude is not involved
//
function distance_on_geoid(lat1, lon1, lat2, lon2) {
// Convert degrees to radians
lat1 = lat1 * Math.PI / 180.0;
lon1 = lon1 * Math.PI / 180.0;
lat2 = lat2 * Math.PI / 180.0;
lon2 = lon2 * Math.PI / 180.0;
// radius of earth in metres
r = 6378100;
// P
rho1 = r * Math.cos(lat1);
z1 = r * Math.sin(lat1);
x1 = rho1 * Math.cos(lon1);
y1 = rho1 * Math.sin(lon1);
// Q
rho2 = r * Math.cos(lat2);
z2 = r * Math.sin(lat2);
x2 = rho2 * Math.cos(lon2);
y2 = rho2 * Math.sin(lon2);
// Dot product
dot = (x1 * x2 + y1 * y2 + z1 * z2);
cos_theta = dot / (r * r);
theta = Math.acos(cos_theta);
// Distance in Metres
return r * theta;
}
// Calculate speed from 2 geoloc point arrays (with lat,long,timestamp)
//
function speed_from_distance_and_time(p1, p2) {
dist = distance_on_geoid(p1.coords.latitude, p1.coords.longitude, p2.coords.latitude, p2.coords.longitude);
// timestamp is in milliseconds
time_s = (p2.timestamp - p1.timestamp) / 1000.0;
speed_mps = dist / time_s;
speed_kph = (speed_mps * 3600.0) / 1000.0;
return speed_kph;
}
// split float number into an array of int (null returned instead of 0 for decimal)
//
function splitFloatNumber(num) {
const intStr = num.toString().split('.')[0];
const decimalStr = num.toString().split('.')[1];
return [Number(intStr), Number(decimalStr)];
}
// Build GPX headers
//
function GPXHeadersBuilder(timestamp, name, type) {
var headers = '<?xml version="1.0" encoding="UTF-8"?><gpx creator="Pebble with barometer" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" xmlns="http://www.topografix.com/GPX/1/1"><metadata><time>' + timestamp + '</time></metadata><trk><name>' + name + '</name><type>' + type + '</type><trkseg>';
var ret = localStorage.setItem("GPX", headers);
return true;
}
// Build GPX footer
//
function GPXtrkptBuilder(lat, lon, ele, timestamp) {
var GPX = localStorage.getItem("GPX");
var trkpt = '<trkpt lat="' + lat + '" lon="' + lon + '"><ele>' + ele + '</ele><time>' + timestamp + '</time></trkpt>';
var ret = localStorage.setItem("GPX", GPX + trkpt);
return true;
}
// Build GPX footer
//
function GPXfooterBuilder() {
var GPX = localStorage.getItem("GPX");
var footer = '</trkseg></trk></gpx>';
var ret = localStorage.setItem("GPX", GPX + footer);
return true;
}
// Adding leading characters to string for nice displays
//
function padStart(string, max_length, padding) {
if (string.length > max_length) {
return string;
} else {
var new_str = string;
for (index = string.length; index < max_length; index++) {
new_str = "0" + new_str;
}
return new_str;
}
}
// called in case of successful geoloc gathering and sends the coordinate to watch
//
function locationSuccess(new_pos) {
console.log('--- locationSuccess');
console.log(" location is " + new_pos.coords.latitude + ',' + new_pos.coords.longitude + ' , acc. ' + new_pos.coords.accuracy);
var prev_pos = getLocation();
storeLocation(new_pos);
if (prev_pos === null) {
console.log('--- start building gpx');
// Start the GPX file
GPXHeadersBuilder(new Date(new_pos.timestamp).toISOString(), "test", "18");
} else {
//clear watch of new position to avoid overlap
//navigator.geolocation.clearWatch(geoloc_id);
//console.log('--- watch geoloc cleared');
var speed = speed_from_distance_and_time(prev_pos, new_pos);
// Prepare display on watch
// now it's only raw data
// init strings
var latitudeString = "";
var longitudeString = "";
var accuracyString = "";
var altitudeString = "";
var speedString = "";
//formating for precision and max size
latitudeString = new_pos.coords.latitude.toString().substring(0, 12);
longitudeString = new_pos.coords.longitude.toString().substring(0, 12);
accuracyString = new_pos.coords.accuracy.toString().substring(0, 4);
altitudeString = splitFloatNumber(new_pos.coords.altitude)[0].toString().substring(0, 5);
timestampISO = new Date(new_pos.timestamp).toISOString();
speedString = speed.toString().substring(0, 5);
if (speedString == "NaN") {
speedString = "---";
}
//add a new datapoint to GPX file
GPXtrkptBuilder(latitudeString, longitudeString, altitudeString, timestampISO);
console.log('GPX: ' + localStorage.getItem("GPX"));
// Build message
message = "OK";
var dict = {
'accuracy': accuracyString,
'altitude': altitudeString,
'speed': speedString,
'status': message
};
// Send the message
Pebble.sendAppMessage(dict, function () {
console.log('Message sent successfully: ' + JSON.stringify(dict));
}, function (e) {
console.log('Message (' + JSON.stringify(dict) + ') failed: ' + JSON.stringify(e));
});
}
// restart the watch
//geoloc_id = navigator.geolocation.watchPosition(locationSuccess, locationError, locationOptions);
}
function locationError(err) {
//clear watch of new position to avoid overlap
//navigator.geolocation.clearWatch(geoloc_id);
console.warn('location error (' + err.code + '): ' + err.message);
// restart the watch
//geoloc_id = navigator.geolocation.watchPosition(locationSuccess, locationError, locationOptions);
}
function get_coordinate() {
/*console.log('---- start geoloc');
navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
*/
}
function init() {
// local storage init
localStorage.clear();
// clear any other var to do
//clearInterval(locationInterval);
console.log('--- Starting regular getCurrentPosition loop using setInterval at 5 sec');
locationInterval = setInterval(function () {
navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
}, 5000);
}
// Get JS readiness events
Pebble.addEventListener('ready', function (e) {
console.log('PebbleKit JS is ready');
// Update Watch on this
Pebble.sendAppMessage({ 'JSReady': 1 });
init();
});
// Get AppMessage events
Pebble.addEventListener('appmessage', function (e) {
// Get the dictionary from the message
var dict = e.payload;
console.log(dict[0].toString());
switch (dict[0]) {
case 'get':
get_coordinate();
break;
default:
console.log('Sorry. I don\'t understand your request :' + dict[0]);
}
});