UNPKG

iobroker.tibberlink

Version:

links tibber API data to be used in ioBroker

163 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TibberPulse = void 0; const tibber_api_1 = require("tibber-api"); const projectUtils_js_1 = require("./projectUtils.js"); class TibberPulse extends projectUtils_js_1.ProjectUtils { tibberConfig; tibberQuery; tibberFeed; httpQueryUrl; reconnectTime = 6000; maxReconnectTime = 900000; countedFeedDisconnects = 0; lastFeedWarningTime = null; deltaFeedWarningTime = 0; constructor(tibberConfig, adapter) { super(adapter); this.tibberConfig = tibberConfig; this.tibberQuery = new tibber_api_1.TibberQuery(this.tibberConfig); this.tibberFeed = new tibber_api_1.TibberFeed(this.tibberQuery); this.httpQueryUrl = tibberConfig.apiEndpoint.queryUrl; this.addEventHandlerOnFeed(this.tibberFeed); } async connectPulseStream() { try { await this.tibberFeed.connect(); } catch (error) { this.adapter.log.warn(`Error in connectPulseStream: ${error.message}`); } } disconnectPulseStream() { try { this.tibberFeed.removeAllListeners(); this.tibberFeed.close(); } catch (error) { this.adapter.log.warn(`Error on feed close: ${error.message}`); } this.tibberFeed = new tibber_api_1.TibberFeed(new tibber_api_1.TibberQuery(this.tibberConfig)); this.addEventHandlerOnFeed(this.tibberFeed); } addEventHandlerOnFeed(currentFeed) { currentFeed.on("connected", data => { this.adapter.log.debug(`Tibber feed connected: ${data.toString()}`); void this.adapter.setState("info.connection", true, true); }); currentFeed.on("disconnected", data => { void this.adapter.setState("info.connection", false, true); if (!this.adapter.config.HomesList.some(info => info.feedActive)) { return; } this.deltaFeedWarningTime = this.lastFeedWarningTime ? (Date.now() - this.lastFeedWarningTime.getTime()) / 60_000 : 0; if (this.countedFeedDisconnects < 25 && this.deltaFeedWarningTime > 60) { this.countedFeedDisconnects = 0; this.lastFeedWarningTime = null; this.deltaFeedWarningTime = 0; } this.countedFeedDisconnects++; const loggingTextBlock = `to reconnect with incremental delay - Error text sent by Tibber: ${data.toString()}`; if (this.deltaFeedWarningTime > 30) { this.countedFeedDisconnects = 0; this.lastFeedWarningTime = null; this.adapter.log.warn(`A feed was disconnected very often. I keep trying ${loggingTextBlock}`); } else { if (this.countedFeedDisconnects == 5) { this.lastFeedWarningTime = new Date(); this.adapter.log.warn(`A feed was disconnected very often. I keep trying ${loggingTextBlock}`); } else if (this.countedFeedDisconnects == 25) { this.adapter.log.error(`A feed was disconnected very often. I keep trying ${loggingTextBlock}`); } else { this.adapter.log.debug(`A feed was disconnected. I try ${loggingTextBlock}`); } } void this.reconnect(); }); currentFeed.on("error", error => { let errorMessage = ""; if (error instanceof Error) { if (error.message) { errorMessage = error.message; } else if (error.name) { errorMessage = error.name; } else { errorMessage = "Unspecified error"; } } else if (typeof error === "string") { errorMessage = error; } else { errorMessage = "Unknown error"; } this.adapter.log.warn(`Error on Tibber feed: ${errorMessage}`); }); currentFeed.on("data", data => { const receivedData = data; this.fetchLiveMeasurement("LiveMeasurement", receivedData); }); } fetchLiveMeasurement(objectDestination, liveMeasurement) { liveMeasurement.powerProduction ??= 0; const power = liveMeasurement.power > 0 ? liveMeasurement.power : liveMeasurement.powerProduction > 0 ? -liveMeasurement.powerProduction : 0; if (this.tibberConfig.homeId !== undefined) { const basePath = `Homes.${this.tibberConfig.homeId}.${objectDestination}`; void this.checkAndSetValue(`${basePath}.timestamp`, liveMeasurement.timestamp, `Timestamp when usage occurred`); void this.checkAndSetValueNumber(`${basePath}.power`, power, `Powerlevel measured at the moment +/-`, "W"); void this.checkAndSetValueNumber(`${basePath}.lastMeterConsumption`, Math.round(1000 * liveMeasurement.lastMeterConsumption) / 1000, `Latest consumption meter state`, "kWh"); if (this.adapter.config.FeedConfigAccumulatedConsumption) { void this.checkAndSetValueNumber(`${basePath}.accumulatedConsumption`, Math.round(1000 * liveMeasurement.accumulatedConsumption) / 1000, `Energy consumed since midnight`, "kWh"); } if (this.adapter.config.FeedConfigAccumulatedProduction) { void this.checkAndSetValueNumber(`${basePath}.accumulatedProduction`, Math.round(1000 * liveMeasurement.accumulatedProduction) / 1000, `Energy feed into grid since midnight`, "kWh"); } if (this.adapter.config.FeedConfigAccumulatedConsumptionLastHour) { void this.checkAndSetValueNumber(`${basePath}.accumulatedConsumptionLastHour`, Math.round(1000 * liveMeasurement.accumulatedConsumptionLastHour) / 1000, `Energy consumed since since last hour shift`, "kWh"); } if (this.adapter.config.FeedConfigAccumulatedProductionLastHour) { void this.checkAndSetValueNumber(`${basePath}.accumulatedProductionLastHour`, Math.round(1000 * liveMeasurement.accumulatedProductionLastHour) / 1000, `Energy produced since last hour shift`, "kWh"); } if (this.adapter.config.FeedConfigAccumulatedCost) { void this.checkAndSetValueNumber(`${basePath}.accumulatedCost`, liveMeasurement.accumulatedCost, `Accumulated cost since midnight; requires active Tibber power deal`); } if (this.adapter.config.FeedConfigAccumulatedReward) { void this.checkAndSetValueNumber(`${basePath}.accumulatedReward`, liveMeasurement.accumulatedReward, `Accumulated reward since midnight; requires active Tibber power deal`); } void this.checkAndSetValue(`${basePath}.currency`, liveMeasurement.currency, "Currency of displayed cost; requires active Tibber power deal"); void this.checkAndSetValueNumber(`${basePath}.minPower`, liveMeasurement.minPower, "Min consumption since midnight", "W"); void this.checkAndSetValueNumber(`${basePath}.averagePower`, liveMeasurement.averagePower, "Average consumption since midnight", "W"); void this.checkAndSetValueNumber(`${basePath}.maxPower`, liveMeasurement.maxPower, "Peak consumption since midnight", "W"); void this.checkAndSetValueNumber(`${basePath}.powerConsumption`, liveMeasurement.power, "Net consumption (A+) at the moment", "W"); void this.checkAndSetValueNumber(`${basePath}.powerProduction`, liveMeasurement.powerProduction, "Net grid feed-in (A-) at the moment", "W"); void this.checkAndSetValueNumber(`${basePath}.minPowerProduction`, liveMeasurement.minPowerProduction, "Min net grid feed-in since midnight", "W"); void this.checkAndSetValueNumber(`${basePath}.maxPowerProduction`, liveMeasurement.maxPowerProduction, "Max net grid feed-in since midnight", "W"); void this.checkAndSetValueNumber(`${basePath}.lastMeterProduction`, Math.round(1000 * liveMeasurement.lastMeterProduction) / 1000, `Latest grid feed-in meter state`, "kWh"); void this.checkAndSetValueNumber(`${basePath}.powerFactor`, liveMeasurement.powerFactor, "Power factor (active power / apparent power)"); void this.checkAndSetValueNumber(`${basePath}.signalStrength`, liveMeasurement.signalStrength, `Device signal strength (Pulse - dB; Watty - percent)`); void this.checkAndSetValueNumber(`${basePath}.voltagePhase1`, liveMeasurement.voltagePhase1, `Voltage on phase 1; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "V"); void this.checkAndSetValueNumber(`${basePath}.voltagePhase2`, liveMeasurement.voltagePhase2, `Voltage on phase 2; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "V"); void this.checkAndSetValueNumber(`${basePath}.voltagePhase3`, liveMeasurement.voltagePhase3, `Voltage on phase 3; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "V"); void this.checkAndSetValueNumber(`${basePath}.currentL1`, liveMeasurement.currentL1, `Current on L1; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "A"); void this.checkAndSetValueNumber(`${basePath}.currentL2`, liveMeasurement.currentL2, `Current on L2; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "A"); void this.checkAndSetValueNumber(`${basePath}.currentL3`, liveMeasurement.currentL3, `Current on L3; on some meters this value is not part of every data frame therefore the value is null at some timestamps`, "A"); } } async reconnect() { this.reconnectTime = 6000; do { this.adapter.log.debug(`Attempting to reconnect to TibberFeed in ${this.reconnectTime / 1000}sec interval - (of max. ${this.maxReconnectTime / 1000}sec)`); await this.adapter.delay(this.reconnectTime); await this.connectPulseStream(); this.reconnectTime = Math.min(this.reconnectTime + 2000, this.maxReconnectTime); } while (!this.tibberFeed.connected); this.adapter.log.debug(`Reconnection successful!`); } } exports.TibberPulse = TibberPulse; //# sourceMappingURL=tibberPulse.js.map