Comparing version 0.0.9 to 0.0.10
{ | ||
"name": "gps", | ||
"main": "gps.js", | ||
"version": "0.0.9", | ||
"version": "0.0.10", | ||
"homepage": "https://github.com/infusion/GPS.js", | ||
@@ -26,2 +26,2 @@ "description": "A GPS NMEA parser library", | ||
] | ||
} | ||
} |
35
gps.js
/** | ||
* @license GPS.js v0.0.9 26/01/2016 | ||
* @license GPS.js v0.0.10 26/01/2016 | ||
* | ||
@@ -78,3 +78,3 @@ * Copyright (c) 2016, Robert Eisele (robert@xarg.org) | ||
} else { | ||
// If we need to parse older GPRMC data, we should hack something like | ||
// If we need to parse older GPRMC data, we should hack something like | ||
// year < 73 ? 2000+year : 1900+year | ||
@@ -118,6 +118,6 @@ ret.setUTCFullYear('20' + year, month, day); | ||
* Mathematically, but more expensive and not numerical stable: | ||
* | ||
* | ||
* raw = 4807.038 | ||
* deg = Math.floor(raw / 100) | ||
* | ||
* | ||
* dec = (raw - (100 * deg)) / 60 | ||
@@ -256,3 +256,3 @@ * res = deg + dec // 48.1173 | ||
if (unit === 'M') { | ||
if (unit === 'M' || unit === '') { | ||
return parseNumber(num); | ||
@@ -285,3 +285,3 @@ } | ||
$--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh | ||
1) Time (UTC) | ||
@@ -330,4 +330,4 @@ 2) Latitude | ||
eg2. $GPGSA,A,3,19,28,14,18,27,22,31,39,,,,,1.7,1.0,1.3*35 | ||
1 = Mode: | ||
@@ -373,3 +373,3 @@ M=Manual, forced to operate in 2D or 3D | ||
$GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh | ||
RMC = Recommended Minimum Specific GPS/TRANSIT Data | ||
@@ -415,3 +415,3 @@ 1 = UTC of position fix | ||
------------------------------------------------------------------------------ | ||
1 = Track degrees | ||
@@ -429,2 +429,11 @@ 2 = Fixed text 'T' indicates that track made good is relative to true north | ||
if (vtg[2] === '' && vtg[8] === '' && vtg[6] === '') { | ||
return { | ||
'track': null, | ||
'speed': null, | ||
'faa': null | ||
}; | ||
} | ||
if (vtg[2] !== 'T') { | ||
@@ -453,3 +462,3 @@ throw 'Invalid VTG track mode: ' + str; | ||
$GPGSV,1,1,13,02,02,213,,03,-3,000,,11,00,121,,14,13,172,05*67 | ||
1 = Total number of messages of this type in this cycle | ||
@@ -504,3 +513,3 @@ 2 = Message number | ||
------------------------------------------------------------------------------ | ||
1. Latitude | ||
@@ -577,3 +586,3 @@ 2. N or S (North or South) | ||
// Heading (N=0, E=90, S=189, W=270) from point 1 to point 2 | ||
// Heading (N=0, E=90, S=189, W=270) from point 1 to point 2 | ||
GPS['Heading'] = function(lat1, lon1, lat2, lon2) { | ||
@@ -580,0 +589,0 @@ |
/* | ||
GPS.js v0.0.9 26/01/2016 | ||
GPS.js v0.0.10 26/01/2016 | ||
@@ -9,9 +9,9 @@ Copyright (c) 2016, Robert Eisele (robert@xarg.org) | ||
60)}function e(b){return""===b?null:parseFloat(b)}function n(b){return""===b?null:1.852*parseFloat(b)}function u(b){switch(b){case "":case "0":return null;case "1":return"fix";case "2":return"dgps-fix";case "3":return"pps-fix";case "6":return"estimated";case "7":return"manual";case "8":return"simulated"}throw"INVALID GGA FIX: "+b;}function p(b){switch(b){case "A":return"active";case "V":return"void";case "":return null}throw"INVALID RMC/GLL STATUS: "+b;}function q(b){switch(b){case "A":return"autonomous"; | ||
case "D":return"differential";case "E":return"estimated";case "M":return"manual input";case "S":return"simulated";case "N":return"not valid";case "P":return"precise"}throw"INVALID FAA MODE: "+b;}function r(b,a){if("M"===a)return e(b);throw"Unknown unit: "+a;}function f(){this.events={};this.state={}}var h=Math.PI/180,m=[];f.prototype.events=null;f.prototype.state=null;f.mod={GGA:function(b,a){if(16!==a.length)throw"Invalid GGA length: "+b;return{time:l(a[1]),lat:k(a[2],a[3]),lon:k(a[4],a[5]),alt:r(a[9], | ||
a[10]),quality:u(a[6]),satelites:e(a[7]),hdop:e(a[8]),geoidal:r(a[11],a[12]),age:e(a[13]),stationID:e(a[14])}},GSA:function(b,a){if(19!==a.length)throw"Invalid GSA length: "+b;b=[];for(var c=3;15>c;c++)""!==a[c]&&b.push(parseInt(a[c],10));a:{c=a[1];switch(c){case "M":c="manual";break a;case "A":c="automatic";break a;case "":c=null;break a}throw"INVALID GSA MODE: "+c;}var d;a:{d=a[2];switch(d){case "1":case "":d=null;break a;case "2":d="2D";break a;case "3":d="3D";break a}throw"INVALID GSA FIX: "+ | ||
d;}return{mode:c,fix:d,satellites:b,pdop:e(a[15]),hdop:e(a[16]),vdop:e(a[17])}},RMC:function(b,a){if(13!==a.length&&14!==a.length)throw"Invalid RMC length: "+b;b=l(a[1],a[9]);var c=p(a[2]),d=a[10],g=a[11];return{time:b,status:c,lat:k(a[3],a[4]),lon:k(a[5],a[6]),speed:n(a[7]),track:e(a[8]),variation:""===d||""===g?null:parseFloat(d)*("W"===g?-1:1),faa:14===a.length?q(a[12]):null}},VTG:function(b,a){if(10!==a.length&&11!==a.length)throw"Invalid VTG length: "+b;if("T"!==a[2])throw"Invalid VTG track mode: "+ | ||
b;if("K"!==a[8]||"N"!==a[6])throw"Invalid VTG speed tag: "+b;return{track:e(a[1]),speed:n(a[5]),faa:11===a.length?q(a[9]):null}},GSV:function(b,a){if(9>a.length||1!==a.length%4)throw"Invalid GSV length: "+b;b=[];for(var c=4;c<a.length-1;c+=4){var d=e(a[c]),g=e(a[c+3]);b.push({prn:d,elevation:e(a[c+1]),azimuth:e(a[c+2]),snr:g,status:null!==d?null!==g?"tracking":"in view":null})}return{msgNumber:e(a[2]),msgsTotal:e(a[1]),satellites:b}},GLL:function(b,a){if(9!==a.length)throw"Invalid GLL length: "+b; | ||
return{time:l(a[5]),status:p(a[6]),lat:k(a[1],a[2]),lon:k(a[3],a[4])}},ZDA:function(b,a){return{time:l(a[1],a[2]+a[3]+a[4])}}};f.Parse=function(b){if("string"!==typeof b)return!1;var a=b.split(","),c=a.pop();if(4>a.length||"$"!==b.charAt(0)||-1===c.indexOf("*"))return!1;c=c.split("*");a.push(c[0]);a.push(c[1]);a[0]=a[0].slice(3);if(void 0!==f.mod[a[0]]){c=this.mod[a[0]](b,a);c.raw=b;for(var d=0,g=1;g<b.length;g++){var e=b.charCodeAt(g);if(42===e)break;d^=e}c.valid=d===parseInt(a[a.length-1],16);c.type= | ||
a[0];return c}return!1};f.Heading=function(b,a,c,d){a=(d-a)*h;b*=h;c*=h;d=Math.cos(c);return(180*Math.atan2(Math.sin(a)*d,Math.cos(b)*Math.sin(c)-Math.sin(b)*d*Math.cos(a))/Math.PI+360)%360};f.Distance=function(b,a,c,d){var e=(c-b)*h*.5;a=(d-a)*h*.5;b*=h;c*=h;e=Math.sin(e);a=Math.sin(a);return 12745.6*Math.asin(Math.sqrt(e*e+Math.cos(b)*Math.cos(c)*a*a))};f.prototype.update=function(b){b=f.Parse(b);if(!1===b)return!1;var a=this.state;if("RMC"===b.type||"GGA"===b.type||"GLL"===b.type)a.time=b.time, | ||
a.lat=b.lat,a.lon=b.lon;"ZDA"===b.type&&(a.time=b.time);"GGA"===b.type&&(a.alt=b.alt);"RMC"===b.type&&(a.speed=b.speed,a.track=b.track);"GSA"===b.type&&(a.satsActive=b.satellites,a.fix=b.fix,a.hdop=b.hdop,a.pdop=b.pdop,a.vdop=b.vdop);if("GSV"===b.type){for(var c=b.satellites,d=0;d<c.length;d++)m.push(c[d]);b.msgNumber===b.msgsTotal&&(a.satsVisible=m,m=[])}void 0!==this.events.data&&this.events.data.call(this,b);void 0!==this.events[b.type]&&this.events[b.type].call(this,b);return!0};f.prototype.partial= | ||
"";f.prototype.updatePartial=function(b){for(this.partial+=b;;){b=this.partial.indexOf("\r\n");if(-1===b)break;var a=this.partial.slice(0,b);"$"===a.charAt(0)&&this.update(a);this.partial=this.partial.slice(b+2)}};f.prototype.on=function(b,a){return void 0===this.events[b]?(this.events[b]=a,this):null};f.prototype.off=function(b){void 0!==this.events[b]&&(this.events[b]=void 0);return this};"object"===typeof exports?module.a=f:t.GPS=f})(this); | ||
case "D":return"differential";case "E":return"estimated";case "M":return"manual input";case "S":return"simulated";case "N":return"not valid";case "P":return"precise"}throw"INVALID FAA MODE: "+b;}function r(b,a){if("M"===a||""===a)return e(b);throw"Unknown unit: "+a;}function f(){this.events={};this.state={}}var h=Math.PI/180,m=[];f.prototype.events=null;f.prototype.state=null;f.mod={GGA:function(b,a){if(16!==a.length)throw"Invalid GGA length: "+b;return{time:l(a[1]),lat:k(a[2],a[3]),lon:k(a[4],a[5]), | ||
alt:r(a[9],a[10]),quality:u(a[6]),satelites:e(a[7]),hdop:e(a[8]),geoidal:r(a[11],a[12]),age:e(a[13]),stationID:e(a[14])}},GSA:function(b,a){if(19!==a.length)throw"Invalid GSA length: "+b;b=[];for(var c=3;15>c;c++)""!==a[c]&&b.push(parseInt(a[c],10));a:{c=a[1];switch(c){case "M":c="manual";break a;case "A":c="automatic";break a;case "":c=null;break a}throw"INVALID GSA MODE: "+c;}var d;a:{d=a[2];switch(d){case "1":case "":d=null;break a;case "2":d="2D";break a;case "3":d="3D";break a}throw"INVALID GSA FIX: "+ | ||
d;}return{mode:c,fix:d,satellites:b,pdop:e(a[15]),hdop:e(a[16]),vdop:e(a[17])}},RMC:function(b,a){if(13!==a.length&&14!==a.length)throw"Invalid RMC length: "+b;b=l(a[1],a[9]);var c=p(a[2]),d=a[10],g=a[11];return{time:b,status:c,lat:k(a[3],a[4]),lon:k(a[5],a[6]),speed:n(a[7]),track:e(a[8]),variation:""===d||""===g?null:parseFloat(d)*("W"===g?-1:1),faa:14===a.length?q(a[12]):null}},VTG:function(b,a){if(10!==a.length&&11!==a.length)throw"Invalid VTG length: "+b;if(""===a[2]&&""===a[8]&&""===a[6])return{track:null, | ||
speed:null,faa:null};if("T"!==a[2])throw"Invalid VTG track mode: "+b;if("K"!==a[8]||"N"!==a[6])throw"Invalid VTG speed tag: "+b;return{track:e(a[1]),speed:n(a[5]),faa:11===a.length?q(a[9]):null}},GSV:function(b,a){if(9>a.length||1!==a.length%4)throw"Invalid GSV length: "+b;b=[];for(var c=4;c<a.length-1;c+=4){var d=e(a[c]),g=e(a[c+3]);b.push({prn:d,elevation:e(a[c+1]),azimuth:e(a[c+2]),snr:g,status:null!==d?null!==g?"tracking":"in view":null})}return{msgNumber:e(a[2]),msgsTotal:e(a[1]),satellites:b}}, | ||
GLL:function(b,a){if(9!==a.length)throw"Invalid GLL length: "+b;return{time:l(a[5]),status:p(a[6]),lat:k(a[1],a[2]),lon:k(a[3],a[4])}},ZDA:function(b,a){return{time:l(a[1],a[2]+a[3]+a[4])}}};f.Parse=function(b){if("string"!==typeof b)return!1;var a=b.split(","),c=a.pop();if(4>a.length||"$"!==b.charAt(0)||-1===c.indexOf("*"))return!1;c=c.split("*");a.push(c[0]);a.push(c[1]);a[0]=a[0].slice(3);if(void 0!==f.mod[a[0]]){c=this.mod[a[0]](b,a);c.raw=b;for(var d=0,g=1;g<b.length;g++){var e=b.charCodeAt(g); | ||
if(42===e)break;d^=e}c.valid=d===parseInt(a[a.length-1],16);c.type=a[0];return c}return!1};f.Heading=function(b,a,c,d){a=(d-a)*h;b*=h;c*=h;d=Math.cos(c);return(180*Math.atan2(Math.sin(a)*d,Math.cos(b)*Math.sin(c)-Math.sin(b)*d*Math.cos(a))/Math.PI+360)%360};f.Distance=function(b,a,c,d){var e=(c-b)*h*.5;a=(d-a)*h*.5;b*=h;c*=h;e=Math.sin(e);a=Math.sin(a);return 12745.6*Math.asin(Math.sqrt(e*e+Math.cos(b)*Math.cos(c)*a*a))};f.prototype.update=function(b){b=f.Parse(b);if(!1===b)return!1;var a=this.state; | ||
if("RMC"===b.type||"GGA"===b.type||"GLL"===b.type)a.time=b.time,a.lat=b.lat,a.lon=b.lon;"ZDA"===b.type&&(a.time=b.time);"GGA"===b.type&&(a.alt=b.alt);"RMC"===b.type&&(a.speed=b.speed,a.track=b.track);"GSA"===b.type&&(a.satsActive=b.satellites,a.fix=b.fix,a.hdop=b.hdop,a.pdop=b.pdop,a.vdop=b.vdop);if("GSV"===b.type){for(var c=b.satellites,d=0;d<c.length;d++)m.push(c[d]);b.msgNumber===b.msgsTotal&&(a.satsVisible=m,m=[])}void 0!==this.events.data&&this.events.data.call(this,b);void 0!==this.events[b.type]&& | ||
this.events[b.type].call(this,b);return!0};f.prototype.partial="";f.prototype.updatePartial=function(b){for(this.partial+=b;;){b=this.partial.indexOf("\r\n");if(-1===b)break;var a=this.partial.slice(0,b);"$"===a.charAt(0)&&this.update(a);this.partial=this.partial.slice(b+2)}};f.prototype.on=function(b,a){return void 0===this.events[b]?(this.events[b]=a,this):null};f.prototype.off=function(b){void 0!==this.events[b]&&(this.events[b]=void 0);return this};"object"===typeof exports?module.a=f:t.GPS=f})(this); |
{ | ||
"name": "gps", | ||
"title": "gps.js", | ||
"version": "0.0.9", | ||
"version": "0.0.10", | ||
"homepage": "https://github.com/infusion/GPS.js", | ||
@@ -31,2 +31,3 @@ "bugs": "https://github.com/infusion/GPS.js/issues", | ||
"serialport": "*", | ||
"angles": "*", | ||
"mocha": "*", | ||
@@ -33,0 +34,0 @@ "chai": "*", |
@@ -50,3 +50,16 @@ | ||
Find the serial device | ||
=== | ||
On Linux serial devices typically have names like `/dev/ttyS1`, on OSX `/dev/tty.usbmodem1411` after installing a USB to serial driver and on Windows, you're probably fine by using the highest COM device you can find in the device manager. Please note that if you have multople USB ports on your computer and use them randomly, you have to lookup the path/device again. | ||
If you find yourself on a BeagleBone, the serial device must be registered manually. Luckily, this can be done within node quite easily using [octalbonescript](https://www.npmjs.com/package/octalbonescript): | ||
```javascript | ||
var obs = require('octalbonescript'); | ||
obs.serial.enable('/dev/ttyS1', function() { | ||
console.log('serial device activated'); | ||
}); | ||
``` | ||
Examples | ||
@@ -103,3 +116,26 @@ === | ||
Confluence | ||
--- | ||
[Confluence](http://www.confluence.org/) is a project, which tries to travel to and document all integer GPS coordinates. GPS.js can assist on that goal. Go into the examples folder and run: | ||
``` | ||
node confluence | ||
``` | ||
You should see something like the following, updating as you move around | ||
``` | ||
You are at (48.53, 9.05951), | ||
The closest confluence point (49, 9) is in 51.36 km. | ||
You have to go 355.2° N | ||
``` | ||
Set Time | ||
--- | ||
On systems without a RTC - like Raspberry PI - you need to update the time yourself at runtime. If the device has an internet connection, it's quite easy to use an NTP server. An alternative for disconnected projects with access to a GPS receiver can be the high-precision time signal, sent by satellites. Go to the examples folder and run the following to update the time: | ||
``` | ||
node set-time | ||
``` | ||
Available Methods | ||
@@ -240,2 +276,6 @@ === | ||
Troubleshooting | ||
=== | ||
If you don't get valid position information after turning on the receiver, chances are high you simply have to wait as it takes some [time to first fix](https://en.wikipedia.org/wiki/Time_to_first_fix). | ||
Functions | ||
@@ -256,5 +296,10 @@ === | ||
--- | ||
Calculates the angle from one coordinate to another. Heading is represented as windrose coordinates (N=0, E=90, S=189, W=270). | ||
Calculates the angle from one coordinate to another. Heading is represented as windrose coordinates (N=0, E=90, S=189, W=270). The result can be used as the argument of [angles](https://github.com/infusion/Angles.js) `compass()` method: | ||
```javascript | ||
var angles = require('angles'); | ||
console.log(angles.compass(GPS.Heading(50, 10, 51, 9))); // will return x ∈ { N, S, E, W, NE, ... } | ||
``` | ||
Using GPS.js with the browser | ||
@@ -261,0 +306,0 @@ === |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
310819
24
1348
326
7
3