UNPKG

@signalk/nmea0183-utilities

Version:

Various utilities for transforming NMEA0183 units into SI units for use in SK.

257 lines (214 loc) 6.68 kB
'use strict'; (function () { var utils = {}; utils.RATIOS = { // DISTANCE NM_IN_KM: 1.852, KM_IN_NM: 0.539956803, // SPEED // Knots KNOTS_IN_MS: 0.514444, KNOTS_IN_MPH: 1.150779, KNOTS_IN_KPH: 1.852, // MPH MPH_IN_MS: 0.44704, MPH_IN_KPH: 1.609344, MPH_IN_KNOTS: 0.868976, // KPH KPH_IN_MS: 0.277778, KPH_IN_MPH: 0.621371, KPH_IN_KNOTS: 0.539957, // MS MS_IN_KPH: 3.6, MS_IN_MPH: 2.236936, MS_IN_KNOTS: 1.943844, // DEGREE DEG_IN_RAD: 0.0174532925, RAD_IN_DEG: 57.2957795, // TEMPERATURES // Celcius CELCIUS_IN_KELVIN: 273.15, }; function checksum(sentencePart) { let check = 0; for (let i = 1; i < sentencePart.length; i++) { check = check ^ sentencePart.charCodeAt(i); }; return check; } exports.valid = function (sentence, validateChecksum) { sentence = String(sentence).trim(); if (sentence === "") { return false; } var validateChecksum = typeof validateChecksum === 'undefined' || validateChecksum if ((sentence.charAt(0) == '$' || sentence.charAt(0) == '!') && (validateChecksum == false || sentence.charAt(sentence.length - 3) == '*')) { if (validateChecksum) { let split = sentence.split('*'); return (parseInt(split[1], 16) == checksum(split[0])); } else { return true } } return false; }; exports.appendChecksum = function (sentence) { let split = String(sentence).trim().split('*'); if (split.length === 1) { if (split[0].charAt(0) == '$' || split[0].charAt(0) == '!') { return split[0].concat('*').concat(checksum(split[0]).toString(16).padStart(2, '0').toUpperCase()); } } return sentence; }; exports.source = function (sentence) { return { type: 'NMEA0183', label: 'signalk-parser-nmea0183', sentence: sentence || '' }; }; exports.transform = function (value, inputFormat, outputFormat) { value = exports.float(value); inputFormat = inputFormat.toLowerCase(); outputFormat = outputFormat.toLowerCase(); if (inputFormat === outputFormat) { return value; } // KM if (inputFormat == 'km') { if (outputFormat == 'nm') return value / utils.RATIOS.NM_IN_KM; } // NM if (inputFormat == 'nm') { if (outputFormat == 'km') return value / utils.RATIOS.KM_IN_NM; if (outputFormat == 'm') return value * 1000 / utils.RATIOS.KM_IN_NM; } // KNOTS if (inputFormat == 'knots') { if (outputFormat == 'kph') return value / utils.RATIOS.KPH_IN_KNOTS; if (outputFormat == 'ms') return value / utils.RATIOS.MS_IN_KNOTS; if (outputFormat == 'mph') return value / utils.RATIOS.MPH_IN_KNOTS; } // KPH if (inputFormat == 'kph') { if (outputFormat == 'knots') return value / utils.RATIOS.KNOTS_IN_KPH; if (outputFormat == 'ms') return value / utils.RATIOS.MS_IN_KPH; if (outputFormat == 'mph') return value / utils.RATIOS.MPH_IN_KPH; } // MPH if (inputFormat == 'mph') { if (outputFormat == 'knots') return value / utils.RATIOS.KNOTS_IN_MPH; if (outputFormat == 'ms') return value / utils.RATIOS.MS_IN_MPH; if (outputFormat == 'kph') return value / utils.RATIOS.KPH_IN_MPH; } // MS if (inputFormat == 'ms') { if (outputFormat == 'knots') return value / utils.RATIOS.KNOTS_IN_MS; if (outputFormat == 'mph') return value / utils.RATIOS.MPH_IN_MS; if (outputFormat == 'kph') return value / utils.RATIOS.KPH_IN_MS; } // ANGLES if (inputFormat == 'deg') { if (outputFormat == 'rad') return value / utils.RATIOS.RAD_IN_DEG; } if (inputFormat == 'rad') { if (outputFormat == 'deg') return value / utils.RATIOS.DEG_IN_RAD; } if (inputFormat == 'c') { if (outputFormat == 'k') return value + utils.RATIOS.CELCIUS_IN_KELVIN; } if (inputFormat == 'k') { if (outputFormat == 'c') return value - utils.RATIOS.CELCIUS_IN_KELVIN; } // Just return input if input/output formats are not recognised. return value; }; exports.magneticVariaton = function (degrees, pole) { pole = pole.toUpperCase(); degrees = this.float(degrees); if (pole == "S" || pole == "W") { degrees *= -1; } return degrees; }; exports.timestamp = function (time, date) { /* TIME (UTC) */ var hours, minutes, seconds, year, month, day; if (time) { hours = this.int(time.slice(0, 2), true); minutes = this.int(time.slice(2, 4), true); seconds = this.int(time.slice(4, 6), true); } else { var dt = new Date(); hours = dt.getUTCHours(); minutes = dt.getUTCMinutes(); seconds = dt.getUTCSeconds(); } /* DATE (UTC) */ if (date) { var year, month, day; day = this.int(date.slice(0, 2), true); month = this.int(date.slice(2, 4), true); year = this.int(date.slice(-2)); year = 2000 + year; } else { var dt = new Date(); year = dt.getUTCFullYear(); month = dt.getUTCMonth(); day = dt.getUTCDate(); } /* construct */ var d = new Date(Date.UTC(year, (month - 1), day, hours, minutes, seconds)); return d.toISOString(); }; exports.coordinate = function (value, pole) { // N 5222.3277 should be read as 52°22.3277' // E 454.5824 should be read as 4°54.5824' // // 1. split at . // 2. last two characters of split[0] (.slice(-2)) + everything after . (split[1]) are the minutes // 3. degrees: split[0][a] // 4. minutes: split[0][b] + '.' + split[1] // // 52°22'19.662'' N -> 52.372128333 // 4°54'34.944'' E -> 4.909706667 // S & W should be negative. pole = pole.toUpperCase(); var split = value.split('.'); var degrees = this.float(split[0].slice(0, -2)); var minsec = this.float(split[0].slice(-2) + '.' + split[1]); var decimal = this.float(degrees + (minsec / 60)); if (pole == "S" || pole == "W") { decimal *= -1; } return exports.float(decimal); }; exports.zero = function (n) { if (this.float(n) < 10) { return "0" + n; } else { return "" + n; } }; exports.int = function (n) { if (("" + n).trim() === '') { return 0; } else { return parseInt(n, 10); } }; exports.integer = function (n) { return exports.int(n); }; exports.float = function (n) { if (("" + n).trim() === '') { return 0.0; } else { return parseFloat(n); } }; exports.double = function (n) { return exports.float(n); }; })();