iobroker.utility-monitor 1.4.4 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -63
- package/admin/jsonConfig.json +130 -39
- package/io-package.json +25 -51
- package/lib/billingManager.js +53 -53
- package/lib/consumptionManager.js +63 -103
- package/lib/messagingHandler.js +108 -109
- package/lib/multiMeterManager.js +48 -68
- package/lib/stateManager.js +6 -5
- package/main.js +31 -45
- package/package.json +13 -13
- package/admin/tab_m.html +0 -305
- package/lib/importManager.js +0 -344
package/lib/billingManager.js
CHANGED
|
@@ -155,10 +155,14 @@ class BillingManager {
|
|
|
155
155
|
monthsSinceContract = Math.max(1, yDiff * 12 + mDiff + 1);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// Calculate accumulated basic charge (monthly fee × months)
|
|
158
159
|
const basicChargeAccumulated = basicChargeMonthly * monthsSinceContract;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
|
|
161
|
+
// Jahresgebühr ist ein FIXER Wert pro Jahr (z.B. 60€)
|
|
162
|
+
// NICHT pro-rata nach Monaten/Tagen berechnen!
|
|
163
|
+
const annualFeeAccumulated = annualFeePerYear;
|
|
164
|
+
|
|
165
|
+
const totalYearlyCost = yearlyConsumptionCost + basicChargeAccumulated + annualFeeAccumulated;
|
|
162
166
|
|
|
163
167
|
// Update states
|
|
164
168
|
await this.adapter.setStateAsync(
|
|
@@ -186,9 +190,11 @@ class BillingManager {
|
|
|
186
190
|
calculator.roundToDecimals(annualFeeAccumulated, 2),
|
|
187
191
|
true,
|
|
188
192
|
);
|
|
193
|
+
// basicCharge enthält NUR die monatliche Grundgebühr (akkumuliert)
|
|
194
|
+
// Jahresgebühr ist separat in annualFee
|
|
189
195
|
await this.adapter.setStateAsync(
|
|
190
196
|
`${type}.costs.basicCharge`,
|
|
191
|
-
calculator.roundToDecimals(
|
|
197
|
+
calculator.roundToDecimals(basicChargeAccumulated, 2),
|
|
192
198
|
true,
|
|
193
199
|
);
|
|
194
200
|
|
|
@@ -416,7 +422,7 @@ class BillingManager {
|
|
|
416
422
|
* @param {object} meter - Meter object from multiMeterManager
|
|
417
423
|
*/
|
|
418
424
|
async closeBillingPeriodForMeter(type, meter) {
|
|
419
|
-
const basePath =
|
|
425
|
+
const basePath = `${type}.${meter.name}`;
|
|
420
426
|
const label = meter.displayName || meter.name;
|
|
421
427
|
|
|
422
428
|
this.adapter.log.info(`🔔 Schließe Abrechnungszeitraum für ${basePath} (${label})...`);
|
|
@@ -432,14 +438,8 @@ class BillingManager {
|
|
|
432
438
|
return;
|
|
433
439
|
}
|
|
434
440
|
|
|
435
|
-
// Get contract date for THIS meter
|
|
436
|
-
|
|
437
|
-
if (meter.name === 'main') {
|
|
438
|
-
const configType = this.adapter.consumptionManager.getConfigType(type);
|
|
439
|
-
contractStartDate = this.adapter.config[`${configType}ContractStart`];
|
|
440
|
-
} else {
|
|
441
|
-
contractStartDate = meter.config?.contractStart;
|
|
442
|
-
}
|
|
441
|
+
// Get contract date for THIS meter (all meters have config.contractStart)
|
|
442
|
+
const contractStartDate = meter.config?.contractStart;
|
|
443
443
|
|
|
444
444
|
if (!contractStartDate) {
|
|
445
445
|
this.adapter.log.error(`❌ Kein Vertragsbeginn für ${basePath} konfiguriert.`);
|
|
@@ -491,42 +491,49 @@ class BillingManager {
|
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
/**
|
|
494
|
-
* Updates billing countdown
|
|
494
|
+
* Updates billing countdown for all meters of a type
|
|
495
|
+
* NOTE: Since v1.4.6, this updates ALL meters (main + additional)
|
|
495
496
|
*
|
|
496
497
|
* @param {string} type - Utility type
|
|
497
498
|
*/
|
|
498
499
|
async updateBillingCountdown(type) {
|
|
499
|
-
|
|
500
|
-
const
|
|
500
|
+
// Get all meters for this type
|
|
501
|
+
const meters = this.adapter.multiMeterManager?.getMetersForType(type) || [];
|
|
501
502
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
503
|
+
// Update countdown for each meter based on its contract date
|
|
504
|
+
for (const meter of meters) {
|
|
505
|
+
const contractStart = meter.config?.contractStart;
|
|
505
506
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
507
|
+
if (!contractStart) {
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
510
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
511
|
+
const startDate = calculator.parseGermanDate(contractStart);
|
|
512
|
+
if (!startDate) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
514
515
|
|
|
515
|
-
|
|
516
|
-
nextAnniversary
|
|
517
|
-
|
|
516
|
+
const today = new Date();
|
|
517
|
+
const nextAnniversary = new Date(startDate);
|
|
518
|
+
nextAnniversary.setFullYear(today.getFullYear());
|
|
518
519
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
displayPeriodEnd.setDate(displayPeriodEnd.getDate() - 1);
|
|
520
|
+
if (nextAnniversary < today) {
|
|
521
|
+
nextAnniversary.setFullYear(today.getFullYear() + 1);
|
|
522
|
+
}
|
|
523
523
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
displayPeriodEnd.
|
|
528
|
-
|
|
529
|
-
|
|
524
|
+
const msPerDay = 1000 * 60 * 60 * 24;
|
|
525
|
+
const daysRemaining = Math.ceil((nextAnniversary.getTime() - today.getTime()) / msPerDay);
|
|
526
|
+
const displayPeriodEnd = new Date(nextAnniversary);
|
|
527
|
+
displayPeriodEnd.setDate(displayPeriodEnd.getDate() - 1);
|
|
528
|
+
|
|
529
|
+
const basePath = `${type}.${meter.name}`;
|
|
530
|
+
await this.adapter.setStateAsync(`${basePath}.billing.daysRemaining`, daysRemaining, true);
|
|
531
|
+
await this.adapter.setStateAsync(
|
|
532
|
+
`${basePath}.billing.periodEnd`,
|
|
533
|
+
displayPeriodEnd.toLocaleDateString('de-DE'),
|
|
534
|
+
true,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
530
537
|
}
|
|
531
538
|
|
|
532
539
|
/**
|
|
@@ -574,21 +581,14 @@ class BillingManager {
|
|
|
574
581
|
// YEARLY RESET: Each meter resets individually based on ITS contract date
|
|
575
582
|
const meters = this.adapter.multiMeterManager?.getMetersForType(type) || [];
|
|
576
583
|
for (const meter of meters) {
|
|
577
|
-
const basePath =
|
|
584
|
+
const basePath = `${type}.${meter.name}`;
|
|
578
585
|
const lastYearStartState = await this.adapter.getStateAsync(`${basePath}.statistics.lastYearStart`);
|
|
579
586
|
|
|
580
587
|
if (lastYearStartState?.val) {
|
|
581
588
|
const lastYearStartDate = new Date(lastYearStartState.val);
|
|
582
589
|
|
|
583
|
-
// Get contract date for THIS specific meter
|
|
584
|
-
|
|
585
|
-
if (meter.name === 'main') {
|
|
586
|
-
// Main meter: use adapter config
|
|
587
|
-
contractStartDate = this.adapter.config[`${configType}ContractStart`];
|
|
588
|
-
} else {
|
|
589
|
-
// Additional meter: use meter's individual config
|
|
590
|
-
contractStartDate = meter.config?.contractStart;
|
|
591
|
-
}
|
|
590
|
+
// Get contract date for THIS specific meter (all meters have config.contractStart)
|
|
591
|
+
const contractStartDate = meter.config?.contractStart;
|
|
592
592
|
|
|
593
593
|
if (contractStartDate) {
|
|
594
594
|
const contractStart = calculator.parseGermanDate(contractStartDate);
|
|
@@ -644,7 +644,7 @@ class BillingManager {
|
|
|
644
644
|
|
|
645
645
|
// Reset each meter
|
|
646
646
|
for (const meter of meters) {
|
|
647
|
-
const basePath =
|
|
647
|
+
const basePath = `${type}.${meter.name}`;
|
|
648
648
|
const label = meter.displayName || meter.name;
|
|
649
649
|
|
|
650
650
|
this.adapter.log.debug(`Resetting daily counter for ${basePath} (${label})`);
|
|
@@ -713,7 +713,7 @@ class BillingManager {
|
|
|
713
713
|
|
|
714
714
|
// Reset each meter
|
|
715
715
|
for (const meter of meters) {
|
|
716
|
-
const basePath =
|
|
716
|
+
const basePath = `${type}.${meter.name}`;
|
|
717
717
|
const label = meter.displayName || meter.name;
|
|
718
718
|
|
|
719
719
|
this.adapter.log.debug(`Resetting monthly counter for ${basePath} (${label})`);
|
|
@@ -771,7 +771,7 @@ class BillingManager {
|
|
|
771
771
|
|
|
772
772
|
// Reset each meter
|
|
773
773
|
for (const meter of meters) {
|
|
774
|
-
const basePath =
|
|
774
|
+
const basePath = `${type}.${meter.name}`;
|
|
775
775
|
const label = meter.displayName || meter.name;
|
|
776
776
|
|
|
777
777
|
this.adapter.log.debug(`Resetting yearly counter for ${basePath} (${label})`);
|
|
@@ -803,7 +803,7 @@ class BillingManager {
|
|
|
803
803
|
* @param {object} meter - Meter object from multiMeterManager
|
|
804
804
|
*/
|
|
805
805
|
async resetYearlyCountersForMeter(type, meter) {
|
|
806
|
-
const basePath =
|
|
806
|
+
const basePath = `${type}.${meter.name}`;
|
|
807
807
|
const label = meter.displayName || meter.name;
|
|
808
808
|
|
|
809
809
|
this.adapter.log.debug(`Resetting yearly counter for ${basePath} (${label})`);
|
|
@@ -47,8 +47,8 @@ class ConsumptionManager {
|
|
|
47
47
|
|
|
48
48
|
this.adapter.log.info(`Initializing ${type} monitoring...`);
|
|
49
49
|
|
|
50
|
-
//
|
|
51
|
-
|
|
50
|
+
// State structure is now created by MultiMeterManager per meter (v1.4.6)
|
|
51
|
+
// Old createUtilityStateStructure removed - states are created under type.meterName.*
|
|
52
52
|
|
|
53
53
|
const configType = this.getConfigType(type);
|
|
54
54
|
const sensorDPKey = `${configType}SensorDP`;
|
|
@@ -56,7 +56,7 @@ class ConsumptionManager {
|
|
|
56
56
|
|
|
57
57
|
if (!sensorDP) {
|
|
58
58
|
this.adapter.log.warn(`${type} is active but no sensor datapoint configured!`);
|
|
59
|
-
|
|
59
|
+
// Note: sensorActive state is now created per meter by MultiMeterManager
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -69,91 +69,34 @@ class ConsumptionManager {
|
|
|
69
69
|
this.adapter.log.info(`${type}: Managed with contract start: ${contractStartDateStr}`);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
//
|
|
73
|
-
this.adapter.
|
|
74
|
-
await this.adapter.setStateAsync(`${type}.info.sensorActive`, true, true);
|
|
75
|
-
this.adapter.log.debug(`Subscribed to ${type} sensor: ${sensorDP}`);
|
|
72
|
+
// Sensor subscription is now handled by MultiMeterManager per meter
|
|
73
|
+
this.adapter.log.debug(`${type} sensor will be subscribed by MultiMeterManager: ${sensorDP}`);
|
|
76
74
|
|
|
77
75
|
// Initialize all meters (main + additional) via MultiMeterManager
|
|
76
|
+
// This handles everything now: state creation, sensor subscription, costs calculation
|
|
78
77
|
if (this.adapter.multiMeterManager) {
|
|
79
78
|
await this.adapter.multiMeterManager.initializeType(type);
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Initialize with current sensor value
|
|
90
|
-
try {
|
|
91
|
-
const sensorState = await this.adapter.getForeignStateAsync(sensorDP);
|
|
92
|
-
if (sensorState && sensorState.val !== null && typeof sensorState.val === 'number') {
|
|
93
|
-
await this.handleSensorUpdate(type, sensorDP, sensorState.val);
|
|
94
|
-
}
|
|
95
|
-
} catch (error) {
|
|
96
|
-
this.adapter.log.warn(`Could not read initial value from ${sensorDP}: ${error.message}`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Initialize period start timestamps if not set
|
|
100
|
-
const now = Date.now();
|
|
101
|
-
const dayStart = await this.adapter.getStateAsync(`${type}.statistics.lastDayStart`);
|
|
102
|
-
if (!dayStart || !dayStart.val) {
|
|
103
|
-
await this.adapter.setStateAsync(`${type}.statistics.lastDayStart`, now, true);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const monthStart = await this.adapter.getStateAsync(`${type}.statistics.lastMonthStart`);
|
|
107
|
-
if (!monthStart || !monthStart.val) {
|
|
108
|
-
await this.adapter.setStateAsync(`${type}.statistics.lastMonthStart`, now, true);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const yearStart = await this.adapter.getStateAsync(`${type}.statistics.lastYearStart`);
|
|
112
|
-
if (!yearStart || !yearStart.val) {
|
|
113
|
-
// Determine year start based on contract date or January 1st
|
|
114
|
-
const contractStartKey = `${configType}ContractStart`;
|
|
115
|
-
const contractStartDateStr = this.adapter.config[contractStartKey];
|
|
116
|
-
|
|
117
|
-
let yearStartDate;
|
|
118
|
-
if (contractStartDateStr) {
|
|
119
|
-
const contractStart = calculator.parseGermanDate(contractStartDateStr);
|
|
120
|
-
if (contractStart && !isNaN(contractStart.getTime())) {
|
|
121
|
-
// Calculate last anniversary
|
|
122
|
-
const nowDate = new Date(now);
|
|
123
|
-
const currentYear = nowDate.getFullYear();
|
|
124
|
-
yearStartDate = new Date(currentYear, contractStart.getMonth(), contractStart.getDate(), 12, 0, 0);
|
|
125
|
-
|
|
126
|
-
// If anniversary is in the future this year, take last year
|
|
127
|
-
if (yearStartDate > nowDate) {
|
|
128
|
-
yearStartDate.setFullYear(currentYear - 1);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!yearStartDate) {
|
|
134
|
-
// Fallback: January 1st of current year
|
|
135
|
-
const nowDate = new Date(now);
|
|
136
|
-
yearStartDate = new Date(nowDate.getFullYear(), 0, 1, 12, 0, 0);
|
|
137
|
-
this.adapter.log.info(
|
|
138
|
-
`${type}: No contract start found. Setting initial year start to January 1st: ${yearStartDate.toLocaleDateString('de-DE')}`,
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
await this.adapter.setStateAsync(`${type}.statistics.lastYearStart`, yearStartDate.getTime(), true);
|
|
143
|
-
}
|
|
144
|
-
// Update current price
|
|
145
|
-
await this.updateCurrentPrice(type);
|
|
146
|
-
|
|
147
|
-
// Initial cost calculation (wichtig! Sonst bleiben Kosten bei 0)
|
|
148
|
-
if (typeof this.adapter.updateCosts === 'function') {
|
|
149
|
-
await this.adapter.updateCosts(type);
|
|
150
|
-
}
|
|
81
|
+
// Note: All initialization moved to MultiMeterManager in v1.4.6:
|
|
82
|
+
// - Sensor value restoration (per meter)
|
|
83
|
+
// - Period start timestamps (per meter)
|
|
84
|
+
// - Current price updates (per meter)
|
|
85
|
+
// - Cost calculations (per meter)
|
|
86
|
+
// Old type-level states (gas.info.*, gas.statistics.*) are no longer used
|
|
151
87
|
|
|
152
88
|
// Initialize yearly consumption from initial reading if set
|
|
89
|
+
// NOTE: This is now handled per meter by MultiMeterManager in v1.4.6
|
|
90
|
+
// This legacy code path should not execute for new setups, but is kept for safety
|
|
153
91
|
const initialReadingKey = `${configType}InitialReading`;
|
|
154
92
|
const initialReading = this.adapter.config[initialReadingKey] || 0;
|
|
155
93
|
|
|
156
|
-
if (initialReading > 0) {
|
|
94
|
+
if (initialReading > 0 && sensorDP) {
|
|
95
|
+
// Get the main meter name to use the correct path
|
|
96
|
+
const mainMeterNameKey = `${configType}MainMeterName`;
|
|
97
|
+
const mainMeterName = this.adapter.config[mainMeterNameKey] || 'main';
|
|
98
|
+
const basePath = `${type}.${mainMeterName}`;
|
|
99
|
+
|
|
157
100
|
const sensorState = await this.adapter.getForeignStateAsync(sensorDP);
|
|
158
101
|
if (sensorState && typeof sensorState.val === 'number') {
|
|
159
102
|
let currentRaw = sensorState.val;
|
|
@@ -173,7 +116,7 @@ class ConsumptionManager {
|
|
|
173
116
|
const zZahl = this.adapter.config.gasZahl || 0.95;
|
|
174
117
|
const yearlyVolume = yearlyConsumption;
|
|
175
118
|
yearlyConsumption = calculator.convertGasM3ToKWh(yearlyConsumption, brennwert, zZahl);
|
|
176
|
-
await this.adapter.setStateAsync(`${
|
|
119
|
+
await this.adapter.setStateAsync(`${basePath}.consumption.yearlyVolume`, yearlyVolume, true);
|
|
177
120
|
this.adapter.log.info(
|
|
178
121
|
`Init yearly ${type}: ${yearlyConsumption.toFixed(2)} kWh = ${(currentRaw - initialReading).toFixed(2)} m³ (current: ${currentRaw.toFixed(2)} m³, initial: ${initialReading} m³)`,
|
|
179
122
|
);
|
|
@@ -183,17 +126,15 @@ class ConsumptionManager {
|
|
|
183
126
|
);
|
|
184
127
|
}
|
|
185
128
|
|
|
186
|
-
await this.adapter.setStateAsync(`${
|
|
129
|
+
await this.adapter.setStateAsync(`${basePath}.consumption.yearly`, yearlyConsumption, true);
|
|
187
130
|
if (typeof this.adapter.updateCosts === 'function') {
|
|
188
131
|
await this.adapter.updateCosts(type);
|
|
189
132
|
}
|
|
190
133
|
}
|
|
191
134
|
}
|
|
192
135
|
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
await this.adapter.updateBillingCountdown(type);
|
|
196
|
-
}
|
|
136
|
+
// Note: Billing countdown is now handled per meter by billingManager.updateBillingCountdown()
|
|
137
|
+
// which is called during checkPeriodResets()
|
|
197
138
|
|
|
198
139
|
this.adapter.log.debug(`Initial cost calculation completed for ${type}`);
|
|
199
140
|
}
|
|
@@ -201,17 +142,25 @@ class ConsumptionManager {
|
|
|
201
142
|
/**
|
|
202
143
|
* Handles sensor value updates
|
|
203
144
|
*
|
|
145
|
+
* NOTE: This method is DEPRECATED since v1.4.6!
|
|
146
|
+
* All sensor updates are now handled by MultiMeterManager.handleSensorUpdate()
|
|
147
|
+
* This method remains only as fallback but should NEVER be called in normal operation.
|
|
148
|
+
*
|
|
204
149
|
* @param {string} type - Utility type
|
|
205
150
|
* @param {string} sensorDP - Sensor datapoint ID
|
|
206
151
|
* @param {number} value - New sensor value
|
|
207
152
|
*/
|
|
208
153
|
async handleSensorUpdate(type, sensorDP, value) {
|
|
154
|
+
this.adapter.log.warn(
|
|
155
|
+
`consumptionManager.handleSensorUpdate() called - this is deprecated! All sensors should be handled by MultiMeterManager.`,
|
|
156
|
+
);
|
|
157
|
+
|
|
209
158
|
if (typeof value !== 'number' || value < 0) {
|
|
210
159
|
this.adapter.log.warn(`Invalid sensor value for ${type}: ${value}`);
|
|
211
160
|
return;
|
|
212
161
|
}
|
|
213
162
|
|
|
214
|
-
this.adapter.log.debug(`Sensor update for ${type}: ${value}`);
|
|
163
|
+
this.adapter.log.debug(`[DEPRECATED] Sensor update for ${type}: ${value}`);
|
|
215
164
|
|
|
216
165
|
const now = Date.now();
|
|
217
166
|
let consumption = value;
|
|
@@ -371,36 +320,47 @@ class ConsumptionManager {
|
|
|
371
320
|
}
|
|
372
321
|
|
|
373
322
|
/**
|
|
374
|
-
* Updates the current price display
|
|
323
|
+
* Updates the current price display for all meters of a type
|
|
324
|
+
* NOTE: Since v1.4.6, this updates ALL meters (main + additional)
|
|
325
|
+
* Only main meters support HT/NT, additional meters have fixed price
|
|
375
326
|
*
|
|
376
327
|
* @param {string} type - Utility type
|
|
377
328
|
*/
|
|
378
329
|
async updateCurrentPrice(type) {
|
|
379
330
|
const configType = this.getConfigType(type);
|
|
380
331
|
|
|
381
|
-
//
|
|
382
|
-
const
|
|
383
|
-
const htNtEnabled = this.adapter.config[htNtEnabledKey] || false;
|
|
332
|
+
// Get all meters for this type
|
|
333
|
+
const meters = this.adapter.multiMeterManager?.getMetersForType(type) || [];
|
|
384
334
|
|
|
385
|
-
|
|
386
|
-
|
|
335
|
+
for (const meter of meters) {
|
|
336
|
+
let tariffName = 'Standard';
|
|
337
|
+
let activePrice = 0;
|
|
387
338
|
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
339
|
+
// Check if this meter has HT/NT enabled
|
|
340
|
+
const htNtEnabled = meter.config?.htNtEnabled || false;
|
|
341
|
+
|
|
342
|
+
if (htNtEnabled) {
|
|
343
|
+
const isHT = calculator.isHTTime(this.adapter.config, configType);
|
|
344
|
+
if (isHT) {
|
|
345
|
+
activePrice = this.adapter.config[`${configType}HtPrice`] || 0;
|
|
346
|
+
tariffName = 'Haupttarif (HT)';
|
|
347
|
+
} else {
|
|
348
|
+
activePrice = this.adapter.config[`${configType}NtPrice`] || 0;
|
|
349
|
+
tariffName = 'Nebentarif (NT)';
|
|
350
|
+
}
|
|
393
351
|
} else {
|
|
394
|
-
|
|
395
|
-
|
|
352
|
+
// Use meter's configured price
|
|
353
|
+
activePrice = meter.config?.preis || 0;
|
|
396
354
|
}
|
|
397
|
-
} else {
|
|
398
|
-
const priceKey = `${configType}Preis`;
|
|
399
|
-
activePrice = this.adapter.config[priceKey] || 0;
|
|
400
|
-
}
|
|
401
355
|
|
|
402
|
-
|
|
403
|
-
|
|
356
|
+
const basePath = `${type}.${meter.name}`;
|
|
357
|
+
await this.adapter.setStateAsync(
|
|
358
|
+
`${basePath}.info.currentPrice`,
|
|
359
|
+
calculator.roundToDecimals(activePrice, 4),
|
|
360
|
+
true,
|
|
361
|
+
);
|
|
362
|
+
await this.adapter.setStateAsync(`${basePath}.info.currentTariff`, tariffName, true);
|
|
363
|
+
}
|
|
404
364
|
}
|
|
405
365
|
}
|
|
406
366
|
|