diff --git a/src/output/debug-output.ts b/src/output/debug-output.ts index f9c1dc9..dc41107 100644 --- a/src/output/debug-output.ts +++ b/src/output/debug-output.ts @@ -18,6 +18,9 @@ export default class DebugOutput extends Output { p1Reader.on(P1ReaderEvents.UsageChanged, (result) => { console.log(' - usageChange %s', result.message); }); + p1Reader.on(P1ReaderEvents.GasUsageChanged, (result) => { + console.log(' - gasUsageChange %s', result.message); + }); p1Reader.on(P1ReaderEvents.ErrorMessage, (message) => { console.log(' - errorMessage %s', message); }); diff --git a/src/output/interval-output.ts b/src/output/interval-output.ts index 4cbb407..4ff864c 100644 --- a/src/output/interval-output.ts +++ b/src/output/interval-output.ts @@ -28,6 +28,9 @@ export default class IntervalOutput extends Output { p1Reader.on(P1ReaderEvents.UsageChanged, (result) => { this.emit(P1ReaderEvents.UsageChanged, result); }); + p1Reader.on(P1ReaderEvents.GasUsageChanged, (result) => { + this.emit(P1ReaderEvents.GasUsageChanged, result); + }); this.timer = setInterval(() => { this.publishNextEvent = true; diff --git a/src/output/mqtt-output.ts b/src/output/mqtt-output.ts index 44b97b6..bc90775 100644 --- a/src/output/mqtt-output.ts +++ b/src/output/mqtt-output.ts @@ -34,6 +34,10 @@ export default class MqttOutput extends Output { this.publishUsage(data); }); + p1Reader.on(P1ReaderEvents.GasUsageChanged, (data) => { + this.publishGasUsage(data); + }); + p1Reader.on(P1ReaderEvents.SolarResult, (data) => { this.publishSolar(data); }); @@ -68,6 +72,14 @@ export default class MqttOutput extends Output { this.mqtt?.publish(this.getTopic('usage'), JSON.stringify(message), { qos: 0, retain: false }); } + private publishGasUsage(data: any): void { + const message = data; + message.val = data.currentUsage; + delete message.currentUsage; + message.tc = Date.now(); + this.mqtt?.publish(this.getTopic('gasUsage'), JSON.stringify(message), { qos: 0, retain: false }); + } + private publishData(data: DsmrMessage): void { if (this.config.distinct) { this.config.distinctFields.forEach((element) => { diff --git a/src/p1-reader-events.ts b/src/p1-reader-events.ts index 7271196..53fb322 100644 --- a/src/p1-reader-events.ts +++ b/src/p1-reader-events.ts @@ -14,5 +14,7 @@ export default class P1ReaderEvents { /** Usage change is emitted after the parsed result. It keeps the last result to compare. */ static get UsageChanged(): string { return 'usageChanged'; } + static get GasUsageChanged(): string { return 'gasUsageChanged'; } + static get SolarResult(): string { return 'solar'; } } diff --git a/src/p1-reader.ts b/src/p1-reader.ts index e2c14de..2930d01 100644 --- a/src/p1-reader.ts +++ b/src/p1-reader.ts @@ -5,10 +5,17 @@ import P1Parser from './p1-parser'; import P1ReaderEvents from './p1-reader-events'; import DsmrMessage from './dsmr-message'; import SolarInput from './solar-input'; +import GasValue from './gas-value'; export default class P1Reader extends EventEmitter { private usage: number; + private gasUsage: number; + + private gasReadingTimestamp: number; + + private gasReading: number; + private reading: boolean; private parsing: boolean; @@ -31,6 +38,9 @@ export default class P1Reader extends EventEmitter { constructor() { super(); this.usage = 0; + this.gasUsage = 0; + this.gasReading = 0; + this.gasReadingTimestamp = 0; this.reading = false; this.parsing = false; } @@ -120,6 +130,44 @@ export default class P1Reader extends EventEmitter { }); this.usage = newUsage; } + + /** + * Handle the gas value - this is a bit different from electricity usage, the meter does not + * indicate the actual gas usage in m3/hour but only submits the meter reading every XX minutes + */ + const gas = result.xGas ?? result.gas; + if (gas) { + const currentGasReadingTimestamp = (new Date(((gas as GasValue)).ts ?? 0).getTime() / 1000); + const period = currentGasReadingTimestamp - this.gasReadingTimestamp; + /** + * Report for every new timestamp + */ + if (period) { + const newGasReading = ((gas as GasValue).totalUse ?? 0); + const relative = this.gasReading ? (newGasReading - this.gasReading) : 0; + let newGasUsage = 0; + + /** + * Gas usage in m3 per hour + */ + newGasUsage = relative * (3600 / period); + + /** + * Gas usage is measured in thousands (0.001) - round the numbers + * accordingly + */ + this.emit(P1ReaderEvents.GasUsageChanged, { + previousUsage: parseFloat(this.gasUsage.toFixed(3)), + currentUsage: parseFloat(newGasUsage.toFixed(3)), + relative: parseFloat(relative.toFixed(3)), + message: `Reading increased +${relative} to ${newGasReading}`, + }); + + this.gasReadingTimestamp = currentGasReadingTimestamp; + this.gasReading = newGasReading; + this.gasUsage = newGasUsage; + } + } } public close(): Promise {