UNPKG

js-aprs-fap

Version:

NodeJs library for parsing APRS packets.

238 lines 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PacketFactory = void 0; const ConversionConstantEnum_1 = require("./ConversionConstantEnum"); const TimeFormatEnum_1 = require("./TimeFormatEnum"); const NmeaSourceEnum_1 = require("./NmeaSourceEnum"); const CompressionOriginEnum_1 = require("./CompressionOriginEnum"); class PacketFactory { makeTimestamp(timestamp, timeFormat) { let date; if (timestamp == 0) { date = new Date(); } else { date = new Date(timestamp); } switch (timeFormat) { case TimeFormatEnum_1.TimeFormatEnum.DHM: return String(date.getUTCDate()).padStart(2, "0") + String(date.getUTCHours()).padStart(2, "0") + String(date.getUTCMinutes()).padStart(2, "0") + 'z'; case TimeFormatEnum_1.TimeFormatEnum.HMS: return String(date.getUTCHours()).padStart(2, "0") + String(date.getUTCMinutes()).padStart(2, "0") + String(date.getUTCSeconds()).padStart(2, "0") + "h"; default: throw new Error("Unsupported time format."); } } makePosition(data) { let retVal = ""; try { retVal = this.buildData(data); } catch (e) { throw e; } if (data.timestamp && data.timestamp != null) { if (data.isMessagingEnabled && data.isMessagingEnabled == true) { retVal = `@${retVal}`; } else { retVal = `/${retVal}`; } } else { if (data.isMessagingEnabled && data.isMessagingEnabled == true) { retVal = `=${retVal}`; } else { retVal = `!${retVal}`; } } return retVal; } buildData(data) { if (!data || data == null) { throw new Error("No data provided."); } if (data.ambiguity && data.ambiguity != null && data.ambiguity != undefined) { data.isUseDao = false; } if (!data.latitude || data.latitude == null || data.latitude < -89.99999 || data.latitude > 89.99999 || !data.longitude || data.longitude == null || data.longitude < -179.99999 || data.longitude > 179.99999) { throw new Error("Invalid location."); } let symbolTable = ""; let symbolCode = ""; if (data.symbols == null || data.symbols == "") { symbolTable = "/"; symbolCode = "/"; } else if (/^([\/\\A-Z0-9])([\x21-\x7b\x7d])$/.test(data.symbols)) { [, symbolTable, symbolCode] = data.symbols.match(/^([\/\\A-Z0-9])([\x21-\x7b\x7d])$/); } else { throw new Error("Invalid symbols."); } let retVal = ""; let latMinDao; let lonMinDao; if (data.isUseCompression == true) { let lat = 380926 * (90 - data.latitude); let lon = 190463 * (180 + data.longitude); let latString = ""; let lonString = ""; for (let i = 3; i >= 0; i--) { let value = Math.floor(lat / (91 ** i)); lat = lat % (91 ** i); latString += String.fromCharCode(value + 33); value = Math.floor(lon / (91 ** i)); lon = lon % (91 ** i); lonString += String.fromCharCode(value + 33); } if (isNaN(Number(symbolTable)) == false) { symbolTable = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"][Number(symbolTable)]; } retVal = `${symbolTable}${latString}${lonString}${symbolCode}`; if (data.speed != null && data.speed >= 0 && data.course != null && data.course > 0 && data.course <= 360) { let cVal = Math.floor((data.course + 2) / 4); if (cVal > 89) { cVal = 0; } retVal += String.fromCharCode(cVal + 33); let speedNum = Math.floor((Math.log((data.speed / ConversionConstantEnum_1.ConversionConstantEnum.KNOT_TO_KMH) + 1) / Math.log(1.08)) + 0.5); if (speedNum > 89) { speedNum = 89; } retVal += String.fromCharCode(speedNum + 33); } else { retVal += " "; } const compressionType = String.fromCharCode(parseInt("001" + NmeaSourceEnum_1.NmeaSourceEnum.OTHER + CompressionOriginEnum_1.CompressionOriginEnum.COMPRESSED, 2) + 33); retVal += compressionType; } else { let latDir = "N"; let lonDir = "E"; let latitude = data.latitude; let longitude = data.longitude; if (latitude && latitude != null && latitude < 0.0) { latitude = latitude * -1; latDir = "S"; } let latDegrees = Math.floor(latitude); let latMin = (latitude - latDegrees) * 60; let latMinStr; if (data.isUseDao != null && data.isUseDao == true) { latMinStr = (latMin * 10000).toFixed(0).padStart(6, "0"); latMinDao = latMinStr.substring(4, 6); } else { latMinStr = String((latMin * 100).toFixed(0)).padStart(4, "0"); } if (/^60/.test(latMinStr)) { latMinStr = "5999"; latMinDao = "99"; } let latString = String(latDegrees).padStart(2, "0") + String(latMinStr).substring(0, 2).padStart(2, "0") + "." + String(latMinStr).substring(2, 4); if (longitude && longitude != null && longitude < 0.0) { longitude = longitude * -1; lonDir = "W"; } let lonDegrees = Math.floor(longitude); let lonMin = (longitude - lonDegrees) * 60; let lonMinStr; if (data.isUseDao != null && data.isUseDao == true) { lonMinStr = String((lonMin * 10000).toFixed(0)).padStart(6, "0"); lonMinDao = lonMinStr.substring(4, 6); } else { lonMinStr = String((lonMin * 100).toFixed(0)).padStart(4, "0"); } if (/^60/.test(lonMinStr)) { lonMinStr = "5999"; lonMinDao = "99"; } let lonString = `${String(lonDegrees).padStart(3, "0")}${String(lonMinStr).substring(0, 2)}.${String(lonMinStr).substring(2, 4)}`; if (data.ambiguity && data.ambiguity > 0 && data.ambiguity <= 4) { if (data.ambiguity <= 2) { latString = latString.substring(0, 7 - data.ambiguity).padEnd(7, " "); lonString = lonString.substring(0, 8 - data.ambiguity).padEnd(8, " "); } else if (data.ambiguity == 3) { latString = `${latString.substring(0, 3)} . `; lonString = `${lonString.substring(0, 4)} . `; } else if (data.ambiguity == 4) { latString = `${latString.substring(0, 2)} . `; lonString = `${lonString.substring(0, 3)} . `; } } retVal += `${latString}${latDir}${symbolTable}${lonString}${lonDir}${symbolCode}`; let course = data.course; let speed = data.speed; if (course && course != null && course >= 0 && speed && speed != null && speed >= 0) { speed = speed / ConversionConstantEnum_1.ConversionConstantEnum.KNOT_TO_KMH; if (speed > 999) { speed = 999; } if (course > 360) { course = 0; } retVal += `${String(course).padStart(3, "0")}/${String(speed).padStart(3, "0")}`; } } if (data.altitude && data.altitude != null) { let altitude = data.altitude / ConversionConstantEnum_1.ConversionConstantEnum.FEET_TO_METERS; if (altitude >= 0) { retVal += `/A=${String(altitude.toFixed(0)).padStart(6, "0")}`; } else { retVal += `/A=-${Math.abs(altitude).toFixed(0).padStart(5, "0")}`; } } if (!!data.comment) { retVal += data.comment; } if (data.isUseCompression == false && data.isUseDao != null && data.isUseDao == true) { retVal += '!w' + String.fromCharCode((Math.floor(Number(latMinDao)) / 1.1 + 0.5) + 33) + String.fromCharCode((Math.floor(Number(lonMinDao)) / 1.1 + 0.5) + 33) + '!'; } if (data.timestamp != null) { let timestamp = data.timestamp; if (/^\d+$/.test(timestamp.toString()) == false) { throw new Error("Timestamp must be numeric."); } let now = new Date().getTime(); if (timestamp == 0) { timestamp = now; } let age = now - timestamp; if (age < -3610) { throw new Error("Timestamp too far in the futre."); } else if (age < 84600) { retVal = `${this.makeTimestamp(timestamp, TimeFormatEnum_1.TimeFormatEnum.HMS)}${retVal}`; } else if (age < 2419200) { retVal = `${this.makeTimestamp(timestamp, TimeFormatEnum_1.TimeFormatEnum.DHM)}${retVal}`; } else { throw new Error("Timestamp too far in the past."); } } return retVal; } } exports.PacketFactory = PacketFactory; //# sourceMappingURL=PacketFactory.js.map