agn-utils/binary-package-parser/rap-parser.js

93 lines
3.0 KiB
JavaScript

'use strict';
const assert = require('assert'),
bitUtil = require('bit-util');
const GPS_13 = 0x13;
/**
* RAPParser is responsible for parsing RAP binary records
*/
class RAPParser {
constructor() {
// Using these local vars to avoid GC for more memory efficency
this._hour = 0;
this._minute = 0;
this._second = 0;
this._year = 0;
this._month = 0;
this._day = 0;
this._byte = 0;
}
/**
* Parse RAP binary response package
* @param {*} rapPkg The binary package data in Buffer. Structure: <Cmd><Len><Data>, Cmd = 0x13
* @returns a GPS data object
*/
parse(rapPkg) {
let record;
if (rapPkg && rapPkg[0] >= GPS_13) {
assert.ok(Buffer.isBuffer(rapPkg), 'rapPkg argument must be an instance of Buffer'); // prettier-ignore
// Byte 19th, if bit 4 is set -> has GPS Fix
if (rapPkg[18] && bitUtil.isBitOn(rapPkg[18], 4)) {
record = {};
let offset = 2; // Add 2 to skip the data package header <Cmd><Len> to read the data
record.lat = rapPkg.readInt32LE(offset) * 1e-5; offset += 4;
record.lon = rapPkg.readInt32LE(offset) * 1e-5; offset += 4;
record.speed = rapPkg.readUInt8(offset); offset += 1;
// GPS Direction in 2 Degree Increasements
record.head = rapPkg.readUInt8(offset) << 1; offset += 1;
this._hour = rapPkg.readUInt8(offset); offset += 1;
this._minute = rapPkg.readUInt8(offset); offset += 1;
this._second = rapPkg.readUInt8(offset); offset += 1;
this._year = 2000 + rapPkg.readUInt8(offset); offset += 1;
this._month = rapPkg.readUInt8(offset); offset += 1;
this._day = rapPkg.readUInt8(offset); offset += 1;
// Month in JS 0 => 11
record.gdt = new Date(Date.UTC(this._year, this._month - 1, this._day, this._hour, this._minute, this._second));
record.inputs = 0;
// Cmd 0x13. Byte 19th
this._byte = rapPkg.readUInt8(offset); offset += 1;
// Cmd 0x13. Byte 19th. Bits 0-3: numbers of GPS setellites
record.sats = bitUtil.extractBits(this._byte, 4, 0);
// Cmd 0x13. Byte 20th
this._byte = rapPkg.readUInt8(offset);
// Cmd 0x13. Byte 20th. Bit 3: Inputs+
if (bitUtil.isBitOn(this._byte, 3)) {
// Cmd 0x13. Byte 20th. Bit 0: 1 => extra inputs (21-24)
offset += bitUtil.isBitOn(this._byte, 0) ? 4 : 1;
// Skip reading Odometer data
// Cmd 0x13. Byte 21th/25th
this._byte = rapPkg.readUInt8(offset); offset += 1;
if (bitUtil.isBitOn(this._byte, 0)) {
// Cmd 0x13. Byte 22th/25th: Whether Digital input state present
this._byte = rapPkg.readUInt8(offset); offset += 1;
// Digital inputs (Up to 5, use only input 1 for Spray on/off, 0: spray on and 1 is off)
// Check Input 1 (bit 0) for spray on/off
record.inputs = bitUtil.isBitOn(this._byte, 0) ? 0 : 1;
}
}
}
}
return record;
}
}
module.exports = RAPParser;