iobroker.tibberlink 2.2.1 → 2.3.1

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
@@ -96,6 +96,21 @@ If you enjoyed this project — or just feeling generous, consider buying me a b
96
96
 
97
97
  ! Note that missing version entries are typically dependency updates for improved security.
98
98
 
99
+ ### 2.3.1 (2024-03-10)
100
+
101
+ - (HombachC) BREAKING: Calculator channels of type 'smart battery buffer' will now switch outputs to 'OFF' only once, directly after setting the channel to Active=false (#332)
102
+ - (HombachC) Fixed error in jsonConfig.json (#329)
103
+ - (HombachC) deleted feed disconnect debug-message, cause warn message already exists
104
+ - (HombachC) bump typescript-eslint to gen 7
105
+ - (HombachC) bump dependencies
106
+
107
+ ### 2.2.2 (2024-02-19)
108
+
109
+ - (HombachC) simplify internal state handling
110
+ - (HombachC) shorten home string in Calculator screen (#317)
111
+ - (HombachC) fix feedback loop trap (#321)
112
+ - (HombachC) add some tooltips to config screen (#317)
113
+
99
114
  ### 2.2.1 (2024-02-08)
100
115
 
101
116
  - (HombachC) fix edge case problems with defect feed data from Tibber server (#312)
@@ -431,6 +431,7 @@
431
431
  "md": 6,
432
432
  "lg": 4
433
433
  },
434
+
434
435
  "FeedConfigPowerFactor": {
435
436
  "type": "checkbox",
436
437
  "label": "PowerFactor",
@@ -440,7 +441,6 @@
440
441
  "lg": 4,
441
442
  "newLine": true
442
443
  },
443
-
444
444
  "FeedConfigSignalStrength": {
445
445
  "type": "checkbox",
446
446
  "label": "SignalStrength",
@@ -465,7 +465,8 @@
465
465
  "pl": "Wartości napięcia i prądu - W przypadku kilku liczników te wartości mogą nie być uwzględnione w ramce danych, co może skutkować wartościami zerowymi. Inne odstępstwa mogą również wystąpić na podstawie konkretnej wersji firmware licznika. Wartości zerowe nie wygenerują stanu w twoich obiektach ioBroker.",
466
466
  "uk": "Значення напруги та струму - В разі кількох лічильників ці значення можуть не включати в кадр даних, що може призвести до нульових значень. Інші відхилення також можуть виникнути на основі конкретної прошивки лічильника. Нульові значення не створять стан в ваших об'єктах ioBroker.",
467
467
  "zh-cn": "电压和电流数值 - 在多台仪表的情况下,这些数值可能不包括在数据帧中,可能导致空值。根据电表的具体固件,还可能出现其他偏差。空值不会在您的ioBroker对象中生成状态。"
468
- }
468
+ },
469
+ "newLine": true
469
470
  },
470
471
 
471
472
  "FeedConfigVoltagePhase1": {
@@ -618,7 +619,20 @@
618
619
  "filter": false,
619
620
  "sort": false,
620
621
  "width": "10% ",
621
- "command": "HomesForConfig"
622
+ "command": "HomesForCalculator",
623
+ "tooltip": {
624
+ "en": "select the home this channel should be attached to",
625
+ "de": "Wählen Sie das Zuhause aus, an das dieser Kanal angehängt werden soll",
626
+ "ru": "выберите дом, к которому должен быть присоединен этот канал",
627
+ "pt": "selecione a casa à qual este canal deve ser anexado",
628
+ "nl": "selecteer het huis waaraan dit kanaal moet worden gekoppeld",
629
+ "fr": "sélectionnez la maison à laquelle ce canal doit être attaché",
630
+ "it": "seleziona la casa a cui questo canale dovrebbe essere collegato",
631
+ "es": "seleccione el hogar al que este canal debe estar adjunto",
632
+ "pl": "wybierz dom, do którego ten kanał powinien być podłączony",
633
+ "uk": "виберіть будинок, до якого має бути приєднаний цей канал",
634
+ "zh-cn": "选择要连接到的主页"
635
+ }
622
636
  },
623
637
  {
624
638
  "type": "select",
@@ -635,6 +649,19 @@
635
649
  "uk": "Тип каналу",
636
650
  "zh-cn": "通道类型"
637
651
  },
652
+ "tooltip": {
653
+ "en": "Channels have to be activated or deactivated in a corresponding state",
654
+ "de": "Kanäle müssen in einem entsprechenden Zustand aktiviert oder deaktiviert werden",
655
+ "ru": "Каналы должны быть активированы или деактивированы в соответствующем состоянии",
656
+ "pt": "Os canais devem ser ativados ou desativados em um estado correspondente",
657
+ "nl": "Kanalen moeten worden geactiveerd of gedeactiveerd in een overeenkomstige staat",
658
+ "fr": "Les chaînes doivent être activées ou désactivées dans un état correspondant",
659
+ "it": "I canali devono essere attivati o disattivati in uno stato corrispondente",
660
+ "es": "Los canales deben activarse o desactivarse en un estado correspondiente",
661
+ "pl": "Kanały muszą być aktywowane lub dezaktywowane w odpowiednim stanie",
662
+ "uk": "Канали повинні бути активовані або деактивовані в відповідному стані",
663
+ "zh-cn": "通道必须在相应状态下激活或停用"
664
+ },
638
665
  "attr": "chType",
639
666
  "options": [
640
667
  {
@@ -752,7 +779,7 @@
752
779
  ],
753
780
  "filter": false,
754
781
  "sort": false,
755
- "width": "15% "
782
+ "width": "15%"
756
783
  },
757
784
  {
758
785
  "type": "text",
@@ -769,11 +796,24 @@
769
796
  "uk": "Назва каналу",
770
797
  "zh-cn": "通道名称"
771
798
  },
799
+ "tooltip": {
800
+ "en": "channel name to better identify your states",
801
+ "de": "Kanalname zur besseren Identifizierung Ihrer Zustände",
802
+ "ru": "название канала для лучшей идентификации ваших состояний",
803
+ "pt": "nome do canal para identificar melhor seus estados",
804
+ "nl": "kanaalnaam om uw toestanden beter te identificeren",
805
+ "fr": "nom du canal pour mieux identifier vos états",
806
+ "it": "nome del canale per identificare meglio i tuoi stati",
807
+ "es": "nombre del canal para identificar mejor tus estados",
808
+ "pl": "nazwa kanału do lepszego zidentyfikowania twoich stanów",
809
+ "uk": "назва каналу для кращої ідентифікації ваших станів",
810
+ "zh-cn": "通道名称以更好地识别您的状态"
811
+ },
772
812
  "maxLength": 25,
773
813
  "attr": "chName",
774
814
  "filter": false,
775
815
  "sort": false,
776
- "width": "15% ",
816
+ "width": "15%",
777
817
  "default": "Channel Name"
778
818
  },
779
819
  {
@@ -794,7 +834,7 @@
794
834
  "attr": "chTargetState",
795
835
  "filter": false,
796
836
  "sort": false,
797
- "width": "15% "
837
+ "width": "15%"
798
838
  },
799
839
  {
800
840
  "type": "text",
@@ -811,11 +851,24 @@
811
851
  "uk": "Значення ТАК",
812
852
  "zh-cn": "值 是"
813
853
  },
854
+ "tooltip": {
855
+ "en": "The values to be written to the output state can be defined in 'value YES' and 'value NO,' e.g., 'true' for boolean states, or a number or text to be written.",
856
+ "de": "Die Werte, die in den Ausgabestatus geschrieben werden sollen, können in 'Wert JA' und 'Wert NEIN' definiert werden, z.B. 'true' für boolesche Zustände oder eine Zahl oder Text, der geschrieben werden soll.",
857
+ "ru": "Значения, которые должны быть записаны в состояние вывода, могут быть определены в 'значение ДА' и 'значение НЕТ', например, 'true' для булевых состояний или число или текст, который должен быть записан.",
858
+ "pt": "Os valores a serem escritos no estado de saída podem ser definidos em 'valor SIM' e 'valor NÃO', por exemplo, 'true' para estados booleanos, ou um número ou texto a ser escrito.",
859
+ "nl": "De waarden die moeten worden geschreven naar de uitvoerstatus kunnen worden gedefinieerd in 'waarde JA' en 'waarde NEE', bijvoorbeeld 'true' voor booleaanse toestanden, of een getal of tekst om te schrijven.",
860
+ "fr": "Les valeurs à écrire dans l'état de sortie peuvent être définies dans 'valeur OUI' et 'valeur NON', par exemple 'true' pour les états booléens, ou un nombre ou un texte à écrire.",
861
+ "it": "I valori da scrivere nello stato di uscita possono essere definiti in 'valore SÌ' e 'valore NO', ad esempio 'true' per gli stati booleani, o un numero o un testo da scrivere.",
862
+ "es": "Los valores que se deben escribir en el estado de salida se pueden definir en 'valor SÍ' y 'valor NO', por ejemplo, 'true' para estados booleanos, o un número o texto que se debe escribir.",
863
+ "pl": "Wartości do zapisania w stanie wyjściowym można zdefiniować w 'wartość TAK' i 'wartość NIE', na przykład 'true' dla stanów logicznych lub liczby lub tekst do zapisania.",
864
+ "uk": "Значення, які слід записувати в вихідний стан, можуть бути визначені у 'значення ТАК' і 'значення НІ', наприклад, 'true' для булевих станів або число або текст для запису.",
865
+ "zh-cn": "要写入输出状态的值可以在'值是'和'值否'中定义,例如,对于布尔状态可以使用'true',或者可以写入数字或文本。"
866
+ },
814
867
  "maxLength": 20,
815
868
  "attr": "chValueOn",
816
869
  "filter": false,
817
870
  "sort": false,
818
- "width": "7.5% ",
871
+ "width": "10%",
819
872
  "default": ""
820
873
  },
821
874
  {
@@ -833,11 +886,24 @@
833
886
  "uk": "Значення НІ",
834
887
  "zh-cn": "值 否"
835
888
  },
889
+ "tooltip": {
890
+ "en": "The values to be written to the output state can be defined in 'value YES' and 'value NO,' e.g., 'true' for boolean states, or a number or text to be written.",
891
+ "de": "Die Werte, die in den Ausgabestatus geschrieben werden sollen, können in 'Wert JA' und 'Wert NEIN' definiert werden, z.B. 'true' für boolesche Zustände oder eine Zahl oder Text, der geschrieben werden soll.",
892
+ "ru": "Значения, которые должны быть записаны в состояние вывода, могут быть определены в 'значение ДА' и 'значение НЕТ', например, 'true' для булевых состояний или число или текст, который должен быть записан.",
893
+ "pt": "Os valores a serem escritos no estado de saída podem ser definidos em 'valor SIM' e 'valor NÃO', por exemplo, 'true' para estados booleanos, ou um número ou texto a ser escrito.",
894
+ "nl": "De waarden die moeten worden geschreven naar de uitvoerstatus kunnen worden gedefinieerd in 'waarde JA' en 'waarde NEE', bijvoorbeeld 'true' voor booleaanse toestanden, of een getal of tekst om te schrijven.",
895
+ "fr": "Les valeurs à écrire dans l'état de sortie peuvent être définies dans 'valeur OUI' et 'valeur NON', par exemple 'true' pour les états booléens, ou un nombre ou un texte à écrire.",
896
+ "it": "I valori da scrivere nello stato di uscita possono essere definiti in 'valore SÌ' e 'valore NO', ad esempio 'true' per gli stati booleani, o un numero o un testo da scrivere.",
897
+ "es": "Los valores que se deben escribir en el estado de salida se pueden definir en 'valor SÍ' y 'valor NO', por ejemplo, 'true' para estados booleanos, o un número o texto que se debe escribir.",
898
+ "pl": "Wartości do zapisania w stanie wyjściowym można zdefiniować w 'wartość TAK' i 'wartość NIE', na przykład 'true' dla stanów logicznych lub liczby lub tekst do zapisania.",
899
+ "uk": "Значення, які слід записувати в вихідний стан, можуть бути визначені у 'значення ТАК' і 'значення НІ', наприклад, 'true' для булевих станів або число або текст для запису.",
900
+ "zh-cn": "要写入输出状态的值可以在'值是'和'值否'中定义,例如,对于布尔状态可以使用'true',或者可以写入数字或文本。"
901
+ },
836
902
  "maxLength": 20,
837
903
  "attr": "chValueOff",
838
904
  "filter": false,
839
905
  "sort": false,
840
- "width": "7.5% ",
906
+ "width": "7.5%",
841
907
  "default": ""
842
908
  },
843
909
 
@@ -859,7 +925,7 @@
859
925
  "attr": "chTargetState2",
860
926
  "filter": false,
861
927
  "sort": false,
862
- "width": "15% ",
928
+ "width": "15%",
863
929
  "hidden": "data.chType !== 7"
864
930
  },
865
931
  {
@@ -877,11 +943,24 @@
877
943
  "uk": "Значення ТАК 2",
878
944
  "zh-cn": "值 是 2"
879
945
  },
946
+ "tooltip": {
947
+ "en": "The values to be written to the output state can be defined in 'value YES' and 'value NO,' e.g., 'true' for boolean states, or a number or text to be written.",
948
+ "de": "Die Werte, die in den Ausgabestatus geschrieben werden sollen, können in 'Wert JA' und 'Wert NEIN' definiert werden, z.B. 'true' für boolesche Zustände oder eine Zahl oder Text, der geschrieben werden soll.",
949
+ "ru": "Значения, которые должны быть записаны в состояние вывода, могут быть определены в 'значение ДА' и 'значение НЕТ', например, 'true' для булевых состояний или число или текст, который должен быть записан.",
950
+ "pt": "Os valores a serem escritos no estado de saída podem ser definidos em 'valor SIM' e 'valor NÃO', por exemplo, 'true' para estados booleanos, ou um número ou texto a ser escrito.",
951
+ "nl": "De waarden die moeten worden geschreven naar de uitvoerstatus kunnen worden gedefinieerd in 'waarde JA' en 'waarde NEE', bijvoorbeeld 'true' voor booleaanse toestanden, of een getal of tekst om te schrijven.",
952
+ "fr": "Les valeurs à écrire dans l'état de sortie peuvent être définies dans 'valeur OUI' et 'valeur NON', par exemple 'true' pour les états booléens, ou un nombre ou un texte à écrire.",
953
+ "it": "I valori da scrivere nello stato di uscita possono essere definiti in 'valore SÌ' e 'valore NO', ad esempio 'true' per gli stati booleani, o un numero o un testo da scrivere.",
954
+ "es": "Los valores que se deben escribir en el estado de salida se pueden definir en 'valor SÍ' y 'valor NO', por ejemplo, 'true' para estados booleanos, o un número o texto que se debe escribir.",
955
+ "pl": "Wartości do zapisania w stanie wyjściowym można zdefiniować w 'wartość TAK' i 'wartość NIE', na przykład 'true' dla stanów logicznych lub liczby lub tekst do zapisania.",
956
+ "uk": "Значення, які слід записувати в вихідний стан, можуть бути визначені у 'значення ТАК' і 'значення НІ', наприклад, 'true' для булевих станів або число або текст для запису.",
957
+ "zh-cn": "要写入输出状态的值可以在'值是'和'值否'中定义,例如,对于布尔状态可以使用'true',或者可以写入数字或文本。"
958
+ },
880
959
  "maxLength": 20,
881
960
  "attr": "chValueOn2",
882
961
  "filter": false,
883
962
  "sort": false,
884
- "width": "7.5% ",
963
+ "width": "7.5%",
885
964
  "default": "",
886
965
  "hidden": "data.chType !== 7"
887
966
  },
@@ -900,11 +979,24 @@
900
979
  "uk": "Значення НІ 2",
901
980
  "zh-cn": "值 否 2"
902
981
  },
982
+ "tooltip": {
983
+ "en": "The values to be written to the output state can be defined in 'value YES' and 'value NO,' e.g., 'true' for boolean states, or a number or text to be written.",
984
+ "de": "Die Werte, die in den Ausgabestatus geschrieben werden sollen, können in 'Wert JA' und 'Wert NEIN' definiert werden, z.B. 'true' für boolesche Zustände oder eine Zahl oder Text, der geschrieben werden soll.",
985
+ "ru": "Значения, которые должны быть записаны в состояние вывода, могут быть определены в 'значение ДА' и 'значение НЕТ', например, 'true' для булевых состояний или число или текст, который должен быть записан.",
986
+ "pt": "Os valores a serem escritos no estado de saída podem ser definidos em 'valor SIM' e 'valor NÃO', por exemplo, 'true' para estados booleanos, ou um número ou texto a ser escrito.",
987
+ "nl": "De waarden die moeten worden geschreven naar de uitvoerstatus kunnen worden gedefinieerd in 'waarde JA' en 'waarde NEE', bijvoorbeeld 'true' voor booleaanse toestanden, of een getal of tekst om te schrijven.",
988
+ "fr": "Les valeurs à écrire dans l'état de sortie peuvent être définies dans 'valeur OUI' et 'valeur NON', par exemple 'true' pour les états booléens, ou un nombre ou un texte à écrire.",
989
+ "it": "I valori da scrivere nello stato di uscita possono essere definiti in 'valore SÌ' e 'valore NO', ad esempio 'true' per gli stati booleani, o un numero o un testo da scrivere.",
990
+ "es": "Los valores que se deben escribir en el estado de salida se pueden definir en 'valor SÍ' y 'valor NO', por ejemplo, 'true' para estados booleanos, o un número o texto que se debe escribir.",
991
+ "pl": "Wartości do zapisania w stanie wyjściowym można zdefiniować w 'wartość TAK' i 'wartość NIE', na przykład 'true' dla stanów logicznych lub liczby lub tekst do zapisania.",
992
+ "uk": "Значення, які слід записувати в вихідний стан, можуть бути визначені у 'значення ТАК' і 'значення НІ', наприклад, 'true' для булевих станів або число або текст для запису.",
993
+ "zh-cn": "要写入输出状态的值可以在'值是'和'值否'中定义,例如,对于布尔状态可以使用'true',或者可以写入数字或文本。"
994
+ },
903
995
  "maxLength": 20,
904
996
  "attr": "chValueOff2",
905
997
  "filter": false,
906
998
  "sort": false,
907
- "width": "7.5% ",
999
+ "width": "7.5%",
908
1000
  "default": "",
909
1001
  "hidden": "data.chType !== 7"
910
1002
  }
@@ -53,7 +53,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
53
53
  this.adapter.config.CalculatorList[channel].chName = `Channel Name`;
54
54
  }
55
55
  const channelName = this.adapter.config.CalculatorList[channel].chName;
56
- //#region *** setup channel folder ***
56
+ //#region *** setup channel folders ***
57
57
  let typeDesc;
58
58
  switch (this.adapter.config.CalculatorList[channel].chType) {
59
59
  case tibberHelper_1.enCalcType.BestCost:
@@ -89,7 +89,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
89
89
  native: {},
90
90
  });
91
91
  //#endregion
92
- //#region *** setup chActive state object ***
92
+ //#region *** setup chActive state object for all channel types ***
93
93
  if (this.adapter.config.CalculatorList[channel].chActive === undefined) {
94
94
  this.adapter.config.CalculatorList[channel].chActive = false;
95
95
  }
@@ -103,17 +103,24 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
103
103
  this.adapter.log.debug(`Wrong type for chActive: ${valueActive}`);
104
104
  }
105
105
  //#endregion
106
- //"best cost": Defined by the "TriggerPrice" state as input.
107
- //"best single hours": Defined by the "AmountHours" state as input.
108
- //"best hours block": Defined by the "AmountHours" state as input.
109
- //"best hours block": Writes data to the "AverageTotalCost", "BlockStartFullHour", "BlockEndFullHour" states as output.
110
- //"best cost LTF": Defined by the "TriggerPrice", "StartTime", "StopTime", "RepeatDays" states as input.
111
- //"best single hours LTF": Defined by the "AmountHours", "StartTime", "StopTime", "RepeatDays" states as input.
112
- //"best hours block LTF": Defined by the "AmountHours", "StartTime", "StopTime", "RepeatDays" states as input.
113
- //"smart battery buffer": Defined by the "AmountHours", "EfficiencyLoss" states as input.
106
+ /* "best cost" | Input state: "TriggerPrice"
107
+ | Output state: "Output"
108
+ "best single hours" | Input state: "AmountHours"
109
+ | Output state: "Output"
110
+ "best hours block" | Input state: "AmountHours"
111
+ | Output state: "Output", "AverageTotalCost", "BlockStartFullHour", "BlockEndFullHour"
112
+ "best cost LTF" | Input state: "TriggerPrice", "StartTime", "StopTime", "RepeatDays"
113
+ | Output state: "Output"
114
+ "best single hours LTF" | Input state: "AmountHours", "StartTime", "StopTime", "RepeatDays"
115
+ | Output state: "Output"
116
+ "best hours block LTF" | Input state: "AmountHours", "StartTime", "StopTime", "RepeatDays"
117
+ | Output state: "Output"
118
+ "smart battery buffer" | Input state: "AmountHours", "EfficiencyLoss"
119
+ | Output state: "Output", "Output2"
120
+ */
114
121
  switch (this.adapter.config.CalculatorList[channel].chType) {
115
122
  case tibberHelper_1.enCalcType.BestCost:
116
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`).value);
123
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`).value); // INPUTS
117
124
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StartTime`).value);
118
125
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StopTime`).value);
119
126
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
@@ -122,9 +129,18 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
122
129
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStartTime`).value);
123
130
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStopTime`).value);
124
131
  await this.setup_chTriggerPrice(homeId, channel);
132
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
133
+ // WIP
134
+ if (this.adapter.config.CalculatorList[channel].chTargetState.length > 10) {
135
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output`).value);
136
+ }
137
+ else {
138
+ // await this.setup_chOutput(homeId, channel);
139
+ }
140
+ //WIP
125
141
  break;
126
142
  case tibberHelper_1.enCalcType.BestSingleHours:
127
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value);
143
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value); // INPUTS
128
144
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StartTime`).value);
129
145
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StopTime`).value);
130
146
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
@@ -133,9 +149,10 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
133
149
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStartTime`).value);
134
150
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStopTime`).value);
135
151
  await this.setup_chAmountHours(homeId, channel);
152
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
136
153
  break;
137
154
  case tibberHelper_1.enCalcType.BestHoursBlock:
138
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value);
155
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value); // INPUTS
139
156
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StartTime`).value);
140
157
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StopTime`).value);
141
158
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
@@ -144,9 +161,10 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
144
161
  await this.setup_chAverageTotalCost(homeId, channel);
145
162
  await this.setup_chBlockStartFullHour(homeId, channel);
146
163
  await this.setup_chBlockEndFullHour(homeId, channel);
164
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
147
165
  break;
148
166
  case tibberHelper_1.enCalcType.BestCostLTF:
149
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`).value);
167
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`).value); // INPUTS
150
168
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
151
169
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AverageTotalCost`).value);
152
170
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStartTime`).value);
@@ -155,9 +173,10 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
155
173
  await this.setup_chStartTime(homeId, channel);
156
174
  await this.setup_chStopTime(homeId, channel);
157
175
  await this.setup_chRepeatDays(homeId, channel);
176
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
158
177
  break;
159
178
  case tibberHelper_1.enCalcType.BestSingleHoursLTF:
160
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value);
179
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value); // INPUTS
161
180
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
162
181
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `AverageTotalCost`).value);
163
182
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `BlockStartTime`).value);
@@ -166,9 +185,10 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
166
185
  await this.setup_chStartTime(homeId, channel);
167
186
  await this.setup_chStopTime(homeId, channel);
168
187
  await this.setup_chRepeatDays(homeId, channel);
188
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
169
189
  break;
170
190
  case tibberHelper_1.enCalcType.BestHoursBlockLTF:
171
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value);
191
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value); // INPUTS
172
192
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`).value);
173
193
  await this.setup_chAmountHours(homeId, channel);
174
194
  await this.setup_chStartTime(homeId, channel);
@@ -177,9 +197,10 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
177
197
  await this.setup_chAverageTotalCost(homeId, channel);
178
198
  await this.setup_chBlockStartFullHour(homeId, channel);
179
199
  await this.setup_chBlockEndFullHour(homeId, channel);
200
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `Output2`).value); // OUTPUTS
180
201
  break;
181
202
  case tibberHelper_1.enCalcType.SmartBatteryBuffer:
182
- this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value);
203
+ this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`).value); // INPUTS
183
204
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StartTime`).value);
184
205
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `StopTime`).value);
185
206
  this.adapter.delObjectAsync(this.getStatePrefix(homeId, `Calculations.${channel}`, `RepeatDays`).value);
@@ -191,10 +212,18 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
191
212
  break;
192
213
  default:
193
214
  this.adapter.log.error(`Calculator Type for channel ${channel} not set, please do!`);
194
- }
195
- //*** subscribeStates ***
196
- this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.*`);
215
+ } //end setup and delete channel states according to channel type
216
+ //#region *** subscribe state changes ***
217
+ // WIP - ORIGINAL: this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.*`);
197
218
  // all states changes inside the calculator channel settings namespace are subscribed
219
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.Active`);
220
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.TriggerPrice`);
221
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.AmountHours`);
222
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.StartTime`);
223
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.StopTime`);
224
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.RepeatDays`);
225
+ this.adapter.subscribeStates(`Homes.${homeId}.Calculations.${channel}.EfficiencyLoss`);
226
+ //#endregion
198
227
  }
199
228
  catch (error) {
200
229
  this.adapter.log.warn(this.generateErrorMessage(error, `setup of states for calculator`));
@@ -206,7 +235,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
206
235
  if (this.adapter.config.CalculatorList[channel].chTriggerPrice === undefined) {
207
236
  this.adapter.config.CalculatorList[channel].chTriggerPrice = 0;
208
237
  }
209
- this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`), this.adapter.config.CalculatorList[channel].chTriggerPrice, `pricelevel to trigger this channel at`, true, true);
238
+ this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `TriggerPrice`), this.adapter.config.CalculatorList[channel].chTriggerPrice, `pricelevel to trigger this channel at`, undefined, true, true);
210
239
  const valueTriggerPrice = await this.getStateValue(`Homes.${homeId}.Calculations.${channel}.TriggerPrice`);
211
240
  if (typeof valueTriggerPrice === "number") {
212
241
  this.adapter.config.CalculatorList[channel].chTriggerPrice = valueTriggerPrice;
@@ -227,7 +256,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
227
256
  if (this.adapter.config.CalculatorList[channel].chAmountHours === undefined) {
228
257
  this.adapter.config.CalculatorList[channel].chAmountHours = 0;
229
258
  }
230
- this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`), this.adapter.config.CalculatorList[channel].chAmountHours, `amount of hours to trigger this channel`, true, true);
259
+ this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `AmountHours`), this.adapter.config.CalculatorList[channel].chAmountHours, `amount of hours to trigger this channel`, undefined, true, true);
231
260
  const valueAmountHours = await this.getStateValue(`Homes.${homeId}.Calculations.${channel}.AmountHours`);
232
261
  if (typeof valueAmountHours === "number") {
233
262
  this.adapter.config.CalculatorList[channel].chAmountHours = valueAmountHours;
@@ -244,7 +273,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
244
273
  async setup_chStartTime(homeId, channel) {
245
274
  try {
246
275
  const channelName = this.adapter.config.CalculatorList[channel].chName;
247
- //*** chAmountHours ***
276
+ //*** chStartTime ***
248
277
  if (this.adapter.config.CalculatorList[channel].chStartTime === undefined) {
249
278
  const today = new Date();
250
279
  today.setHours(0, 0, 0, 0); // sets clock to 0:00
@@ -267,7 +296,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
267
296
  async setup_chStopTime(homeId, channel) {
268
297
  try {
269
298
  const channelName = this.adapter.config.CalculatorList[channel].chName;
270
- //*** chAmountHours ***
299
+ //*** chStopTime ***
271
300
  if (this.adapter.config.CalculatorList[channel].chStopTime === undefined) {
272
301
  const today = new Date();
273
302
  today.setHours(23, 59, 0, 0); // sets clock to 0:00
@@ -294,7 +323,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
294
323
  if (this.adapter.config.CalculatorList[channel].chRepeatDays === undefined) {
295
324
  this.adapter.config.CalculatorList[channel].chRepeatDays = 0;
296
325
  }
297
- this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `RepeatDays`), this.adapter.config.CalculatorList[channel].chRepeatDays, `number of days to shift this LTF channel for repetition`, true, true);
326
+ this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `RepeatDays`), this.adapter.config.CalculatorList[channel].chRepeatDays, `number of days to shift this LTF channel for repetition`, undefined, true, true);
298
327
  const valueRepeatDays = await this.getStateValue(`Homes.${homeId}.Calculations.${channel}.RepeatDays`);
299
328
  if (typeof valueRepeatDays === "number") {
300
329
  this.adapter.config.CalculatorList[channel].chRepeatDays = valueRepeatDays;
@@ -315,7 +344,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
315
344
  if (this.adapter.config.CalculatorList[channel].chEfficiencyLoss === undefined) {
316
345
  this.adapter.config.CalculatorList[channel].chEfficiencyLoss = 0;
317
346
  }
318
- this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`), this.adapter.config.CalculatorList[channel].chEfficiencyLoss, `efficiency loss between charge and discharge of battery system`, true, true);
347
+ this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `EfficiencyLoss`), this.adapter.config.CalculatorList[channel].chEfficiencyLoss, `efficiency loss between charge and discharge of battery system`, undefined, true, true);
319
348
  const valueEfficiencyLoss = await this.getStateValue(`Homes.${homeId}.Calculations.${channel}.EfficiencyLoss`);
320
349
  if (typeof valueEfficiencyLoss === "number") {
321
350
  this.adapter.config.CalculatorList[channel].chAmountHours = valueEfficiencyLoss;
@@ -332,7 +361,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
332
361
  async setup_chAverageTotalCost(homeId, channel) {
333
362
  try {
334
363
  const channelName = this.adapter.config.CalculatorList[channel].chName;
335
- this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `AverageTotalCost`), 0, `average total cost in determined block`, false, false);
364
+ this.checkAndSetValueNumber(this.getStatePrefix(homeId, `Calculations.${channel}`, `AverageTotalCost`), 0, `average total cost in determined block`, undefined, false, false);
336
365
  this.adapter.log.debug(`setup calculator output state AverageTotalCost in home: ${homeId} - channel: ${channel}-${channelName}`);
337
366
  }
338
367
  catch (error) {
@@ -365,9 +394,13 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
365
394
  this.adapter.log.warn(this.generateErrorMessage(error, `write state BlockEndFullHour for calculator`));
366
395
  }
367
396
  }
368
- async startCalculatorTasks() {
397
+ async startCalculatorTasks(onStateChange) {
398
+ if (onStateChange === undefined)
399
+ onStateChange = false;
369
400
  if (!this.adapter.config.UseCalculator)
370
401
  return;
402
+ const badComponents = ["tibberlink", "Homes", "Calculations"]; // we must not use an input as output!!
403
+ // WIP einen first Run mode implementieren, das muss nicht bei jedem Lauf durchgegangen werden
371
404
  for (const channel in this.adapter.config.CalculatorList) {
372
405
  if (!this.adapter.config.CalculatorList[channel] ||
373
406
  !this.adapter.config.CalculatorList[channel].chTargetState ||
@@ -375,6 +408,17 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
375
408
  this.adapter.log.warn(`Empty destination state in calculator channel ${channel} defined - provide correct external state - execution of channel skipped`);
376
409
  continue;
377
410
  }
411
+ const chTargetStateComponents = this.adapter.config.CalculatorList[channel].chTargetState.split(".");
412
+ let foundAllBadComponents = true;
413
+ badComponents.forEach((badComponent) => {
414
+ if (!chTargetStateComponents.includes(badComponent))
415
+ foundAllBadComponents = false;
416
+ });
417
+ // WIP - oder enthält "Output"....
418
+ if (foundAllBadComponents) {
419
+ this.adapter.log.error(`Invalid destination state defined in calculator channel ${channel}. Please avoid specifying the activation state of this channel as the destination. Skipping channel execution.`);
420
+ continue;
421
+ }
378
422
  if (this.adapter.config.CalculatorList[channel].chType === tibberHelper_1.enCalcType.SmartBatteryBuffer) {
379
423
  if (!this.adapter.config.CalculatorList[channel] ||
380
424
  !this.adapter.config.CalculatorList[channel].chTargetState2 ||
@@ -382,6 +426,17 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
382
426
  this.adapter.log.warn(`Empty second destination state in calculator channel ${channel} defined - provide correct external state 2 - execution of channel skipped`);
383
427
  continue;
384
428
  }
429
+ const chTargetState2Components = this.adapter.config.CalculatorList[channel].chTargetState2.split(".");
430
+ let foundAllBadComponents = true;
431
+ badComponents.forEach((badComponent) => {
432
+ if (!chTargetState2Components.includes(badComponent))
433
+ foundAllBadComponents = false;
434
+ });
435
+ // WIP - oder enthält "Output"....
436
+ if (foundAllBadComponents) {
437
+ this.adapter.log.error(`Invalid second destination state defined in calculator channel ${channel}. Please avoid specifying the activation state of this channel as the destination. Skipping channel execution.`);
438
+ continue;
439
+ }
385
440
  }
386
441
  try {
387
442
  switch (this.adapter.config.CalculatorList[channel].chType) {
@@ -403,8 +458,14 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
403
458
  case tibberHelper_1.enCalcType.BestHoursBlockLTF:
404
459
  this.executeCalculatorBestHoursBlock(parseInt(channel), true);
405
460
  break;
406
- case tibberHelper_1.enCalcType.SmartBatteryBuffer:
407
- this.executeCalculatorSmartBatteryBuffer(parseInt(channel));
461
+ case tibberHelper_1.enCalcType.SmartBatteryBuffer: // If Active=false been set just now - or still active then act - else just produce debug log in the following runs
462
+ // WIP #332 - 2.3.0
463
+ if (this.adapter.config.CalculatorList[channel].chActive || onStateChange) {
464
+ this.executeCalculatorSmartBatteryBuffer(parseInt(channel));
465
+ }
466
+ else {
467
+ this.adapter.log.debug(`calculator channel: ${channel}-smart battery buffer; execution skipped because channel not set to active in channel states`);
468
+ }
408
469
  break;
409
470
  default:
410
471
  this.adapter.log.debug(`unknown value for calculator type: ${this.adapter.config.CalculatorList[channel].chType}`);
@@ -607,7 +668,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
607
668
  valueToSet = this.adapter.config.CalculatorList[channel].chValueOff;
608
669
  }
609
670
  // calculate average cost of determined block of hours, write to data point
610
- this.checkAndSetValueNumber(this.getStatePrefix(this.adapter.config.CalculatorList[channel].chHomeID, `Calculations.${channel}`, `AverageTotalCost`), Math.round(1000 * (minSum / n)) / 1000, `average total cost in determined block`, false, false);
671
+ this.checkAndSetValueNumber(this.getStatePrefix(this.adapter.config.CalculatorList[channel].chHomeID, `Calculations.${channel}`, `AverageTotalCost`), Math.round(1000 * (minSum / n)) / 1000, `average total cost in determined block`, undefined, false, false);
611
672
  // write start and stop time of determined block to data points
612
673
  const beginDate = new Date(filteredPrices[startIndex].startsAt);
613
674
  const endDate = new Date(filteredPrices[startIndex + n - 1].startsAt);
@@ -623,6 +684,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
623
684
  }
624
685
  }
625
686
  async executeCalculatorSmartBatteryBuffer(channel) {
687
+ //#region *** SPECIFICATION ***
626
688
  /*
627
689
  Summary:
628
690
  Develop a channel that categorizes hourly energy prices into three groups—cheap, normal, and expensive.
@@ -651,6 +713,7 @@ class TibberCalculator extends tibberHelper_1.TibberHelper {
651
713
  - Normal Hours - disable battery charging (OFF-1) and also disable feed into home energy system (OFF-2)
652
714
  - Expensive Hours - disable battery charging (OFF-1) and enable feed into home energy system (ON-2)
653
715
  */
716
+ //#endregion
654
717
  try {
655
718
  let valueToSet = "";
656
719
  let valueToSet2 = "";