iobroker.nebenkosten-monitor 1.3.1 → 1.3.2

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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  # ioBroker.nebenkosten-monitor
4
4
 
5
+ [![NPM version](https://img.shields.io/npm/v/iobroker.nebenkosten-monitor.svg)](https://www.npmjs.com/package/iobroker.nebenkosten-monitor)
5
6
  [![GitHub release](https://img.shields.io/github/v/release/fischi87/ioBroker.nebenkosten-monitor)](https://github.com/fischi87/ioBroker.nebenkosten-monitor/releases)
6
7
  [![GitHub license](https://img.shields.io/github/license/fischi87/ioBroker.nebenkosten-monitor)](https://github.com/fischi87/ioBroker.nebenkosten-monitor/blob/main/LICENSE)
7
8
  [![Test and Release](https://github.com/fischi87/ioBroker.nebenkosten-monitor/workflows/Test%20and%20Release/badge.svg)](https://github.com/fischi87/ioBroker.nebenkosten-monitor/actions)
@@ -227,6 +228,15 @@ Der Adapter setzt Zähler automatisch zurück:
227
228
 
228
229
  ## Changelog
229
230
 
231
+ ### 1.3.2 (2026-01-09)
232
+
233
+ - **NEW:** **PV / Einspeise-Unterstützung** ☀️ - Neuer Tab für Photovoltaik:
234
+ - Überwache deine Netzeinspeisung (kWh).
235
+ - Berechne deine Vergütung (Earnings) automatisch.
236
+ - Volle Unterstützung für Zählerstände, Abrechnungszeiträume und Historie.
237
+ - **NEW:** **PV-Benachrichtigungen** - Erhalte Erinnerungen auch für deine PV-Anlage (Abrechnung/Vertrag).
238
+ - **IMPROVED:** Konfigurations-Reihenfolge optimiert (Gebühren logisch gruppiert).
239
+
230
240
  ### 1.3.1 (2026-01-09)
231
241
 
232
242
  - **FIX:** Kritischer Fehler behoben: HT/NT-Datenpunkte wurden aufgrund eines internen Namensfehlers (electricity vs. strom) nicht angelegt.
@@ -172,6 +172,30 @@
172
172
  "lg": 4,
173
173
  "xl": 3
174
174
  },
175
+ "gasGrundgebuehr": {
176
+ "type": "number",
177
+ "hidden": "!data.gasAktiv",
178
+ "label": "Grundgebühr (€/Monat)",
179
+ "step": 0.01,
180
+ "default": 0,
181
+ "xs": 12,
182
+ "sm": 12,
183
+ "md": 6,
184
+ "lg": 4,
185
+ "xl": 3
186
+ },
187
+ "gasJahresgebuehr": {
188
+ "type": "number",
189
+ "hidden": "!data.gasAktiv",
190
+ "label": "Jahresgebühr (z.B. Zählermiete) (€/Jahr)",
191
+ "step": 0.01,
192
+ "default": 0,
193
+ "xs": 12,
194
+ "sm": 12,
195
+ "md": 6,
196
+ "lg": 4,
197
+ "xl": 3
198
+ },
175
199
  "_gasHtNtDivider": {
176
200
  "type": "divider",
177
201
  "hidden": "!data.gasAktiv"
@@ -272,31 +296,6 @@
272
296
  "lg": 4,
273
297
  "xl": 3
274
298
  },
275
- "gasGrundgebuehr": {
276
- "type": "number",
277
- "hidden": "!data.gasAktiv",
278
- "label": "Grundgebühr (€/Monat)",
279
- "step": 0.01,
280
- "default": 0,
281
- "xs": 12,
282
- "sm": 12,
283
- "md": 6,
284
- "lg": 4,
285
- "xl": 3
286
- },
287
- "gasJahresgebuehr": {
288
- "type": "number",
289
- "hidden": "!data.gasAktiv",
290
- "label": "Jahresgebühr (z.B. Zählermiete) (€/Jahr)",
291
- "step": 0.01,
292
- "default": 0,
293
- "xs": 12,
294
- "sm": 12,
295
- "md": 6,
296
- "lg": 4,
297
- "xl": 3
298
- },
299
-
300
299
  "_gasAbschlagHeader": {
301
300
  "type": "header",
302
301
  "text": "💳 Abschlag (Monatliche Vorauszahlung)",
@@ -646,6 +645,30 @@
646
645
  "lg": 4,
647
646
  "xl": 3
648
647
  },
648
+ "stromGrundgebuehr": {
649
+ "type": "number",
650
+ "hidden": "!data.stromAktiv",
651
+ "label": "Grundgebühr (€/Monat)",
652
+ "step": 0.01,
653
+ "default": 0,
654
+ "xs": 12,
655
+ "sm": 12,
656
+ "md": 6,
657
+ "lg": 4,
658
+ "xl": 3
659
+ },
660
+ "stromJahresgebuehr": {
661
+ "type": "number",
662
+ "hidden": "!data.stromAktiv",
663
+ "label": "Jahresgebühr (z.B. Zählermiete) (€/Jahr)",
664
+ "step": 0.01,
665
+ "default": 0,
666
+ "xs": 12,
667
+ "sm": 12,
668
+ "md": 6,
669
+ "lg": 4,
670
+ "xl": 3
671
+ },
649
672
  "_stromHtNtDivider": {
650
673
  "type": "divider",
651
674
  "hidden": "!data.stromAktiv"
@@ -741,41 +764,145 @@
741
764
  "lg": 4,
742
765
  "xl": 3
743
766
  },
744
- "stromGrundgebuehr": {
767
+ "_stromAbschlagHeader": {
768
+ "type": "header",
769
+ "text": "💳 Abschlag (Monatliche Vorauszahlung)",
770
+ "size": 4,
771
+ "hidden": "!data.stromAktiv"
772
+ },
773
+ "_stromAbschlagHelp": {
774
+ "type": "staticText",
775
+ "text": "Trage deinen monatlichen Abschlag ein. Der Adapter berechnet dann, ob du über oder unter deinem Verbrauch liegst.",
776
+ "hidden": "!data.stromAktiv",
777
+ "sm": 12,
778
+ "style": {
779
+ "fontSize": "0.9em",
780
+ "color": "#666",
781
+ "marginBottom": "10px"
782
+ },
783
+ "xs": 12,
784
+ "md": 12,
785
+ "lg": 12,
786
+ "xl": 12
787
+ },
788
+ "stromAbschlag": {
745
789
  "type": "number",
790
+ "label": "Monatlicher Abschlag (€)",
791
+ "placeholder": "z.B. 65.00",
746
792
  "hidden": "!data.stromAktiv",
747
- "label": "Grundgebühr (€/Monat)",
793
+ "sm": 12,
794
+ "md": 6,
748
795
  "step": 0.01,
749
796
  "default": 0,
750
797
  "xs": 12,
798
+ "lg": 4,
799
+ "xl": 3
800
+ }
801
+ }
802
+ },
803
+ "tabPv": {
804
+ "type": "panel",
805
+ "label": "PV / Einspeisung",
806
+ "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik00IDIyaDJ0LTJoMmgydi0yaDJ2LTJoMlY4bC01LTVoLTl2MTdoM3ptOC02aC0ydjJoMnptMC00aC0ydjJoMnptMC00aC0ydjJoMnptLTQtNGgydjRoLTJ6bTQtNGgydjRoLTJ6Ii8+PC9zdmc+",
807
+ "items": {
808
+ "_pvActivationHeader": {
809
+ "type": "header",
810
+ "text": "Grundeinstellungen",
811
+ "size": 4
812
+ },
813
+ "pvAktiv": {
814
+ "type": "checkbox",
815
+ "label": "PV-Einspeisung überwachen (Lieferung)",
816
+ "sm": 12,
817
+ "md": 6,
818
+ "newLine": true,
819
+ "xs": 12,
820
+ "lg": 6,
821
+ "xl": 6
822
+ },
823
+ "_pvSensorHeader": {
824
+ "type": "header",
825
+ "text": "Sensor-Konfiguration",
826
+ "size": 5,
827
+ "hidden": "!data.pvAktiv"
828
+ },
829
+ "pvSensorDP": {
830
+ "type": "objectId",
831
+ "label": "🔍 Sensor für Einspeisung auswählen (kWh)",
832
+ "hidden": "!data.pvAktiv",
833
+ "sm": 12,
834
+ "xs": 12,
835
+ "md": 8,
836
+ "lg": 6,
837
+ "xl": 4
838
+ },
839
+ "_pvMeterHeader": {
840
+ "type": "header",
841
+ "text": "Offset (Optional)",
842
+ "size": 5,
843
+ "hidden": "!data.pvAktiv"
844
+ },
845
+ "_pvOffsetHelp": {
846
+ "type": "staticText",
847
+ "text": "Nur nötig wenn Sensor nicht mit physischem Zähler übereinstimmt. Offset = Physischer Wert - Sensor Wert",
848
+ "hidden": "!data.pvAktiv",
849
+ "sm": 12,
850
+ "style": {
851
+ "fontSize": "0.9em",
852
+ "color": "#666",
853
+ "marginBottom": "10px"
854
+ },
855
+ "xs": 12,
856
+ "md": 12,
857
+ "lg": 12,
858
+ "xl": 12
859
+ },
860
+ "pvOffset": {
861
+ "type": "number",
862
+ "label": "Offset (kWh)",
863
+ "placeholder": "z.B. 0 (optional)",
864
+ "hidden": "!data.pvAktiv",
751
865
  "sm": 12,
752
866
  "md": 6,
867
+ "step": 0.001,
868
+ "xs": 12,
753
869
  "lg": 4,
754
870
  "xl": 3
755
871
  },
756
- "stromJahresgebuehr": {
872
+ "pvInitialReading": {
757
873
  "type": "number",
758
- "hidden": "!data.stromAktiv",
759
- "label": "Jahresgebühr (z.B. Zählermiete) (€/Jahr)",
760
- "step": 0.01,
761
- "default": 0,
874
+ "label": "Einspeise-Zählerstand bei Start (kWh)",
875
+ "placeholder": "z.B. 0 (Zählerstand am Stichtag)",
876
+ "help": "Wird für Jahres-Einspeisung verwendet: Aktuell - Beginn = Jahreseinspeisung. 💡 Jahresabschluss: Nutze pv.billing.closePeriod zum automatischen Archivieren & Zurücksetzen",
877
+ "hidden": "!data.pvAktiv",
878
+ "sm": 12,
879
+ "md": 6,
880
+ "step": 0.001,
762
881
  "xs": 12,
882
+ "lg": 4,
883
+ "xl": 3
884
+ },
885
+ "pvContractStart": {
886
+ "type": "text",
887
+ "label": "📅 Stichtag / Vertragsbeginn",
888
+ "placeholder": "z.B. 01.01.2025",
889
+ "hidden": "!data.pvAktiv",
763
890
  "sm": 12,
764
891
  "md": 6,
892
+ "xs": 12,
765
893
  "lg": 4,
766
894
  "xl": 3
767
895
  },
768
-
769
- "_stromAbschlagHeader": {
896
+ "_pvPreisHeader": {
770
897
  "type": "header",
771
- "text": "💳 Abschlag (Monatliche Vorauszahlung)",
898
+ "text": "💰 Vergütungsinformationen",
772
899
  "size": 4,
773
- "hidden": "!data.stromAktiv"
900
+ "hidden": "!data.pvAktiv"
774
901
  },
775
- "_stromAbschlagHelp": {
902
+ "_pvPriceHelp": {
776
903
  "type": "staticText",
777
- "text": "Trage deinen monatlichen Abschlag ein. Der Adapter berechnet dann, ob du über oder unter deinem Verbrauch liegst.",
778
- "hidden": "!data.stromAktiv",
904
+ "text": "Trage hier deine Einspeisevergütung ein.",
905
+ "hidden": "!data.pvAktiv",
779
906
  "sm": 12,
780
907
  "style": {
781
908
  "fontSize": "0.9em",
@@ -787,16 +914,39 @@
787
914
  "lg": 12,
788
915
  "xl": 12
789
916
  },
790
- "stromAbschlag": {
917
+ "pvPreis": {
791
918
  "type": "number",
792
- "label": "Monatlicher Abschlag (€)",
793
- "placeholder": "z.B. 65.00",
794
- "hidden": "!data.stromAktiv",
919
+ "hidden": "!data.pvAktiv",
920
+ "label": "Einspeisevergütung (€/kWh)",
921
+ "min": 0,
922
+ "step": 0.0001,
923
+ "xs": 12,
795
924
  "sm": 12,
796
925
  "md": 6,
926
+ "lg": 4,
927
+ "xl": 3
928
+ },
929
+ "pvGrundgebuehr": {
930
+ "type": "number",
931
+ "hidden": "!data.pvAktiv",
932
+ "label": "Grundgebühr (Messstellenbetrieb) (€/Monat)",
797
933
  "step": 0.01,
798
934
  "default": 0,
799
935
  "xs": 12,
936
+ "sm": 12,
937
+ "md": 6,
938
+ "lg": 4,
939
+ "xl": 3
940
+ },
941
+ "pvJahresgebuehr": {
942
+ "type": "number",
943
+ "hidden": "!data.pvAktiv",
944
+ "label": "Jahresgebühr (€/Jahr)",
945
+ "step": 0.01,
946
+ "default": 0,
947
+ "xs": 12,
948
+ "sm": 12,
949
+ "md": 6,
800
950
  "lg": 4,
801
951
  "xl": 3
802
952
  }
@@ -950,13 +1100,23 @@
950
1100
  },
951
1101
  "notificationStromEnabled": {
952
1102
  "type": "checkbox",
953
- "label": "Strom-Erinnerung",
1103
+ "label": "Strom-Erinnerung",
954
1104
  "hidden": "!data.notificationEnabled || !data.stromAktiv",
955
1105
  "sm": 12,
956
1106
  "md": 4,
957
1107
  "xs": 12,
958
1108
  "lg": 4,
959
1109
  "xl": 4
1110
+ },
1111
+ "notificationPVEnabled": {
1112
+ "type": "checkbox",
1113
+ "label": "PV-Erinnerung",
1114
+ "hidden": "!data.notificationEnabled || !data.pvAktiv",
1115
+ "sm": 12,
1116
+ "md": 4,
1117
+ "xs": 12,
1118
+ "lg": 4,
1119
+ "xl": 4
960
1120
  }
961
1121
  }
962
1122
  },
package/io-package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "nebenkosten-monitor",
4
- "version": "1.3.1",
4
+ "version": "1.3.2",
5
5
  "news": {
6
+ "1.3.2": {
7
+ "en": "New: PV/Feed-in integration! Monitor your solar feed-in and earnings. New: Notifications for PV. Improved: Reorganized config UI.",
8
+ "de": "Neu: PV/Einspeise-Integration! Überwache deine Solareinspeisung und Vergütung. Neu: Benachrichtigungen für PV. Verbessert: Aufgeräumte Konfigurations-Oberfläche."
9
+ },
6
10
  "1.3.1": {
7
11
  "en": "Fix: Critical bug where HT/NT objects were not created for non-gas utilities (missing config mapping)",
8
12
  "de": "Fix: Kritischer Fehler, bei dem HT/NT-Objekte für Strom/Wasser nicht erstellt wurden (fehlendes Config-Mapping)"
@@ -152,8 +152,8 @@ class MessagingHandler {
152
152
  return;
153
153
  }
154
154
 
155
- const types = ['gas', 'water', 'electricity'];
156
- const typesDe = { gas: 'Gas', water: 'Wasser', electricity: 'Strom' };
155
+ const types = ['gas', 'water', 'electricity', 'pv'];
156
+ const typesDe = { gas: 'Gas', water: 'Wasser', electricity: 'Strom', pv: 'PV' };
157
157
 
158
158
  for (const type of types) {
159
159
  const configType = this.adapter.consumptionManager.getConfigType(type);
@@ -30,6 +30,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
30
30
  gas: { name: 'Gas', unit: 'kWh', volumeUnit: 'm³' },
31
31
  water: { name: 'Wasser', unit: 'm³', volumeUnit: 'm³' },
32
32
  electricity: { name: 'Strom', unit: 'kWh', volumeUnit: 'kWh' },
33
+ pv: { name: 'PV', unit: 'kWh', volumeUnit: 'kWh', consumption: 'Einspeisung', cost: 'Vergütung' },
33
34
  };
34
35
 
35
36
  const label = labels[type];
@@ -47,7 +48,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
47
48
  await adapter.setObjectNotExistsAsync(`${type}.consumption`, {
48
49
  type: 'channel',
49
50
  common: {
50
- name: 'Verbrauch',
51
+ name: label.consumption || 'Verbrauch',
51
52
  },
52
53
  native: {},
53
54
  });
@@ -101,7 +102,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
101
102
  await adapter.setObjectNotExistsAsync(`${type}.consumption.daily`, {
102
103
  type: 'state',
103
104
  common: {
104
- name: `Tagesverbrauch (${label.unit})`,
105
+ name: `Tages-${(label.consumption || 'Verbrauch').toLowerCase()} (${label.unit})`,
105
106
  type: 'number',
106
107
  role: STATE_ROLES.consumption,
107
108
  read: true,
@@ -115,7 +116,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
115
116
  await adapter.setObjectNotExistsAsync(`${type}.consumption.monthly`, {
116
117
  type: 'state',
117
118
  common: {
118
- name: `Monatsverbrauch (${label.unit})`,
119
+ name: `Monats-${(label.consumption || 'Verbrauch').toLowerCase()} (${label.unit})`,
119
120
  type: 'number',
120
121
  role: STATE_ROLES.consumption,
121
122
  read: true,
@@ -129,7 +130,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
129
130
  await adapter.setObjectNotExistsAsync(`${type}.consumption.yearly`, {
130
131
  type: 'state',
131
132
  common: {
132
- name: `Jahresverbrauch (${label.unit})`,
133
+ name: `Jahres-${(label.consumption || 'Verbrauch').toLowerCase()} (${label.unit})`,
133
134
  type: 'number',
134
135
  role: STATE_ROLES.consumption,
135
136
  read: true,
@@ -145,6 +146,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
145
146
  electricity: 'strom',
146
147
  water: 'wasser',
147
148
  gas: 'gas',
149
+ pv: 'pv',
148
150
  };
149
151
  const configType = configTypeMap[type] || type;
150
152
 
@@ -195,7 +197,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
195
197
  await adapter.setObjectNotExistsAsync(`${type}.costs`, {
196
198
  type: 'channel',
197
199
  common: {
198
- name: 'Kosten',
200
+ name: label.cost || 'Kosten',
199
201
  },
200
202
  native: {},
201
203
  });
@@ -203,7 +205,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
203
205
  await adapter.setObjectNotExistsAsync(`${type}.costs.daily`, {
204
206
  type: 'state',
205
207
  common: {
206
- name: 'Tageskosten (€)',
208
+ name: `Tages-${(label.cost || 'Kosten').toLowerCase()} (€)`,
207
209
  type: 'number',
208
210
  role: STATE_ROLES.cost,
209
211
  read: true,
@@ -217,7 +219,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
217
219
  await adapter.setObjectNotExistsAsync(`${type}.costs.monthly`, {
218
220
  type: 'state',
219
221
  common: {
220
- name: 'Monatskosten (€)',
222
+ name: `Monats-${(label.cost || 'Kosten').toLowerCase()} (€)`,
221
223
  type: 'number',
222
224
  role: STATE_ROLES.cost,
223
225
  read: true,
@@ -231,7 +233,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
231
233
  await adapter.setObjectNotExistsAsync(`${type}.costs.yearly`, {
232
234
  type: 'state',
233
235
  common: {
234
- name: 'Jahreskosten (€)',
236
+ name: `Jahres-${(label.cost || 'Kosten').toLowerCase()} (€)`,
235
237
  type: 'number',
236
238
  role: STATE_ROLES.cost,
237
239
  read: true,
@@ -333,7 +335,7 @@ async function createUtilityStateStructure(adapter, type, _config = {}) {
333
335
  await adapter.setObjectNotExistsAsync(`${type}.costs.totalYearly`, {
334
336
  type: 'state',
335
337
  common: {
336
- name: 'Gesamtkosten Jahr (Verbrauch + Grundgebühr) (€)',
338
+ name: `Gesamt-${(label.cost || 'Kosten').toLowerCase()} Jahr (Verbrauch + Grundgebühr) (€)`,
337
339
  type: 'number',
338
340
  role: STATE_ROLES.cost,
339
341
  read: true,
package/main.js CHANGED
@@ -42,6 +42,7 @@ class NebenkostenMonitor extends utils.Adapter {
42
42
  await this.initializeUtility('gas', this.config.gasAktiv);
43
43
  await this.initializeUtility('water', this.config.wasserAktiv);
44
44
  await this.initializeUtility('electricity', this.config.stromAktiv);
45
+ await this.initializeUtility('pv', this.config.pvAktiv);
45
46
 
46
47
  // Subscribe to billing period closure triggers
47
48
  this.subscribeStates('*.billing.closePeriod');
@@ -169,7 +170,7 @@ class NebenkostenMonitor extends utils.Adapter {
169
170
  }
170
171
 
171
172
  // Determine which utility this sensor belongs to
172
- const types = ['gas', 'water', 'electricity'];
173
+ const types = ['gas', 'water', 'electricity', 'pv'];
173
174
  for (const type of types) {
174
175
  const configType = this.consumptionManager.getConfigType(type);
175
176
  if (this.config[`${configType}Aktiv`] && this.config[`${configType}SensorDP`] === id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.nebenkosten-monitor",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Überwachung von Gas, Wasser und Strom mit Kostenrechnung",
5
5
  "author": {
6
6
  "name": "fischi87",