import base64ToArrayBuffer from 'base64-arraybuffer'; import moment from 'moment'; import { asciiToBinaryCodedDecimal, base64ToHex, formatAlphaDate, formatAlphaTime, formatCleanNumericValue, formatAlphaWeekday, removeLeadingZeroes, } from './binary'; import { NeedMoreBytesError, ParserError } from './errors'; import { Parser } from './Parser'; import { ParserResult } from './ParserResult'; import type { MeterInterpretationCode } from './ReadStrategy'; import * as Registers from './registers'; export class AlphaA1Parser extends Parser { billingTable: string | undefined; constructor(interpretationCode?: MeterInterpretationCode, billingTable?: string) { super(); this.interpretationCode = interpretationCode || 1; this.billingTable = billingTable ?? undefined; } static PAYLOAD_SIZE = 233; assertIfFirstByteIsNonzero(arrayBuffer) { if (arrayBuffer[0]) { throw new ParserError('primer byte no es cero'); } } isPayloadIncomplete(arrayBuffer) { return arrayBuffer.length < AlphaA1Parser.PAYLOAD_SIZE; } isPreviousBillingTable() { const CURRENT_BILLING_TABLE = '00'; return this.billingTable !== CURRENT_BILLING_TABLE; } parseReadingStrategyNine(arrayBuffer, aBase64String) { const result = new ParserResult(); result.add( Registers.SerialNumberModel, removeLeadingZeroes(asciiToBinaryCodedDecimal(arrayBuffer.slice(2, 7))), ); result.add(Registers.ReadAtModel, moment().format()); result.add(Registers.HexPayloadModel, base64ToHex(aBase64String)); return result; } parseReadingStrategyOne(arrayBuffer) { const result = new ParserResult(); const isPreviousBillingTable = this.isPreviousBillingTable(); result.add( Registers.SerialNumberModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(2, 7)), 0), ); // eslint-disable-next-line no-bitwise result.add(Registers.WeekdayNowModel, formatAlphaWeekday(arrayBuffer[7] >> 5)); const DATE = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(9, 12))); result.add(Registers.DateNowModel, DATE); result.add( Registers.TimeNowModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(12, 15)), DATE), ); result.add( Registers.DemandResetCounterModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(15, 16)), 0), ); result.add( Registers.KhModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(16, 19)), 3), ); result.add( isPreviousBillingTable ? Registers.TotalActiveEnergyImportPreviousModel : Registers.TotalActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(21, 24)), 1), ); result.add( isPreviousBillingTable ? Registers.Tariff1ActiveEnergyImportPreviousModel : Registers.Tariff1ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(24, 27)), 1), ); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumDemandImportPreviousModel : Registers.Tariff1MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(27, 30)), 3), ); result.add( isPreviousBillingTable ? Registers.Tariff1CumulativeMaximumDemandImportPreviousModel : Registers.Tariff1CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(30, 33)), 3), ); const Tariff1Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(33, 36))); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumDemandImportDatePreviousModel : Registers.Tariff1MaximumDemandImportDateModel, Tariff1Date, ); result.add( Registers.Tariff1MaximumDemandImportTimePreviousModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(36, 38)), Tariff1Date), ); result.add( isPreviousBillingTable ? Registers.Tariff2ActiveEnergyImportPreviousModel : Registers.Tariff2ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(38, 41)), 1), ); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportPreviousModel : Registers.Tariff2MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(41, 44)), 3), ); result.add( isPreviousBillingTable ? Registers.Tariff2CumulativeMaximumDemandImportPreviousModel : Registers.Tariff2CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(44, 47)), 3), ); const Tariff2Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(47, 50))); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportDatePreviousModel : Registers.Tariff2MaximumDemandImportDateModel, Tariff2Date, ); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportTimePreviousModel : Registers.Tariff2MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(50, 52)), Tariff2Date), ); result.add( isPreviousBillingTable ? Registers.Tariff3ActiveEnergyImportPreviousModel : Registers.Tariff3ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(52, 55)), 1), ); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportPreviousModel : Registers.Tariff3MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(55, 58)), 3), ); result.add( isPreviousBillingTable ? Registers.Tariff3CumulativeMaximumDemandImportPreviousModel : Registers.Tariff3CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(58, 61)), 3), ); const Tariff3Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(61, 64))); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportDatePreviousModel : Registers.Tariff3MaximumDemandImportDateModel, Tariff3Date, ); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportTimePreviousModel : Registers.Tariff3MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(64, 66)), Tariff3Date), ); result.add( isPreviousBillingTable ? Registers.Tariff4ActiveEnergyImportPreviousModel : Registers.Tariff4ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(66, 69)), 1), ); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportPreviousModel : Registers.Tariff4MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(69, 72)), 3), ); result.add( isPreviousBillingTable ? Registers.Tariff4CumulativeMaximumDemandImportPreviousModel : Registers.Tariff4CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(72, 75)), 3), ); const Tariff4Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(75, 78))); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportDatePreviousModel : Registers.Tariff4MaximumDemandImportDateModel, Tariff4Date, ); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportTimePreviousModel : Registers.Tariff4MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(78, 80)), Tariff4Date), ); result.add( isPreviousBillingTable ? Registers.TotalReactiveEnergyImportPreviousModel : Registers.TotalReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(80, 83)), 1), ); return result; } parseReadingStrategyTwo(arrayBuffer) { const result = new ParserResult(); const isPreviousBillingTable = this.isPreviousBillingTable(); result.add( Registers.SerialNumberModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(2, 7)), 0), ); // eslint-disable-next-line no-bitwise result.add(Registers.WeekdayNowModel, formatAlphaWeekday(arrayBuffer[7] >> 5)); const DATE = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(9, 12))); result.add(Registers.DateNowModel, DATE); result.add( Registers.TimeNowModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(12, 15)), DATE), ); result.add( Registers.DemandResetCounterModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(15, 16)), 0), ); result.add( Registers.KhModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(16, 19)), 3), ); const decimalsEnergy = Number(asciiToBinaryCodedDecimal(arrayBuffer.slice(19, 20))) + 6; const DPLCOD = Number(asciiToBinaryCodedDecimal(arrayBuffer.slice(20, 21))); result.add( isPreviousBillingTable ? Registers.Tariff1ActiveEnergyImportPreviousModel : Registers.Tariff1ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(21, 28)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumDemandImportPreviousModel : Registers.Tariff1MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(28, 31)), DPLCOD), ); const tariff1DatePrevious = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(31, 34))); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumDemandImportDatePreviousModel : Registers.Tariff1MaximumDemandImportDateModel, tariff1DatePrevious, ); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumDemandImportTimePreviousModel : Registers.Tariff1MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(34, 36)), tariff1DatePrevious), ); result.add( isPreviousBillingTable ? Registers.Tariff1CumulativeMaximumDemandImportPreviousModel : Registers.Tariff1CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(36, 39)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff2ActiveEnergyImportPreviousModel : Registers.Tariff2ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(42, 49)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportPreviousModel : Registers.Tariff2MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(49, 52)), DPLCOD), ); const tariff2DatePrevious = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(52, 55))); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportDatePreviousModel : Registers.Tariff2MaximumDemandImportDateModel, tariff2DatePrevious, ); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumDemandImportTimePreviousModel : Registers.Tariff2MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(55, 57)), tariff2DatePrevious), ); result.add( isPreviousBillingTable ? Registers.Tariff2CumulativeMaximumDemandImportPreviousModel : Registers.Tariff2CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(57, 60)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff3ActiveEnergyImportPreviousModel : Registers.Tariff3ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(63, 70)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportPreviousModel : Registers.Tariff3MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(70, 73)), DPLCOD), ); const tariff3DatePrevious = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(73, 76))); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportDatePreviousModel : Registers.Tariff3MaximumDemandImportDateModel, tariff3DatePrevious, ); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumDemandImportTimePreviousModel : Registers.Tariff3MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(76, 78)), tariff3DatePrevious), ); result.add( isPreviousBillingTable ? Registers.Tariff3CumulativeMaximumDemandImportPreviousModel : Registers.Tariff3CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(78, 81)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff4ActiveEnergyImportPreviousModel : Registers.Tariff4ActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(84, 91)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportPreviousModel : Registers.Tariff4MaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(91, 94)), DPLCOD), ); const tariff4DatePrevious = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(94, 97))); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportDatePreviousModel : Registers.Tariff4MaximumDemandImportDateModel, tariff4DatePrevious, ); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumDemandImportTimePreviousModel : Registers.Tariff4MaximumDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(97, 99)), tariff4DatePrevious), ); result.add( isPreviousBillingTable ? Registers.Tariff4CumulativeMaximumDemandImportPreviousModel : Registers.Tariff4CumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(99, 102)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff1ReactiveEnergyImportPreviousModel : Registers.Tariff1ReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(105, 112)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff1ReactiveMaximumDemandImportPreviousModel : Registers.Tariff1ReactiveMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(112, 115)), DPLCOD), ); const tariff1Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(115, 118))); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumReactiveDemandImportDatePreviousModel : Registers.Tariff1MaximumReactiveDemandImportDateModel, tariff1Date, ); result.add( isPreviousBillingTable ? Registers.Tariff1MaximumReactiveDemandImportTimePreviousModel : Registers.Tariff1MaximumReactiveDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(118, 120)), tariff1Date), ); result.add( isPreviousBillingTable ? Registers.Tariff1ReactiveCumulativeMaximumDemandImportPreviousModel : Registers.Tariff1ReactiveCumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(120, 123)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff2ReactiveEnergyImportPreviousModel : Registers.Tariff2ReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(126, 133)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff2ReactiveMaximumDemandImportPreviousModel : Registers.Tariff2ReactiveMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(133, 136)), DPLCOD), ); const tariff2Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(136, 139))); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumReactiveDemandImportDatePreviousModel : Registers.Tariff2MaximumReactiveDemandImportDateModel, tariff2Date, ); result.add( isPreviousBillingTable ? Registers.Tariff2MaximumReactiveDemandImportTimePreviousModel : Registers.Tariff2MaximumReactiveDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(139, 141)), tariff2Date), ); result.add( isPreviousBillingTable ? Registers.Tariff2ReactiveCumulativeMaximumDemandImportPreviousModel : Registers.Tariff2ReactiveCumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(141, 144)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff3ReactiveEnergyImportPreviousModel : Registers.Tariff3ReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(147, 154)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff3ReactiveMaximumDemandImportPreviousModel : Registers.Tariff3ReactiveMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(154, 157)), DPLCOD), ); const tariff3Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(157, 160))); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumReactiveDemandImportDatePreviousModel : Registers.Tariff3MaximumReactiveDemandImportDateModel, tariff3Date, ); result.add( isPreviousBillingTable ? Registers.Tariff3MaximumReactiveDemandImportTimePreviousModel : Registers.Tariff3MaximumReactiveDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(160, 162)), tariff3Date), ); result.add( isPreviousBillingTable ? Registers.Tariff3ReactiveCumulativeMaximumDemandImportPreviousModel : Registers.Tariff3ReactiveCumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(162, 165)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.Tariff4ReactiveEnergyImportPreviousModel : Registers.Tariff4ReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(168, 175)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.Tariff4ReactiveMaximumDemandImportPreviousModel : Registers.Tariff4ReactiveMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(175, 178)), DPLCOD), ); const tariff4Date = formatAlphaDate(asciiToBinaryCodedDecimal(arrayBuffer.slice(178, 181))); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumReactiveDemandImportDatePreviousModel : Registers.Tariff4MaximumReactiveDemandImportDateModel, tariff4Date, ); result.add( isPreviousBillingTable ? Registers.Tariff4MaximumReactiveDemandImportTimePreviousModel : Registers.Tariff4MaximumReactiveDemandImportTimeModel, formatAlphaTime(asciiToBinaryCodedDecimal(arrayBuffer.slice(181, 183)), tariff4Date), ); result.add( isPreviousBillingTable ? Registers.Tariff4ReactiveCumulativeMaximumDemandImportPreviousModel : Registers.Tariff4ReactiveCumulativeMaximumDemandImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(183, 186)), DPLCOD), ); result.add( isPreviousBillingTable ? Registers.TotalCapacitiveReactiveEnergyExportPreviousModel : Registers.TotalCapacitiveReactiveEnergyExportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(186, 196)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.TotalInductiveReactiveEnergyExportPreviousModel : Registers.TotalInductiveReactiveEnergyExportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(196, 203)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.TotalCapacitiveReactiveEnergyImportPreviousModel : Registers.TotalCapacitiveReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(203, 210)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.TotalInductiveReactiveEnergyImportPreviousModel : Registers.TotalInductiveReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(210, 217)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.TotalActiveEnergyImportPreviousModel : Registers.TotalActiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(217, 224)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.TotalReactiveEnergyImportPreviousModel : Registers.TotalReactiveEnergyImportModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(224, 231)), decimalsEnergy), ); result.add( isPreviousBillingTable ? Registers.PowerFactorPreviousModel : Registers.PowerFactorModel, formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(231, 233)), 3), ); return result; } parseBody(arrayBuffer, aBase64String): ParserResult { const incomplete = this.isPayloadIncomplete(arrayBuffer); if (incomplete) { throw new NeedMoreBytesError(); } switch (this.interpretationCode) { case 1: return this.parseReadingStrategyOne(arrayBuffer); case 2: return this.parseReadingStrategyTwo(arrayBuffer); case 9: return this.parseReadingStrategyNine(arrayBuffer, aBase64String); default: throw new ParserError(`Unidentified reading interpretation`); } } getMeterNumber(arrayBuffer) { return formatCleanNumericValue(asciiToBinaryCodedDecimal(arrayBuffer.slice(2, 7)), 0); } parse(aBase64String: string, recoverMeterNumber?: Function): ParserResult { const arrayBuffer = new Uint8Array(base64ToArrayBuffer.decode(aBase64String)); if (arrayBuffer.length < 2) { throw new NeedMoreBytesError(); } this.assertIfFirstByteIsNonzero(arrayBuffer); if (recoverMeterNumber) { return recoverMeterNumber(this.getMeterNumber(arrayBuffer)); } const modelByte = arrayBuffer[1]; if (modelByte === 1 || modelByte === 0) { return this.parseBody(arrayBuffer, aBase64String); } else { throw new ParserError(`Byte model no identificado`); } } }