iobroker.utility-monitor 1.4.5 → 1.5.0
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 +159 -44
- package/admin/custom/.vite/manifest.json +90 -0
- package/admin/custom/@mf-types/Components.d.ts +2 -0
- package/admin/custom/@mf-types/compiled-types/Components/CSVImporter.d.ts +11 -0
- package/admin/custom/@mf-types/compiled-types/Components.d.ts +2 -0
- package/admin/custom/@mf-types.d.ts +3 -0
- package/admin/custom/@mf-types.zip +0 -0
- package/admin/custom/CSVImporter_v15_11.js +4415 -0
- package/admin/custom/assets/Components-i0AZ59nl.js +18887 -0
- package/admin/custom/assets/UtilityMonitor__loadShare__react__loadShare__-Da99Mak4.js +42 -0
- package/admin/custom/assets/UtilityMonitor__mf_v__runtimeInit__mf_v__-BmC4OGk6.js +16 -0
- package/admin/custom/assets/_commonjsHelpers-Dj2_voLF.js +30 -0
- package/admin/custom/assets/hostInit-DEXfeB0W.js +10 -0
- package/admin/custom/assets/index-B3WVNJTz.js +401 -0
- package/admin/custom/assets/index-VBwl8x_k.js +64 -0
- package/admin/custom/assets/preload-helper-BelkbqnE.js +61 -0
- package/admin/custom/assets/virtualExposes-CqCLUNLT.js +19 -0
- package/admin/custom/index.html +12 -0
- package/admin/custom/mf-manifest.json +1 -0
- package/admin/jsonConfig.json +219 -35
- package/io-package.json +51 -2
- package/lib/billingManager.js +276 -170
- package/lib/calculator.js +19 -138
- package/lib/consumptionManager.js +48 -331
- package/lib/importManager.js +300 -0
- package/lib/messagingHandler.js +112 -49
- package/lib/meter/MeterRegistry.js +110 -0
- package/lib/multiMeterManager.js +410 -181
- package/lib/stateManager.js +508 -36
- package/lib/utils/billingHelper.js +69 -0
- package/lib/utils/consumptionHelper.js +47 -0
- package/lib/utils/helpers.js +178 -0
- package/lib/utils/typeMapper.js +19 -0
- package/main.js +99 -36
- package/package.json +10 -4
package/lib/stateManager.js
CHANGED
|
@@ -1,28 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* State Manager module for nebenkosten-monitor
|
|
3
2
|
* Manages the creation and structure of all adapter states
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
|
-
/**
|
|
7
|
-
* Safe wrapper for setObjectNotExistsAsync with error handling
|
|
8
|
-
*
|
|
9
|
-
* @param {object} adapter - Adapter instance
|
|
10
|
-
* @param {string} id - State ID
|
|
11
|
-
* @param {object} obj - State object
|
|
12
|
-
* @returns {Promise<void>}
|
|
13
|
-
*/
|
|
14
|
-
async function safeSetObjectNotExists(adapter, id, obj) {
|
|
15
|
-
try {
|
|
16
|
-
await adapter.setObjectNotExistsAsync(id, obj);
|
|
17
|
-
} catch (error) {
|
|
18
|
-
adapter.log.warn(`Failed to create state ${id}: ${error.message}`);
|
|
19
|
-
// Re-throw critical errors
|
|
20
|
-
if (error.message && error.message.includes('EACCES')) {
|
|
21
|
-
throw error;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
5
|
/**
|
|
27
6
|
* State role definitions for different state types
|
|
28
7
|
*/
|
|
@@ -162,6 +141,20 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
162
141
|
native: {},
|
|
163
142
|
});
|
|
164
143
|
|
|
144
|
+
await adapter.setObjectNotExistsAsync(`${type}.consumption.weekly`, {
|
|
145
|
+
type: 'state',
|
|
146
|
+
common: {
|
|
147
|
+
name: `Wochen-${(label.consumption || 'Verbrauch').toLowerCase()} (${label.unit})`,
|
|
148
|
+
type: 'number',
|
|
149
|
+
role: STATE_ROLES.consumption,
|
|
150
|
+
read: true,
|
|
151
|
+
write: false,
|
|
152
|
+
unit: label.unit,
|
|
153
|
+
def: 0,
|
|
154
|
+
},
|
|
155
|
+
native: {},
|
|
156
|
+
});
|
|
157
|
+
|
|
165
158
|
// Map internal type to config type (electricity -> strom, water -> wasser, gas -> gas)
|
|
166
159
|
const configTypeMap = {
|
|
167
160
|
electricity: 'strom',
|
|
@@ -200,6 +193,28 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
200
193
|
native: {},
|
|
201
194
|
});
|
|
202
195
|
}
|
|
196
|
+
|
|
197
|
+
const htNtWeeklyStates = ['weeklyHT', 'weeklyNT'];
|
|
198
|
+
const htNtWeeklyLabels = {
|
|
199
|
+
weeklyHT: 'Wochenverbrauch Haupttarif (HT)',
|
|
200
|
+
weeklyNT: 'Wochenverbrauch Nebentarif (NT)',
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
for (const state of htNtWeeklyStates) {
|
|
204
|
+
await adapter.setObjectNotExistsAsync(`${type}.consumption.${state}`, {
|
|
205
|
+
type: 'state',
|
|
206
|
+
common: {
|
|
207
|
+
name: `${htNtWeeklyLabels[state]} (${label.unit})`,
|
|
208
|
+
type: 'number',
|
|
209
|
+
role: STATE_ROLES.consumption,
|
|
210
|
+
read: true,
|
|
211
|
+
write: false,
|
|
212
|
+
unit: label.unit,
|
|
213
|
+
def: 0,
|
|
214
|
+
},
|
|
215
|
+
native: {},
|
|
216
|
+
});
|
|
217
|
+
}
|
|
203
218
|
}
|
|
204
219
|
|
|
205
220
|
await adapter.setObjectNotExistsAsync(`${type}.consumption.lastUpdate`, {
|
|
@@ -265,6 +280,20 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
265
280
|
native: {},
|
|
266
281
|
});
|
|
267
282
|
|
|
283
|
+
await adapter.setObjectNotExistsAsync(`${type}.costs.weekly`, {
|
|
284
|
+
type: 'state',
|
|
285
|
+
common: {
|
|
286
|
+
name: `Wochen-${(label.cost || 'Kosten').toLowerCase()} (€)`,
|
|
287
|
+
type: 'number',
|
|
288
|
+
role: STATE_ROLES.cost,
|
|
289
|
+
read: true,
|
|
290
|
+
write: false,
|
|
291
|
+
unit: '€',
|
|
292
|
+
def: 0,
|
|
293
|
+
},
|
|
294
|
+
native: {},
|
|
295
|
+
});
|
|
296
|
+
|
|
268
297
|
// HT/NT states - only create if HT/NT tariff is enabled
|
|
269
298
|
// Note: htNtEnabledKey already calculated above for consumption section
|
|
270
299
|
if (_config[htNtEnabledKey]) {
|
|
@@ -351,6 +380,34 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
351
380
|
},
|
|
352
381
|
native: {},
|
|
353
382
|
});
|
|
383
|
+
|
|
384
|
+
await adapter.setObjectNotExistsAsync(`${type}.costs.weeklyHT`, {
|
|
385
|
+
type: 'state',
|
|
386
|
+
common: {
|
|
387
|
+
name: 'Wochenkosten Haupttarif (HT) (€)',
|
|
388
|
+
type: 'number',
|
|
389
|
+
role: STATE_ROLES.cost,
|
|
390
|
+
read: true,
|
|
391
|
+
write: false,
|
|
392
|
+
unit: '€',
|
|
393
|
+
def: 0,
|
|
394
|
+
},
|
|
395
|
+
native: {},
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
await adapter.setObjectNotExistsAsync(`${type}.costs.weeklyNT`, {
|
|
399
|
+
type: 'state',
|
|
400
|
+
common: {
|
|
401
|
+
name: 'Wochenkosten Nebentarif (NT) (€)',
|
|
402
|
+
type: 'number',
|
|
403
|
+
role: STATE_ROLES.cost,
|
|
404
|
+
read: true,
|
|
405
|
+
write: false,
|
|
406
|
+
unit: '€',
|
|
407
|
+
def: 0,
|
|
408
|
+
},
|
|
409
|
+
native: {},
|
|
410
|
+
});
|
|
354
411
|
}
|
|
355
412
|
|
|
356
413
|
await adapter.setObjectNotExistsAsync(`${type}.costs.totalYearly`, {
|
|
@@ -765,6 +822,68 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
765
822
|
});
|
|
766
823
|
}
|
|
767
824
|
|
|
825
|
+
// Last week consumption
|
|
826
|
+
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastWeek`, {
|
|
827
|
+
type: 'state',
|
|
828
|
+
common: {
|
|
829
|
+
name: `Verbrauch letzte Woche (${label.unit})`,
|
|
830
|
+
type: 'number',
|
|
831
|
+
role: STATE_ROLES.consumption,
|
|
832
|
+
read: true,
|
|
833
|
+
write: false,
|
|
834
|
+
unit: label.unit,
|
|
835
|
+
def: 0,
|
|
836
|
+
},
|
|
837
|
+
native: {},
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
if (type === 'gas') {
|
|
841
|
+
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastWeekVolume`, {
|
|
842
|
+
type: 'state',
|
|
843
|
+
common: {
|
|
844
|
+
name: `Verbrauch letzte Woche (${label.volumeUnit})`,
|
|
845
|
+
type: 'number',
|
|
846
|
+
role: STATE_ROLES.consumption,
|
|
847
|
+
read: true,
|
|
848
|
+
write: false,
|
|
849
|
+
unit: label.volumeUnit,
|
|
850
|
+
def: 0,
|
|
851
|
+
},
|
|
852
|
+
native: {},
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Last month consumption
|
|
857
|
+
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastMonth`, {
|
|
858
|
+
type: 'state',
|
|
859
|
+
common: {
|
|
860
|
+
name: `Verbrauch letzter Monat (${label.unit})`,
|
|
861
|
+
type: 'number',
|
|
862
|
+
role: STATE_ROLES.consumption,
|
|
863
|
+
read: true,
|
|
864
|
+
write: false,
|
|
865
|
+
unit: label.unit,
|
|
866
|
+
def: 0,
|
|
867
|
+
},
|
|
868
|
+
native: {},
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
if (type === 'gas') {
|
|
872
|
+
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastMonthVolume`, {
|
|
873
|
+
type: 'state',
|
|
874
|
+
common: {
|
|
875
|
+
name: `Verbrauch letzter Monat (${label.volumeUnit})`,
|
|
876
|
+
type: 'number',
|
|
877
|
+
role: STATE_ROLES.consumption,
|
|
878
|
+
read: true,
|
|
879
|
+
write: false,
|
|
880
|
+
unit: label.volumeUnit,
|
|
881
|
+
def: 0,
|
|
882
|
+
},
|
|
883
|
+
native: {},
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
|
|
768
887
|
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastDayStart`, {
|
|
769
888
|
type: 'state',
|
|
770
889
|
common: {
|
|
@@ -777,6 +896,18 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
777
896
|
native: {},
|
|
778
897
|
});
|
|
779
898
|
|
|
899
|
+
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastWeekStart`, {
|
|
900
|
+
type: 'state',
|
|
901
|
+
common: {
|
|
902
|
+
name: 'Wochenzähler zurückgesetzt am',
|
|
903
|
+
type: 'number',
|
|
904
|
+
role: STATE_ROLES.timestamp,
|
|
905
|
+
read: true,
|
|
906
|
+
write: false,
|
|
907
|
+
},
|
|
908
|
+
native: {},
|
|
909
|
+
});
|
|
910
|
+
|
|
780
911
|
await adapter.setObjectNotExistsAsync(`${type}.statistics.lastMonthStart`, {
|
|
781
912
|
type: 'state',
|
|
782
913
|
common: {
|
|
@@ -817,11 +948,12 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
|
|
|
817
948
|
async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
818
949
|
const isGas = type === 'gas';
|
|
819
950
|
|
|
951
|
+
// All meters now include the meter name in labels for consistency
|
|
820
952
|
const labels = {
|
|
821
|
-
gas: { name:
|
|
822
|
-
water: { name:
|
|
823
|
-
electricity: { name:
|
|
824
|
-
pv: { name:
|
|
953
|
+
gas: { name: `Gas (${meterName})`, unit: 'kWh', volumeUnit: 'm³' },
|
|
954
|
+
water: { name: `Wasser (${meterName})`, unit: 'm³', volumeUnit: 'm³' },
|
|
955
|
+
electricity: { name: `Strom (${meterName})`, unit: 'kWh', volumeUnit: 'kWh' },
|
|
956
|
+
pv: { name: `PV (${meterName})`, unit: 'kWh', volumeUnit: 'kWh' },
|
|
825
957
|
};
|
|
826
958
|
|
|
827
959
|
const label = labels[type];
|
|
@@ -832,7 +964,7 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
832
964
|
// Fallback to prevent crash
|
|
833
965
|
return;
|
|
834
966
|
}
|
|
835
|
-
const basePath =
|
|
967
|
+
const basePath = `${type}.${meterName}`;
|
|
836
968
|
|
|
837
969
|
// Create main channel
|
|
838
970
|
await adapter.setObjectNotExistsAsync(basePath, {
|
|
@@ -895,6 +1027,20 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
895
1027
|
},
|
|
896
1028
|
native: {},
|
|
897
1029
|
});
|
|
1030
|
+
|
|
1031
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.weeklyVolume`, {
|
|
1032
|
+
type: 'state',
|
|
1033
|
+
common: {
|
|
1034
|
+
name: 'Wöchentlicher Verbrauch (m³)',
|
|
1035
|
+
type: 'number',
|
|
1036
|
+
role: STATE_ROLES.consumption,
|
|
1037
|
+
read: true,
|
|
1038
|
+
write: false,
|
|
1039
|
+
unit: 'm³',
|
|
1040
|
+
def: 0,
|
|
1041
|
+
},
|
|
1042
|
+
native: {},
|
|
1043
|
+
});
|
|
898
1044
|
}
|
|
899
1045
|
|
|
900
1046
|
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.daily`, {
|
|
@@ -939,6 +1085,65 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
939
1085
|
native: {},
|
|
940
1086
|
});
|
|
941
1087
|
|
|
1088
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.weekly`, {
|
|
1089
|
+
type: 'state',
|
|
1090
|
+
common: {
|
|
1091
|
+
name: `Wochenverbrauch (${label.unit})`,
|
|
1092
|
+
type: 'number',
|
|
1093
|
+
role: STATE_ROLES.consumption,
|
|
1094
|
+
read: true,
|
|
1095
|
+
write: false,
|
|
1096
|
+
unit: label.unit,
|
|
1097
|
+
def: 0,
|
|
1098
|
+
},
|
|
1099
|
+
native: {},
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1102
|
+
if (_config.htNtEnabled) {
|
|
1103
|
+
const htNtStates = [
|
|
1104
|
+
'dailyHT',
|
|
1105
|
+
'dailyNT',
|
|
1106
|
+
'monthlyHT',
|
|
1107
|
+
'monthlyNT',
|
|
1108
|
+
'yearlyHT',
|
|
1109
|
+
'yearlyNT',
|
|
1110
|
+
'weeklyHT',
|
|
1111
|
+
'weeklyNT',
|
|
1112
|
+
];
|
|
1113
|
+
const htNtLabels = {
|
|
1114
|
+
dailyHT: 'Tagesverbrauch Haupttarif (HT)',
|
|
1115
|
+
dailyNT: 'Tagesverbrauch Nebentarif (NT)',
|
|
1116
|
+
monthlyHT: 'Monatsverbrauch Haupttarif (HT)',
|
|
1117
|
+
monthlyNT: 'Monatsverbrauch Nebentarif (NT)',
|
|
1118
|
+
yearlyHT: 'Jahresverbrauch Haupttarif (HT)',
|
|
1119
|
+
yearlyNT: 'Jahresverbrauch Nebentarif (NT)',
|
|
1120
|
+
weeklyHT: 'Wochenverbrauch Haupttarif (HT)',
|
|
1121
|
+
weeklyNT: 'Wochenverbrauch Nebentarif (NT)',
|
|
1122
|
+
weeklyVolumeHT: 'Wochenverbrauch Haupttarif (m³)',
|
|
1123
|
+
weeklyVolumeNT: 'Wochenverbrauch Nebentarif (m³)',
|
|
1124
|
+
};
|
|
1125
|
+
|
|
1126
|
+
if (type === 'gas') {
|
|
1127
|
+
htNtStates.push('weeklyVolumeHT', 'weeklyVolumeNT');
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
for (const state of htNtStates) {
|
|
1131
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.${state}`, {
|
|
1132
|
+
type: 'state',
|
|
1133
|
+
common: {
|
|
1134
|
+
name: `${htNtLabels[state]} (${label.unit})`,
|
|
1135
|
+
type: 'number',
|
|
1136
|
+
role: STATE_ROLES.consumption,
|
|
1137
|
+
read: true,
|
|
1138
|
+
write: false,
|
|
1139
|
+
unit: label.unit,
|
|
1140
|
+
def: 0,
|
|
1141
|
+
},
|
|
1142
|
+
native: {},
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
942
1147
|
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.lastUpdate`, {
|
|
943
1148
|
type: 'state',
|
|
944
1149
|
common: {
|
|
@@ -1002,6 +1207,59 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
1002
1207
|
native: {},
|
|
1003
1208
|
});
|
|
1004
1209
|
|
|
1210
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.costs.weekly`, {
|
|
1211
|
+
type: 'state',
|
|
1212
|
+
common: {
|
|
1213
|
+
name: 'Wochenkosten (€)',
|
|
1214
|
+
type: 'number',
|
|
1215
|
+
role: STATE_ROLES.cost,
|
|
1216
|
+
read: true,
|
|
1217
|
+
write: false,
|
|
1218
|
+
unit: '€',
|
|
1219
|
+
def: 0,
|
|
1220
|
+
},
|
|
1221
|
+
native: {},
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
if (_config.htNtEnabled) {
|
|
1225
|
+
const htNtCostStates = [
|
|
1226
|
+
'dailyHT',
|
|
1227
|
+
'dailyNT',
|
|
1228
|
+
'monthlyHT',
|
|
1229
|
+
'monthlyNT',
|
|
1230
|
+
'yearlyHT',
|
|
1231
|
+
'yearlyNT',
|
|
1232
|
+
'weeklyHT',
|
|
1233
|
+
'weeklyNT',
|
|
1234
|
+
];
|
|
1235
|
+
const htNtCostLabels = {
|
|
1236
|
+
dailyHT: 'Tageskosten Haupttarif (HT)',
|
|
1237
|
+
dailyNT: 'Tageskosten Nebentarif (NT)',
|
|
1238
|
+
monthlyHT: 'Monatskosten Haupttarif (HT)',
|
|
1239
|
+
monthlyNT: 'Monatskosten Nebentarif (NT)',
|
|
1240
|
+
yearlyHT: 'Jahreskosten Haupttarif (HT)',
|
|
1241
|
+
yearlyNT: 'Jahreskosten Nebentarif (NT)',
|
|
1242
|
+
weeklyHT: 'Wochenkosten Haupttarif (HT)',
|
|
1243
|
+
weeklyNT: 'Wochenkosten Nebentarif (NT)',
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
for (const state of htNtCostStates) {
|
|
1247
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.costs.${state}`, {
|
|
1248
|
+
type: 'state',
|
|
1249
|
+
common: {
|
|
1250
|
+
name: `${htNtCostLabels[state]} (€)`,
|
|
1251
|
+
type: 'number',
|
|
1252
|
+
role: STATE_ROLES.cost,
|
|
1253
|
+
read: true,
|
|
1254
|
+
write: false,
|
|
1255
|
+
unit: '€',
|
|
1256
|
+
def: 0,
|
|
1257
|
+
},
|
|
1258
|
+
native: {},
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1005
1263
|
await adapter.setObjectNotExistsAsync(`${basePath}.costs.totalYearly`, {
|
|
1006
1264
|
type: 'state',
|
|
1007
1265
|
common: {
|
|
@@ -1278,27 +1536,27 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
1278
1536
|
native: {},
|
|
1279
1537
|
});
|
|
1280
1538
|
|
|
1281
|
-
await adapter.setObjectNotExistsAsync(`${basePath}.info.
|
|
1539
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.info.sensorActive`, {
|
|
1282
1540
|
type: 'state',
|
|
1283
1541
|
common: {
|
|
1284
|
-
name: '
|
|
1285
|
-
type: '
|
|
1286
|
-
role:
|
|
1542
|
+
name: 'Sensor aktiv',
|
|
1543
|
+
type: 'boolean',
|
|
1544
|
+
role: 'indicator.reachable',
|
|
1287
1545
|
read: true,
|
|
1288
1546
|
write: false,
|
|
1547
|
+
def: false,
|
|
1289
1548
|
},
|
|
1290
1549
|
native: {},
|
|
1291
1550
|
});
|
|
1292
1551
|
|
|
1293
|
-
await adapter.setObjectNotExistsAsync(`${basePath}.info.
|
|
1552
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.info.lastSync`, {
|
|
1294
1553
|
type: 'state',
|
|
1295
1554
|
common: {
|
|
1296
|
-
name: '
|
|
1297
|
-
type: '
|
|
1298
|
-
role: STATE_ROLES.
|
|
1555
|
+
name: 'Letzte Synchronisation',
|
|
1556
|
+
type: 'number',
|
|
1557
|
+
role: STATE_ROLES.timestamp,
|
|
1299
1558
|
read: true,
|
|
1300
1559
|
write: false,
|
|
1301
|
-
def: false,
|
|
1302
1560
|
},
|
|
1303
1561
|
native: {},
|
|
1304
1562
|
});
|
|
@@ -1383,6 +1641,68 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
1383
1641
|
});
|
|
1384
1642
|
}
|
|
1385
1643
|
|
|
1644
|
+
// Last week consumption
|
|
1645
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastWeek`, {
|
|
1646
|
+
type: 'state',
|
|
1647
|
+
common: {
|
|
1648
|
+
name: `Verbrauch letzte Woche (${label.unit})`,
|
|
1649
|
+
type: 'number',
|
|
1650
|
+
role: STATE_ROLES.consumption,
|
|
1651
|
+
read: true,
|
|
1652
|
+
write: false,
|
|
1653
|
+
unit: label.unit,
|
|
1654
|
+
def: 0,
|
|
1655
|
+
},
|
|
1656
|
+
native: {},
|
|
1657
|
+
});
|
|
1658
|
+
|
|
1659
|
+
if (type === 'gas') {
|
|
1660
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastWeekVolume`, {
|
|
1661
|
+
type: 'state',
|
|
1662
|
+
common: {
|
|
1663
|
+
name: `Verbrauch letzte Woche (${label.volumeUnit})`,
|
|
1664
|
+
type: 'number',
|
|
1665
|
+
role: STATE_ROLES.consumption,
|
|
1666
|
+
read: true,
|
|
1667
|
+
write: false,
|
|
1668
|
+
unit: label.volumeUnit,
|
|
1669
|
+
def: 0,
|
|
1670
|
+
},
|
|
1671
|
+
native: {},
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
// Last month consumption
|
|
1676
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastMonth`, {
|
|
1677
|
+
type: 'state',
|
|
1678
|
+
common: {
|
|
1679
|
+
name: `Verbrauch letzter Monat (${label.unit})`,
|
|
1680
|
+
type: 'number',
|
|
1681
|
+
role: STATE_ROLES.consumption,
|
|
1682
|
+
read: true,
|
|
1683
|
+
write: false,
|
|
1684
|
+
unit: label.unit,
|
|
1685
|
+
def: 0,
|
|
1686
|
+
},
|
|
1687
|
+
native: {},
|
|
1688
|
+
});
|
|
1689
|
+
|
|
1690
|
+
if (type === 'gas') {
|
|
1691
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastMonthVolume`, {
|
|
1692
|
+
type: 'state',
|
|
1693
|
+
common: {
|
|
1694
|
+
name: `Verbrauch letzter Monat (${label.volumeUnit})`,
|
|
1695
|
+
type: 'number',
|
|
1696
|
+
role: STATE_ROLES.consumption,
|
|
1697
|
+
read: true,
|
|
1698
|
+
write: false,
|
|
1699
|
+
unit: label.volumeUnit,
|
|
1700
|
+
def: 0,
|
|
1701
|
+
},
|
|
1702
|
+
native: {},
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1386
1706
|
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastDayStart`, {
|
|
1387
1707
|
type: 'state',
|
|
1388
1708
|
common: {
|
|
@@ -1419,6 +1739,18 @@ async function createMeterStructure(adapter, type, meterName, _config = {}) {
|
|
|
1419
1739
|
native: {},
|
|
1420
1740
|
});
|
|
1421
1741
|
|
|
1742
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.statistics.lastWeekStart`, {
|
|
1743
|
+
type: 'state',
|
|
1744
|
+
common: {
|
|
1745
|
+
name: 'Wochenzähler zurückgesetzt am',
|
|
1746
|
+
type: 'number',
|
|
1747
|
+
role: STATE_ROLES.timestamp,
|
|
1748
|
+
read: true,
|
|
1749
|
+
write: false,
|
|
1750
|
+
},
|
|
1751
|
+
native: {},
|
|
1752
|
+
});
|
|
1753
|
+
|
|
1422
1754
|
adapter.log.debug(`Meter state structure created for ${type}.${meterName}`);
|
|
1423
1755
|
}
|
|
1424
1756
|
|
|
@@ -1523,6 +1855,61 @@ async function createTotalsStructure(adapter, type) {
|
|
|
1523
1855
|
native: {},
|
|
1524
1856
|
});
|
|
1525
1857
|
|
|
1858
|
+
if (type === 'gas') {
|
|
1859
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.weeklyVolume`, {
|
|
1860
|
+
type: 'state',
|
|
1861
|
+
common: {
|
|
1862
|
+
name: 'Wochenverbrauch Gesamt (m³)',
|
|
1863
|
+
type: 'number',
|
|
1864
|
+
role: STATE_ROLES.consumption,
|
|
1865
|
+
read: true,
|
|
1866
|
+
write: false,
|
|
1867
|
+
unit: 'm³',
|
|
1868
|
+
def: 0,
|
|
1869
|
+
},
|
|
1870
|
+
native: {},
|
|
1871
|
+
});
|
|
1872
|
+
|
|
1873
|
+
// Also add HT/NT volume totals if gas has HT/NT enabled
|
|
1874
|
+
if (adapter.config.gasHtNtEnabled) {
|
|
1875
|
+
const hntVolumeStates = ['weeklyVolumeHT', 'weeklyVolumeNT'];
|
|
1876
|
+
const hntVolumeLabels = {
|
|
1877
|
+
weeklyVolumeHT: 'Wochenverbrauch Gesamt Haupttarif (HT) (m³)',
|
|
1878
|
+
weeklyVolumeNT: 'Wochenverbrauch Gesamt Nebentarif (NT) (m³)',
|
|
1879
|
+
};
|
|
1880
|
+
|
|
1881
|
+
for (const state of hntVolumeStates) {
|
|
1882
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.${state}`, {
|
|
1883
|
+
type: 'state',
|
|
1884
|
+
common: {
|
|
1885
|
+
name: hntVolumeLabels[state],
|
|
1886
|
+
type: 'number',
|
|
1887
|
+
role: STATE_ROLES.consumption,
|
|
1888
|
+
read: true,
|
|
1889
|
+
write: false,
|
|
1890
|
+
unit: 'm³',
|
|
1891
|
+
def: 0,
|
|
1892
|
+
},
|
|
1893
|
+
native: {},
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption.weekly`, {
|
|
1900
|
+
type: 'state',
|
|
1901
|
+
common: {
|
|
1902
|
+
name: `Wochenverbrauch Gesamt (${label.unit})`,
|
|
1903
|
+
type: 'number',
|
|
1904
|
+
role: STATE_ROLES.consumption,
|
|
1905
|
+
read: true,
|
|
1906
|
+
write: false,
|
|
1907
|
+
unit: label.unit,
|
|
1908
|
+
def: 0,
|
|
1909
|
+
},
|
|
1910
|
+
native: {},
|
|
1911
|
+
});
|
|
1912
|
+
|
|
1526
1913
|
// COST STATES (totals)
|
|
1527
1914
|
await adapter.setObjectNotExistsAsync(`${basePath}.costs`, {
|
|
1528
1915
|
type: 'channel',
|
|
@@ -1560,6 +1947,20 @@ async function createTotalsStructure(adapter, type) {
|
|
|
1560
1947
|
native: {},
|
|
1561
1948
|
});
|
|
1562
1949
|
|
|
1950
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.costs.weekly`, {
|
|
1951
|
+
type: 'state',
|
|
1952
|
+
common: {
|
|
1953
|
+
name: 'Wochenkosten Gesamt (€)',
|
|
1954
|
+
type: 'number',
|
|
1955
|
+
role: STATE_ROLES.cost,
|
|
1956
|
+
read: true,
|
|
1957
|
+
write: false,
|
|
1958
|
+
unit: '€',
|
|
1959
|
+
def: 0,
|
|
1960
|
+
},
|
|
1961
|
+
native: {},
|
|
1962
|
+
});
|
|
1963
|
+
|
|
1563
1964
|
await adapter.setObjectNotExistsAsync(`${basePath}.costs.totalYearly`, {
|
|
1564
1965
|
type: 'state',
|
|
1565
1966
|
common: {
|
|
@@ -1577,11 +1978,82 @@ async function createTotalsStructure(adapter, type) {
|
|
|
1577
1978
|
adapter.log.debug(`Totals state structure created for ${type}`);
|
|
1578
1979
|
}
|
|
1579
1980
|
|
|
1981
|
+
/**
|
|
1982
|
+
* Creates history structure for a specific year
|
|
1983
|
+
*
|
|
1984
|
+
* @param {object} adapter - The adapter instance
|
|
1985
|
+
* @param {string} type - 'gas', 'water', 'electricity', 'pv'
|
|
1986
|
+
* @param {string} meterName - Meter name
|
|
1987
|
+
* @param {number|string} year - Year (YYYY)
|
|
1988
|
+
* @returns {Promise<void>}
|
|
1989
|
+
*/
|
|
1990
|
+
async function createHistoryStructure(adapter, type, meterName, year) {
|
|
1991
|
+
const basePath = `${type}.${meterName}.history.${year}`;
|
|
1992
|
+
|
|
1993
|
+
await adapter.setObjectNotExistsAsync(`${type}.${meterName}.history`, {
|
|
1994
|
+
type: 'channel',
|
|
1995
|
+
common: { name: 'Historie' },
|
|
1996
|
+
native: {},
|
|
1997
|
+
});
|
|
1998
|
+
|
|
1999
|
+
await adapter.setObjectNotExistsAsync(basePath, {
|
|
2000
|
+
type: 'channel',
|
|
2001
|
+
common: { name: `Jahr ${year}` },
|
|
2002
|
+
native: { year },
|
|
2003
|
+
});
|
|
2004
|
+
|
|
2005
|
+
const unit = type === 'water' ? 'm³' : 'kWh';
|
|
2006
|
+
|
|
2007
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.consumption`, {
|
|
2008
|
+
type: 'state',
|
|
2009
|
+
common: {
|
|
2010
|
+
name: `Jahresverbrauch ${year} (${unit})`,
|
|
2011
|
+
type: 'number',
|
|
2012
|
+
role: STATE_ROLES.consumption,
|
|
2013
|
+
read: true,
|
|
2014
|
+
write: false,
|
|
2015
|
+
unit: unit,
|
|
2016
|
+
def: 0,
|
|
2017
|
+
},
|
|
2018
|
+
native: {},
|
|
2019
|
+
});
|
|
2020
|
+
|
|
2021
|
+
if (type === 'gas') {
|
|
2022
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.volume`, {
|
|
2023
|
+
type: 'state',
|
|
2024
|
+
common: {
|
|
2025
|
+
name: `Jahresverbrauch ${year} (m³)`,
|
|
2026
|
+
type: 'number',
|
|
2027
|
+
role: STATE_ROLES.consumption,
|
|
2028
|
+
read: true,
|
|
2029
|
+
write: false,
|
|
2030
|
+
unit: 'm³',
|
|
2031
|
+
def: 0,
|
|
2032
|
+
},
|
|
2033
|
+
native: {},
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
await adapter.setObjectNotExistsAsync(`${basePath}.costs`, {
|
|
2038
|
+
type: 'state',
|
|
2039
|
+
common: {
|
|
2040
|
+
name: `Jahreskosten ${year} (€)`,
|
|
2041
|
+
type: 'number',
|
|
2042
|
+
role: STATE_ROLES.cost,
|
|
2043
|
+
read: true,
|
|
2044
|
+
write: false,
|
|
2045
|
+
unit: '€',
|
|
2046
|
+
def: 0,
|
|
2047
|
+
},
|
|
2048
|
+
native: {},
|
|
2049
|
+
});
|
|
2050
|
+
}
|
|
2051
|
+
|
|
1580
2052
|
module.exports = {
|
|
1581
2053
|
createUtilityStateStructure,
|
|
1582
2054
|
createMeterStructure,
|
|
1583
2055
|
createTotalsStructure,
|
|
2056
|
+
createHistoryStructure,
|
|
1584
2057
|
deleteUtilityStateStructure,
|
|
1585
|
-
safeSetObjectNotExists,
|
|
1586
2058
|
STATE_ROLES,
|
|
1587
2059
|
};
|