feat: 导入 NMEA-0183 GPS 协议解析库(node-nmea)
Some checks failed
Node.js CI / build (10.x) (push) Has been cancelled
Node.js CI / build (12.x) (push) Has been cancelled
Node.js CI / build (14.x) (push) Has been cancelled
Node.js CI / build (15.x) (push) Has been cancelled

NMEA-0183 语句解析器,含 21 个语句类型 codec 与配套单元测试。

- codecs/:APB/BWC/DBT/GGA/GLL/GRMT/GSA/GSV/HDG/HDM/HDT/MWV/RDID/
  RMB/RMC/ROT/RSA/TXT/VTG/VWR/ZDA
- test/:各 codec 对应的 mocha 用例
- .github/workflows/:node与 npm-publish 流水线

许可证:MIT(原作者 James Penn)
This commit is contained in:
hyzl
2026-10-19 09:54:44 +08:00
commit b0a1993169
50 changed files with 1951 additions and 0 deletions

10
test/APBtest.js Normal file
View File

@@ -0,0 +1,10 @@
var should = require('should');
describe('GGA ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPAPB,A,A,0.10,R,N,V,V,011,M,DEST,011,M,011,M*3C");
msg.should.have.property('type', 'autopilot-b');
msg.should.have.property('sentence', 'APB');
});
});

10
test/BWCtest.js Normal file
View File

@@ -0,0 +1,10 @@
var should = require('should');
describe('BWC ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPBWC,220516,5130.02,N,00046.34,W,213.8,T,218.0,M,0004.6,N,EGLM*21");
msg.should.have.property('type', '2waypoint');
msg.should.have.property('sentence', 'BWC');
});
});

23
test/DBTtest.js Normal file
View File

@@ -0,0 +1,23 @@
var should = require('should');
describe('DBT parsing', function () {
it('parses feet and meters', function () {
var msg = require("../nmea.js").parse("$IIDBT,036.41,f,011.10,M,005.99,F*25");
msg.should.have.property('sentence', 'DBT');
msg.should.have.property('type', 'depth-transducer');
msg.should.have.property('depthFeet', 36.41);
msg.should.have.property('depthMeters', 11.10);
});
});
describe('DBT encoding', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('II', {
type: 'depth-transducer',
depthFeet: 36.41,
depthFathoms: 5.99,
depthMeters: 11.10
});
nmeaMsg.should.equal("$IIDBT,36.41,f,11.10,M,5.99,F*25");
});
});

44
test/GGAtest.js Normal file
View File

@@ -0,0 +1,44 @@
var should = require('should');
describe('GGA ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$IIGGA,123519,4807.04,N,1131.00,E,1,8,0.9,545.9,M,46.9,M,,*52");
msg.should.have.property('type', 'fix');
msg.should.have.property('sentence', 'GGA');
msg.should.have.property('talker_id', 'II');
msg.should.have.property('timestamp', '123519');
msg.should.have.property('lat', '4807.04');
msg.should.have.property('latPole', 'N');
msg.should.have.property('lon', '1131.00');
msg.should.have.property('lonPole', 'E');
msg.should.have.property('fixType', 'fix');
msg.should.have.property('numSat', 8);
msg.should.have.property('horDilution', 0.9);
msg.should.have.property('alt', 545.9);
msg.should.have.property('altUnit', 'M');
msg.should.have.property('geoidalSep', 46.9);
msg.should.have.property('geoidalSepUnit', 'M');
});
});
describe('GGA', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('II', {
type: 'fix',
timestamp: new Date(Date.UTC(2013, 1, 1, 12, 35, 19)),
lat: 4807.04,
latPole: 'N',
lon: 1131.00,
lonPole: 'E',
fixType: 'fix',
numSat: 8,
horDilution: 0.9,
alt: 545.9,
altUnit: 'M',
geoidalSep: 46.9,
geoidalSepUnit: 'M'
});
nmeaMsg.should.equal("$IIGGA,123519,4807.04,N,1131.00,E,1,8,0.9,545.9,M,46.9,M,,*52");
});
});

29
test/GLLtest.js Normal file
View File

@@ -0,0 +1,29 @@
var should = require('should');
describe('GLL ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPGLL,6005.068,N,02332.341,E,095601,A,D*42");
msg.should.have.property('type', 'geo-position');
msg.should.have.property('sentence', 'GLL');
msg.should.have.property('lat', '6005.068');
msg.should.have.property('latPole', 'N');
msg.should.have.property('lon', '02332.341');
msg.should.have.property('lonPole', 'E');
msg.should.have.property('status', 'valid');
});
});
describe('GLL', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('II', {
type: 'geo-position',
lat: 6005.06,
latPole: 'N',
lon: 2332.34,
lonPole: 'E',
timestamp: new Date(2013, 4, 1, 21,17 - new Date().getTimezoneOffset(),22),
status: 'valid'
});
nmeaMsg.should.equal("$IIGLL,6005.06,N,2332.34,E,211722,A,D*62");
});
});

9
test/GRMTtest.js Normal file
View File

@@ -0,0 +1,9 @@
var should = require('should');
describe('GRMT ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$PGRMT,GPS19x-HVS Software Version 2.20,,,,,,,,*6F");
msg.should.have.property('type', 'sensor-information');
msg.should.have.property('sentence', 'GRMT');
});
});

9
test/GSAtest.js Normal file
View File

@@ -0,0 +1,9 @@
var should = require('should');
describe('GSV ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPGSA,A,3,12,05,25,29,,,,,,,,,9.4,7.6,5.6*37");
msg.should.have.property('type', 'active-satellites');
msg.should.have.property('sentence', 'GSA');
});
});

9
test/GSVtest.js Normal file
View File

@@ -0,0 +1,9 @@
var should = require('should');
describe('GSV ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*2D");
msg.should.have.property('type', 'satellite-list-partial');
msg.should.have.property('sentence', 'GSV');
});
});

19
test/HDMtest.js Normal file
View File

@@ -0,0 +1,19 @@
var should = require('should');
describe('HDM parsing', function () {
it('parse heading', function () {
var msg = require("../nmea.js").parse("$IIHDM,201.5,M*24");
msg.should.have.property('sentence', 'HDM');
msg.should.have.property('heading', 201.5);
});
});
describe('HDM encoding', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('II', {
type: 'heading-info-magnetic',
heading: 201.5
});
nmeaMsg.should.equal("$IIHDM,201.5,M*24");
});
});

19
test/HDTtest.js Normal file
View File

@@ -0,0 +1,19 @@
var should = require('should');
describe('HDT parsing', function () {
it('parse heading', function () {
var msg = require("../nmea.js").parse("$IIHDT,234.2,T*25");
msg.should.have.property('sentence', 'HDT');
msg.should.have.property('heading', 234.2);
});
});
describe('HDT encoding', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('II', {
type: 'heading-info',
heading: 234.2
});
nmeaMsg.should.equal("$IIHDT,234.2,T*25");
});
});

27
test/MWVtest.js Normal file
View File

@@ -0,0 +1,27 @@
var should = require('should');
describe('MWV parsing', function () {
it('parses ok', function () {
var msg = require("../nmea.js").parse("$IIMWV,017,R,02.91,N,A*2F");
msg.should.have.property('sentence', 'MWV');
msg.should.have.property('type', 'wind');
msg.should.have.property('angle', 17);
msg.should.have.property('reference', 'R');
msg.should.have.property('speed', 2.91);
msg.should.have.property('units', 'N');
msg.should.have.property('status', 'A');
});
});
describe('MWV encoding', function () {
it('parses ok', function () {
var nmeaMsg = require("../nmea.js").encode('XX', {
type: 'wind',
angle: 17,
reference: 'R',
speed: 2.91,
units: 'N',
status: 'A'});
nmeaMsg.should.equal("$XXMWV,017.00,R,2.91,N,A*31");
});
});

10
test/RDIDtest.js Normal file
View File

@@ -0,0 +1,10 @@
var should = require('should');
describe('RDID ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$PRDID,-1.31,7.81,47.31*68");
msg.should.have.property('type', 'gyro');
msg.should.have.property('sentence', 'RDID');
});
});

9
test/RMCtest.js Normal file
View File

@@ -0,0 +1,9 @@
var should = require('should');
describe('RMC ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A");
msg.should.have.property('type', 'nav-info');
msg.should.have.property('sentence', 'RMC');
});
});

18
test/ROTtest.js Normal file
View File

@@ -0,0 +1,18 @@
var should = require('should');
describe('ROT ', function () {
it('parses', function () {
var msg = require("../nmea.js").parse("$--ROT,-2.53,A*3F");
msg.should.have.property('type', 'rate-of-turn');
msg.should.have.property('sentence', 'ROT');
msg.should.have.property('rateOfTurn', -2.53);
});
it('encodes', function () {
var msg = require("../nmea.js").encode('--', {
type: 'rate-of-turn',
rateOfTurn: -2.53452
});
msg.should.equal('$--ROT,-2.53,A*3F');
});
});

24
test/VTGtest.js Normal file
View File

@@ -0,0 +1,24 @@
var should = require('should');
describe('VTG parsing', function () {
it('parses ok', function () {
var msg = require("../nmea.js").parse("$IIVTG,210.43,T,210.43,M,5.65,N,,,A*67");
msg.should.have.property('sentence', 'VTG');
msg.should.have.property('type', 'track-info');
msg.should.have.property('trackTrue', 210.43);
msg.should.have.property('trackMagnetic', 210.43);
msg.should.have.property('speedKnots', 5.65);
});
});
describe('VTG encoding', function () {
it('encodes ok', function () {
var nmeaMsg = require("../nmea.js").encode('XX', {
type: 'track-info',
trackTrue: 210.43,
trackMagnetic: 209.43,
speedKnots: 2.91
});
nmeaMsg.should.equal("$XXVTG,210.43,T,209.43,M,2.91,N,,,A*63");
});
});

22
test/helperstest.js Normal file
View File

@@ -0,0 +1,22 @@
var should = require('should');
describe('helpers ', function () {
it('padLeft', function () {
var msg = require("../helpers.js").padLeft("abc", 5, " ");
msg.should.equal(" abc");
});
it('parseDateTime', function () {
// Input = 3rd of April of 2005
var dt = require("../helpers.js").parseDateTime("030405", "112233");
(+dt.getUTCDate()).should.equal(3);
(+dt.getUTCMonth() + 1).should.equal(4);
(+dt.getUTCFullYear()).should.equal(2005);
(+dt.getUTCHours()).should.equal(11);
(+dt.getUTCMinutes()).should.equal(22);
(+dt.getUTCSeconds()).should.equal(33);
});
});

18
test/nmeaTest.js Normal file
View File

@@ -0,0 +1,18 @@
var should = require('should');
describe('Encoding unknown', function () {
it('undefined throws error', function () {
var nmea = require("../nmea.js");
(function(){
nmea.encode(undefined);
}).should.throw("Can not encode undefined, did you forget msg parameter?");
});
it('no type throws error', function () {
var nmea = require("../nmea.js");
(function(){
nmea.encode('II', {type:"foo"});
}).should.throw("No encoder for type:foo");
});
});