import { createErrorFromCode, SFPToolboxError, SFPToolboxErrorCode } from '../error/error'; import { ElsterParser } from './ElsterParser'; import { NeedMoreBytesError, ParserError } from './errors'; import type { ParserResult } from './ParserResult'; import base64 from 'base-64'; import type { ReadRegister } from './registers'; import type { ReadStrategy } from './ReadStrategy'; import { MeterFamilyCode } from './MeterFamilies'; import type { Parser } from './Parser'; import { HexingParser } from './HexingParser'; import { IskraParser } from './IskraParser'; import { AlphaA1Parser } from './AlphaA1Parser'; import { AlphaA3Parser } from './AlphaA3Parser'; import { HX110HexingParser } from './HX110HexingParser'; import { HXE310AndHXF300HexingParser } from './HXE310AndHXF300HexingParser'; import { HolleyParser } from './HolleyParser'; export class ReadingClerk { resolve: (result: ReadRegister[]) => void; reject: (error: SFPToolboxError) => void; readingString: string; result: null | ParserResult; hasResolved: boolean; parser: Parser; onFirstByteCallback: Function; recoverMeterNumber?: Function | undefined; constructor( resolver: (result: ReadRegister[]) => void, rejecter: (error: SFPToolboxError) => void, onFirstByteCallback: Function, readStrategy: ReadStrategy, recoverMeterNumber?: Function | undefined, ) { this.resolve = (...args) => { if (!this.hasResolved) { resolver(...args); } }; this.reject = (...args) => { if (!this.hasResolved) { rejecter(...args); } }; this.readingString = ''; this.result = null; this.hasResolved = false; this.onFirstByteCallback = onFirstByteCallback; this.parser = this.parserFor(readStrategy); this.recoverMeterNumber = recoverMeterNumber; } parserFor(readStrategy: ReadStrategy): Parser { if (readStrategy.meterFamily.code === MeterFamilyCode.Hexing) { return new HexingParser(readStrategy.interpretationCode); } else if (readStrategy.meterFamily.code === MeterFamilyCode.HX110Hexing) { return new HX110HexingParser(readStrategy.interpretationCode); } else if (readStrategy.meterFamily.code === MeterFamilyCode.HXE310AndHXF300Hexing) { return new HXE310AndHXF300HexingParser(readStrategy.interpretationCode); } else if (readStrategy.meterFamily.code === MeterFamilyCode.Elster) { return new ElsterParser(readStrategy.interpretationCode); } else if (readStrategy.meterFamily.code === MeterFamilyCode.Iskra) { return new IskraParser(readStrategy.interpretationCode); } else if (readStrategy.meterFamily.code === MeterFamilyCode.AlphaA1) { return new AlphaA1Parser(readStrategy.interpretationCode, readStrategy.billingTable); } else if (readStrategy.meterFamily.code === MeterFamilyCode.AlphaA3) { return new AlphaA3Parser(readStrategy.interpretationCode, readStrategy.billingTable); } else if (readStrategy.meterFamily.code === MeterFamilyCode.Holley) { return new HolleyParser(readStrategy.interpretationCode); } else { throw new Error('Unknown meter family'); } } appendString(aString: string) { if (this.hasResolved) { // Early return if it has already resolved return; } if (!this.getString()) { this.onFirstByteCallback?.(); } try { this.readingString = base64.encode(base64.decode(this.readingString) + base64.decode(aString)); if (this.recoverMeterNumber) { this.parser.parse(this.readingString, meterNumber => { this.resolve(this.recoverMeterNumber?.(meterNumber)); }); } else { this.result = this.parser.parse(this.readingString); this.resolve(this.result.serialize()); } } catch (error) { if (error instanceof NeedMoreBytesError) { // do nothing } else if (error instanceof ParserError) { this.reject(createErrorFromCode(SFPToolboxErrorCode.ParsingError)); } else { throw error; } } } getString() { return this.readingString; } }