iobroker.autodarts 0.3.1 → 0.3.3
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 +13 -0
- package/admin/i18n/de.json +4 -4
- package/admin/i18n/en.json +4 -4
- package/admin/i18n/es.json +4 -4
- package/admin/i18n/fr.json +5 -5
- package/admin/i18n/it.json +4 -4
- package/admin/i18n/nl.json +4 -4
- package/admin/i18n/pl.json +4 -4
- package/admin/i18n/pt.json +4 -4
- package/admin/i18n/ru.json +4 -4
- package/admin/i18n/uk.json +4 -4
- package/admin/i18n/zh-cn.json +4 -4
- package/admin/jsonConfig.json +3 -3
- package/io-package.json +31 -28
- package/lib/adapter-config.d.ts +4 -1
- package/lib/httpHelper.js +43 -0
- package/lib/httpHelper.test.js +171 -0
- package/lib/throw.js +17 -5
- package/lib/trafficLight.js +3 -2
- package/lib/visit.js +3 -2
- package/main.js +119 -190
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,19 @@ In the adapter settings, enter:
|
|
|
59
59
|
<!--
|
|
60
60
|
### **WORK IN PROGRESS**
|
|
61
61
|
-->
|
|
62
|
+
### 0.3.3 (2025-12-27)
|
|
63
|
+
- Changed: Configuration fields interval and triggerReset now use seconds instead of milliseconds in the admin UI.
|
|
64
|
+
|
|
65
|
+
### 0.3.2 (2025-12-27)
|
|
66
|
+
- (DrozmotiX) **ENHANCED**: Fixed all TypeScript type errors by adding proper type definitions for config properties
|
|
67
|
+
- (DrozmotiX) **ENHANCED**: Refactored HTTP request handling - created reusable httpHelper module to eliminate code duplication
|
|
68
|
+
- (DrozmotiX) **ENHANCED**: Converted HTTP callback-based requests to async/await pattern for better error handling
|
|
69
|
+
- (DrozmotiX) **ENHANCED**: Improved connection state logging - now logs when connection is restored after being offline
|
|
70
|
+
- (DrozmotiX) **ENHANCED**: Standardized async/await usage across all state change handlers for consistency
|
|
71
|
+
- (DrozmotiX) **FIXED**: Removed unused error variable in fetchVersion method
|
|
72
|
+
- (DrozmotiX) **FIXED**: Added proper error type checking in fetchConfig to prevent runtime errors
|
|
73
|
+
- (DrozmotiX) **TESTING**: Added comprehensive unit tests for httpHelper module covering success, timeout, and error scenarios
|
|
74
|
+
|
|
62
75
|
### 0.3.1 (2025-12-27)
|
|
63
76
|
- Changed: Object creation now uses extendObjectAsync with proper roles and types instead of setObjectNotExistsAsync.
|
|
64
77
|
|
package/admin/i18n/de.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Autodarts (Boardmanager) Port",
|
|
5
5
|
"host_port_help": "Portnummer des lokalen Autodarts Boardmanagers.",
|
|
6
6
|
"intro_txt": "Konfiguration des Autodarts-Adapters.",
|
|
7
|
-
"polling": "Abfrageintervall (
|
|
8
|
-
"polling_help": "Abfrageintervall in
|
|
9
|
-
"reset": "Trigger-Reset (
|
|
10
|
-
"reset_help": "Setzt den Triple- und Bullseye-Trigger nach x
|
|
7
|
+
"polling": "Abfrageintervall (s)",
|
|
8
|
+
"polling_help": "Abfrageintervall in Sekunden zum Abrufen von Daten vom Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Trigger-Reset (s)",
|
|
10
|
+
"reset_help": "Setzt den Triple- und Bullseye-Trigger nach x Sekunden zurück (0 = kein Reset).",
|
|
11
11
|
"triple_flag": "Minimales Feld für den Triple-Trigger",
|
|
12
12
|
"triple_flag2": "Maximales Feld für den Triple-Trigger",
|
|
13
13
|
"triple_flag2_help": "Feld „Maximale Punktzahl“ für den Triple-Trigger. Darts mit einer Punktzahl über diesem Wert lösen den Triple-Trigger-Datenpunkt nicht aus.",
|
package/admin/i18n/en.json
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
"host_port": "Autodarts (Boardmanager) Port",
|
|
5
5
|
"host_port_help": "Port number of the local Autodarts Boardmanager.",
|
|
6
6
|
"intro_txt": "Autodarts adapter configuration.",
|
|
7
|
-
"polling": "Polling interval (
|
|
8
|
-
"polling_help": "Polling interval in
|
|
7
|
+
"polling": "Polling interval (s)",
|
|
8
|
+
"polling_help": "Polling interval in seconds to retrieve data from the Autodarts Boardmanager.",
|
|
9
9
|
"triple_flag": "Minimum field for the triple trigger",
|
|
10
10
|
"triple_flag2": "Maximum field for the triple trigger",
|
|
11
11
|
"triple_flag2_help": "Maximum score field for the triple trigger. Darts with a score above this value will not trigger the Triple-Trigger datapoint.",
|
|
12
12
|
"triple_flag_help": "Minimum score field for the triple trigger. Darts with a score below this value will not trigger the Triple-Trigger datapoint.",
|
|
13
|
-
"reset": "Trigger-Reset (
|
|
14
|
-
"reset_help": "Reset the triple and bullseye trigger after x
|
|
13
|
+
"reset": "Trigger-Reset (s)",
|
|
14
|
+
"reset_help": "Reset the triple and bullseye trigger after x seconds (0 = no reset)."
|
|
15
15
|
}
|
package/admin/i18n/es.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Puerto Autodarts (Boardmanager)",
|
|
5
5
|
"host_port_help": "Número de puerto del administrador local de Autodarts Boardmanager.",
|
|
6
6
|
"intro_txt": "Configuración del adaptador Autodarts.",
|
|
7
|
-
"polling": "Intervalo de sondeo
|
|
8
|
-
"polling_help": "Intervalo de sondeo en
|
|
9
|
-
"reset": "Restablecimiento
|
|
10
|
-
"reset_help": "Restablezca el disparador triple y de diana después de x
|
|
7
|
+
"polling": "Intervalo(s) de sondeo",
|
|
8
|
+
"polling_help": "Intervalo de sondeo en segundos para recuperar datos del Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Restablecimiento de disparador (s)",
|
|
10
|
+
"reset_help": "Restablezca el disparador triple y de diana después de x segundos (0 = sin reinicio).",
|
|
11
11
|
"triple_flag": "Campo mínimo para el triple disparador",
|
|
12
12
|
"triple_flag2": "Campo máximo para el triple disparador",
|
|
13
13
|
"triple_flag2_help": "Campo de puntuación máxima para el triple disparador. Los dardos con una puntuación superior a este valor no activarán el punto de datos Triple-Trigger.",
|
package/admin/i18n/fr.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"host_ip": "Autodarts (Boardmanager) Hôte/IP",
|
|
3
|
-
"host_ip_help": "Adresse IP
|
|
3
|
+
"host_ip_help": "Adresse IP du Boardmanager Autodarts local.",
|
|
4
4
|
"host_port": "Port Autodarts (Boardmanager)",
|
|
5
5
|
"host_port_help": "Numéro de port du Boardmanager Autodarts local.",
|
|
6
6
|
"intro_txt": "Configuration de l'adaptateur Autodarts.",
|
|
7
|
-
"polling": "Intervalle d'interrogation
|
|
8
|
-
"polling_help": "Intervalle d'interrogation en
|
|
9
|
-
"reset": "Déclencheur-
|
|
10
|
-
"reset_help": "Réinitialisez le déclencheur triple et bullseye après x
|
|
7
|
+
"polling": "Intervalle(s) d'interrogation",
|
|
8
|
+
"polling_help": "Intervalle d'interrogation en secondes pour récupérer les données de l'Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Déclencheur-Réinitialisation(s)",
|
|
10
|
+
"reset_help": "Réinitialisez le déclencheur triple et bullseye après x secondes (0 = pas de réinitialisation).",
|
|
11
11
|
"triple_flag": "Champ minimum pour le triple déclencheur",
|
|
12
12
|
"triple_flag2": "Champ maximum pour le triple déclencheur",
|
|
13
13
|
"triple_flag2_help": "Champ de score maximum pour le triple déclencheur. Les fléchettes avec un score supérieur à cette valeur ne déclencheront pas le point de données Triple-Trigger.",
|
package/admin/i18n/it.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Porta Autodarts (Boardmanager).",
|
|
5
5
|
"host_port_help": "Numero di porta del Boardmanager Autodarts locale.",
|
|
6
6
|
"intro_txt": "Configurazione dell'adattatore Autodarts.",
|
|
7
|
-
"polling": "Intervallo di polling (
|
|
8
|
-
"polling_help": "Intervallo di polling in
|
|
9
|
-
"reset": "
|
|
10
|
-
"reset_help": "Ripristina il
|
|
7
|
+
"polling": "Intervallo di polling (s)",
|
|
8
|
+
"polling_help": "Intervallo di polling in secondi per recuperare i dati da Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Trigger-Reset(s)",
|
|
10
|
+
"reset_help": "Ripristina il grilletto triplo e bullseye dopo x secondi (0 = nessun ripristino).",
|
|
11
11
|
"triple_flag": "Campo minimo per il triplo trigger",
|
|
12
12
|
"triple_flag2": "Campo massimo per il triplo trigger",
|
|
13
13
|
"triple_flag2_help": "Campo del punteggio massimo per il triplo trigger. Le freccette con un punteggio superiore a questo valore non attiveranno il punto dati Triple-Trigger.",
|
package/admin/i18n/nl.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Autodarts (Bestuursmanager) Port",
|
|
5
5
|
"host_port_help": "Poortnummer van de lokale Autodarts Boardmanager.",
|
|
6
6
|
"intro_txt": "Autodarts-adapterconfiguratie.",
|
|
7
|
-
"polling": "Polling-interval (
|
|
8
|
-
"polling_help": "Polling-interval in
|
|
9
|
-
"reset": "Trigger-reset (
|
|
10
|
-
"reset_help": "Reset de drievoudige en bullseye-trigger na x
|
|
7
|
+
"polling": "Polling-interval (s)",
|
|
8
|
+
"polling_help": "Polling-interval in seconden om gegevens uit de Autodarts Boardmanager op te halen.",
|
|
9
|
+
"reset": "Trigger-reset (s)",
|
|
10
|
+
"reset_help": "Reset de drievoudige en bullseye-trigger na x seconden (0 = geen reset).",
|
|
11
11
|
"triple_flag": "Minimumveld voor de drievoudige trigger",
|
|
12
12
|
"triple_flag2": "Maximaal veld voor de drievoudige trigger",
|
|
13
13
|
"triple_flag2_help": "Maximaal scoreveld voor de drievoudige trigger. Darten met een score boven deze waarde activeren het Triple-Trigger-datapunt niet.",
|
package/admin/i18n/pl.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Port Autodarts (Boardmanager).",
|
|
5
5
|
"host_port_help": "Numer portu lokalnego zarządcy Autodarts.",
|
|
6
6
|
"intro_txt": "Konfiguracja adaptera Autodarts.",
|
|
7
|
-
"polling": "Interwał odpytywania (
|
|
8
|
-
"polling_help": "Interwał odpytywania w
|
|
9
|
-
"reset": "Reset wyzwalacza (
|
|
10
|
-
"reset_help": "Zresetuj wyzwalacz potrójny i tarczy po x
|
|
7
|
+
"polling": "Interwał odpytywania (s)",
|
|
8
|
+
"polling_help": "Interwał odpytywania w sekundach w celu pobrania danych z menedżera Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Reset wyzwalacza (s)",
|
|
10
|
+
"reset_help": "Zresetuj wyzwalacz potrójny i tarczy po x sekundach (0 = brak resetu).",
|
|
11
11
|
"triple_flag": "Minimalne pole dla potrójnego wyzwalacza",
|
|
12
12
|
"triple_flag2": "Maksymalne pole dla potrójnego wyzwalacza",
|
|
13
13
|
"triple_flag2_help": "Pole maksymalnego wyniku dla potrójnego wyzwalacza. Rzutki z wynikiem powyżej tej wartości nie uruchomią punktu danych Triple-Trigger.",
|
package/admin/i18n/pt.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Porto Autodarts (Boardmanager)",
|
|
5
5
|
"host_port_help": "Número da porta do Autodarts Boardmanager local.",
|
|
6
6
|
"intro_txt": "Configuração do adaptador Autodarts.",
|
|
7
|
-
"polling": "Intervalo de pesquisa
|
|
8
|
-
"polling_help": "Intervalo de pesquisa em
|
|
9
|
-
"reset": "
|
|
10
|
-
"reset_help": "Redefina o gatilho triplo e alvo após x
|
|
7
|
+
"polling": "Intervalo(s) de pesquisa",
|
|
8
|
+
"polling_help": "Intervalo de pesquisa em segundos para recuperar dados do Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Redefinição(ões) de gatilho",
|
|
10
|
+
"reset_help": "Redefina o gatilho triplo e alvo após x segundos (0 = sem reinicialização).",
|
|
11
11
|
"triple_flag": "Campo mínimo para o disparo triplo",
|
|
12
12
|
"triple_flag2": "Campo máximo para o disparo triplo",
|
|
13
13
|
"triple_flag2_help": "Campo de pontuação máxima para o disparo triplo. Dardos com pontuação acima deste valor não acionarão o ponto de dados Triple-Trigger.",
|
package/admin/i18n/ru.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Порт Autodarts (Boardmanager)",
|
|
5
5
|
"host_port_help": "Номер порта местного Autodarts Boardmanager.",
|
|
6
6
|
"intro_txt": "Конфигурация адаптера Autodarts.",
|
|
7
|
-
"polling": "Интервал опроса (
|
|
8
|
-
"polling_help": "Интервал опроса в
|
|
9
|
-
"reset": "
|
|
10
|
-
"reset_help": "Сбросьте триггер и триггер «яблочко» через x
|
|
7
|
+
"polling": "Интервал опроса (с)",
|
|
8
|
+
"polling_help": "Интервал опроса в секундах для получения данных из Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Триггер-Сброс (ы)",
|
|
10
|
+
"reset_help": "Сбросьте триггер и триггер «яблочко» через x секунд (0 = сброса нет).",
|
|
11
11
|
"triple_flag": "Минимальное поле для тройного триггера",
|
|
12
12
|
"triple_flag2": "Максимальное поле для тройного триггера",
|
|
13
13
|
"triple_flag2_help": "Поле максимального результата для тройного триггера. Дартс с результатом выше этого значения не будет активировать точку данных тройного триггера.",
|
package/admin/i18n/uk.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Autodarts (Boardmanager) Порт",
|
|
5
5
|
"host_port_help": "Номер порту місцевого менеджера Autodarts Board.",
|
|
6
6
|
"intro_txt": "Конфігурація адаптера Autodarts.",
|
|
7
|
-
"polling": "Інтервал опитування (
|
|
8
|
-
"polling_help": "Інтервал опитування в
|
|
9
|
-
"reset": "
|
|
10
|
-
"reset_help": "Скинути потрійний тригер і тригер
|
|
7
|
+
"polling": "Інтервал опитування (с)",
|
|
8
|
+
"polling_help": "Інтервал опитування в секундах для отримання даних із Autodarts Boardmanager.",
|
|
9
|
+
"reset": "Тригер-Скидання (s)",
|
|
10
|
+
"reset_help": "Скинути потрійний тригер і тригер «яблочко» через x секунд (0 = без скидання).",
|
|
11
11
|
"triple_flag": "Мінімальне поле для потрійного тригера",
|
|
12
12
|
"triple_flag2": "Максимальне поле для потрійного тригера",
|
|
13
13
|
"triple_flag2_help": "Поле максимального балу для потрійного тригера. Дартс із результатом вище цього значення не активує точку даних Triple-Trigger.",
|
package/admin/i18n/zh-cn.json
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"host_port": "Autodarts(Boardmanager)端口",
|
|
5
5
|
"host_port_help": "本地 Autodarts Boardmanager 的端口号。",
|
|
6
6
|
"intro_txt": "Autodarts 适配器配置。",
|
|
7
|
-
"polling": "
|
|
8
|
-
"polling_help": "从 Autodarts Boardmanager
|
|
9
|
-
"reset": "
|
|
10
|
-
"reset_help": "x
|
|
7
|
+
"polling": "轮询间隔(秒)",
|
|
8
|
+
"polling_help": "从 Autodarts Boardmanager 检索数据的轮询间隔(以秒为单位)。",
|
|
9
|
+
"reset": "触发-复位",
|
|
10
|
+
"reset_help": "x 秒后重置三重触发器和靶心触发器(0 = 不重置)。",
|
|
11
11
|
"triple_flag": "三重触发器的最小字段",
|
|
12
12
|
"triple_flag2": "三重触发器的最大字段",
|
|
13
13
|
"triple_flag2_help": "三重触发器的最大分数字段。分数高于此值的飞镖将不会触发三重触发数据点。",
|
package/admin/jsonConfig.json
CHANGED
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"marginBottom": "10px"
|
|
127
127
|
}
|
|
128
128
|
},
|
|
129
|
-
"
|
|
129
|
+
"triggerResetSec": {
|
|
130
130
|
"type": "number",
|
|
131
131
|
"label": "reset",
|
|
132
132
|
"help": "reset_help",
|
|
@@ -142,11 +142,11 @@
|
|
|
142
142
|
"marginBottom": "10px"
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
|
-
"
|
|
145
|
+
"intervalSec": {
|
|
146
146
|
"type": "number",
|
|
147
147
|
"label": "polling",
|
|
148
148
|
"help": "polling_help",
|
|
149
|
-
"default":
|
|
149
|
+
"default": 1,
|
|
150
150
|
"newLine": true,
|
|
151
151
|
"sm": 12,
|
|
152
152
|
"xs": 12,
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "autodarts",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.3.3": {
|
|
7
|
+
"en": "Changed: Configuration fields interval and triggerReset now use seconds instead of milliseconds in the admin UI.",
|
|
8
|
+
"de": "Geändert: Konfiguration Felder Intervall und TriggerReset verwenden jetzt Sekunden statt Millisekunden im Admin UI.",
|
|
9
|
+
"ru": "Изменение: интервалы полей конфигурации и триггер сброс теперь используют секунды вместо миллисекунд в пользовательском интерфейсе администратора.",
|
|
10
|
+
"pt": "Modificado: Intervalo de campos de configuração e gatilhoReset agora use segundos em vez de milissegundos na interface de administração.",
|
|
11
|
+
"nl": "Gewijzigd: Configuratievelden interval en triggerReset gebruikt nu seconden in plaats van milliseconden in de admin UI.",
|
|
12
|
+
"fr": "Changed: Champs de configuration intervalle et triggerReset maintenant utiliser secondes au lieu de millisecondes dans l'interface utilisateur admin.",
|
|
13
|
+
"it": "Modificato: intervallo di campi di configurazione e triggerReset ora utilizzare secondi invece di millisecondi nell'interfaccia utente di amministrazione.",
|
|
14
|
+
"es": "Cambio: intervalo de campos de configuración y gatilloReset ahora use segundos en lugar de milisegundos en la interfaz de administración.",
|
|
15
|
+
"pl": "Zmieniony: Przedział pól konfiguracyjnych i tryggerReset używają teraz sekund zamiast milisekund w interfejsu administratora.",
|
|
16
|
+
"uk": "Змінено: інтервал конфігураційних полів і тригерЗмінити зараз за допомогою секунд замість мілісекундів в адмін UI.",
|
|
17
|
+
"zh-cn": "已更改: 配置字段间隔和触发 Reset 现在在管理员UI中使用秒而不是毫秒 ."
|
|
18
|
+
},
|
|
19
|
+
"0.3.2": {
|
|
20
|
+
"en": "**ENHANCED**: Fixed all TypeScript type errors by adding proper type definitions for config properties\n**ENHANCED**: Refactored HTTP request handling - created reusable httpHelper module to eliminate code duplication\n**ENHANCED**: Converted HTTP callback-based requests to async/await pattern for better error handling\n**ENHANCED**: Improved connection state logging - now logs when connection is restored after being offline\n**ENHANCED**: Standardized async/await usage across all state change handlers for consistency\n**FIXED**: Removed unused error variable in fetchVersion method\n**FIXED**: Added proper error type checking in fetchConfig to prevent runtime errors\n**TESTING**: Added comprehensive unit tests for httpHelper module covering success, timeout, and error scenarios",
|
|
21
|
+
"de": "**ENHANCED**: Alle TypeScript-Typfehler behoben, indem richtige Typendefinitionen für config-Eigenschaften hinzugefügt wurden\n**ENHANCED**: Refactored HTTP Request Handling - erstelltes wiederverwendbares httpHelper Modul zur Beseitigung der Codevervielfachung\n**ENHANCED**: Konvertierte HTTP-Requests auf async/await-Muster für eine bessere Fehlerbehandlung\n**ENHANCED**: Verbesserte Verbindungszustandsprotokollierung - protokolliert nun, wenn die Verbindung nach Offline wiederhergestellt wird\n**ENHANCED**: Standardisierte async/await Nutzung über alle State Change-Handler für Konsistenz\n**FIXED**: Ungenutzte Fehlervariable in fetchVersion Methode entfernt\n**FIXED**: Es wurde eine ordnungsgemäße Fehlersuche im fetchConfig hinzugefügt, um Laufzeitfehler zu verhindern\n**TESTING**: Ergänzende Unit-Tests für das httpHelper-Modul für Erfolgs-, Timeout- und Fehlerszenarien",
|
|
22
|
+
"ru": "** УСТАНОВЛЕНО**: исправлены все ошибки типа TypeScript путем добавления правильных определений типа для свойств конфигурации\n**УДАЛЕН**: Рефакторированная обработка HTTP-запросов - создан многоразовый модуль httpHelper для устранения дублирования кода\n** УВЕДОМЛЕН**: преобразованные HTTP-запросы на основе обратного вызова для улучшения обработки ошибок\n** ВОССТАНОВЛЕНИЕ**: Улучшенная регистрация состояния соединения - теперь журналы, когда соединение восстанавливается после автономного подключения\n** УСТАНОВЛЕНО**: Стандартизированное использование асинхронизации/ожиданий для всех обработчиков изменений состояния\n**FIXED**: Удаление неиспользуемой переменной ошибки в методе fetchVersion\n**FIXED**: добавлена правильная проверка типа ошибки в fetchConfig для предотвращения ошибок во время выполнения\n** Тестирование**: добавлены комплексные единичные тесты для модуля httpHelper, охватывающие сценарии успеха, тайм-аута и ошибок",
|
|
23
|
+
"pt": "**Enhanced**: Corrigido todos os erros de tipo TypeScript adicionando definições de tipo adequadas para as propriedades de configuração\n**ENHANCED**: Refactored HTTP request handling - created reutilizable httpHelper module to elimine code duplication\n**ENHANCED**: Requisições baseadas em callback HTTP convertidas para o padrão assync/await para melhor manipulação de erros\n**Enhanced**: Registro melhorado do estado da conexão - agora registra quando a conexão é restaurada após estar offline\n**ENHANCED**: Uso padrão de assync/await em todos os manipuladores de mudança de estado para consistência\n**FIXED**: Variável de erro não utilizada removida no método fetchVersion\n**FIXED**: Adicionado o tipo de erro correto verificando no fetchConfig para evitar erros de execução\n**TESTING**: Adicionados testes unitários abrangentes para o módulo httpHelper cobrindo cenários de sucesso, tempo e erro",
|
|
24
|
+
"nl": "**ENHANCED**: Fixed all TypeScript type fouten door het toevoegen van juiste type definities voor config eigenschappen\n**ENHANKELIJK**: Refactored HTTP request handling - herbruikbare httpHelper module gemaakt om code duplicatie te elimineren\n**ENHANCED**: Converted HTTP callback-gebaseerde verzoeken om async/wacht patroon voor betere foutafhandeling\n**ENHANCED**: Verbeterde verbindingstoestand logging - nu logt wanneer de verbinding wordt hersteld na offline zijn\n** ANTWOORD**: Gestandaardiseerd async/wacht gebruik in alle state change handlers voor consistentie\n** VAST**: Verwijderde ongebruikte fout variabele in fetchVersie methode\n** VAST**: Toegevoegd juiste fout type controleren in fetchConfig om runtime fouten te voorkomen\n**TESTING**: Toegevoegd uitgebreide unit testen voor httpHelper module over succes, timeout, en fout scenario's",
|
|
25
|
+
"fr": "**ENHANCED**: Correction de toutes les erreurs de type TypeScript en ajoutant des définitions de type appropriées pour les propriétés de configuration\n**ENHANDED**: Refactored HTTP request handling - créé module httpHelper réutilisable pour éliminer la duplication de code\n**ENHANCED**: Converti les requêtes basées sur le callback HTTP en modèle async/attendit pour une meilleure gestion des erreurs\n**ENHANCED**: Amélioration de l'enregistrement d'état de connexion - logs maintenant lorsque la connexion est restaurée après être hors ligne\n**CHANGE**: utilisation normalisée async/attendue dans tous les gestionnaires de changement d'état pour une cohérence\n**FIXED**: Supprimé la variable d'erreur inutilisée dans la méthode fetchVersion\n**FIXED**: Ajout d'une vérification de type d'erreur dans fetchConfig pour prévenir les erreurs d'exécution\n**TESTING**: Ajout de tests unitaires complets pour le module httpHelper couvrant les scénarios de succès, de délai et d'erreur",
|
|
26
|
+
"it": "**ENHANCED**: Risolto tutti gli errori di tipo TypeScript aggiungendo definizioni di tipo corrette per proprietà di configurazione\n**ENHANCED**: Refactored HTTP request handling - creato modulo httpHelper riutilizzabile per eliminare la duplicazione di codice\n**ENHANCED**: Le richieste basate su callback HTTP convertite in un modello asinc/aspettato per una migliore gestione degli errori\n**ENHANCED**: Registrazione dello stato di connessione migliorata - ora i log quando la connessione viene ripristinata dopo essere offline\n**ENHANCED**: Uso standardizzato asinc/aspettato in tutti i maneggiatori di cambio di stato per consistenza\n**FIXED**: Rimossa variabile di errore non utilizzata nel metodo fetchVersion\n**FIXED**: Aggiunta il corretto tipo di errore di controllo in fetchConfig per evitare errori runtime\n**TESTING**: Aggiunti test unitari completi per il modulo httpHelper che copre il successo, il timeout e gli scenari di errore",
|
|
27
|
+
"es": "**ENHANCED**: Arregla todos los errores tipo TipoScript añadiendo definiciones adecuadas para propiedades de configuración\n**ENHANCED**: Refactored HTTP request handling - creó el módulo httpHelper reutilizable para eliminar la duplicación de códigos\n**ENHANCED**: Solicitudes convertidas basadas en llamadas HTTP a async/await patrón para un mejor manejo de errores\n**ENHANCED**: Mejora de la conexión de registro de estado - ahora registros cuando la conexión se restaura después de estar fuera de línea\n**ENHANCED**: El uso estandarizado async/await en todos los manejadores del cambio estatal para la consistencia\n**FIXED**: Retire la variable de error no utilizado en el método fetchVersion\n**FIXED**: Añadido el tipo de error correcto en fetchConfig para evitar errores de tiempo de ejecución\n** Notas**: Se agregaron pruebas de unidad completas para el módulo httpHelper que abarcan el éxito, el tiempo y los escenarios de error",
|
|
28
|
+
"pl": "* *ENHANCED* *: Naprawiono wszystkie błędy typu TypeScript poprzez dodanie właściwych definicji typów dla właściwości konfiguracyjnych \n* *ENHANCED* *: Refactored HTTP request handling - created realisable httpHelper module to elimination code duplication \n* *ENHANCED* *: Konwertowany HTTP połączeń backback prośby async / czekać wzór dla lepszej obsługi błędów \n* *ENHANCED* *: Ulepszone logowanie stanu połączenia - teraz loguje się, gdy połączenie jest przywrócone po offline \n* *ENHANCED* *: Standaryzowane async / czekać na wykorzystanie we wszystkich stanowych opiekunów zmian dla spójności \n* *FIXED* *: Usunięto nieużywaną zmienną błędu w metodzie fetchVersion \n* *FIXED* *: Dodano poprawny typ błędu sprawdzający w fetchConfig, aby zapobiec błędom w runtime \n* *TESTING* *: Dodano kompleksowe testy jednostkowe dla modułu httpHelper obejmujące sukcesy, timeout i scenariusze błędów ",
|
|
29
|
+
"uk": "**ENHANCED**: Виправлено всі помилки типу TypeScript, додаючи правильні визначення типу для властивостей конфігурації\n**ENHANCED**: Перефакторований HTTP-запитування - створений багаторазовий модуль HTTPHelper для усунення дублікатів коду\n**ENHANCED**: Конвертовані запити на основі HTTP-повідомлень на основі async/await для кращої обробки помилок\n**ENHANCED***: Покращується з'єднання держреєстрації - тепер журнали, коли з'єднання відновлюється після офлайн\n**ENHANCED***: стандартизоване використання async/await у всіх ручках зі змінами стану для консистенції\n**FIXED**: Видалено невикористану змінну помилку в методі fetchVersion\n**FIXED***: Додано належну перевірку типу помилки в fetchConfig, щоб запобігти помилки часу\n**TESTING***: Додано комплексні тести для модуля httpHelper, що охоплює успіхи, часовий час та сценарії помилок",
|
|
30
|
+
"zh-cn": "** ENHANCED**:通过添加适当的配置属性类型定义来固定所有类型脚本类型错误\n** ENHANCED **: 重置了 HTTP 请求处理 - 创建了可重复使用的 httpHelper 模块,以消除代码重复\n** ENHANCED**: 将基于 HTTP 回调请求转换为同步/等待模式,以更好地处理错误\n** ENHANCED **: 连接状态记录的改进 -- -- 下线后恢复连接时的日志\n** ENHANCED**:所有州变化处理器的标准化合成/等待使用,以保持一致\n** FIXED**:删除了拾取Version 方法中的未使用错误变量\n** FIXED**:在获取中添加适当的错误类型检查Config以防止运行时间错误\n** TESTING**:为httpHelper模块添加了涵盖成功、超时和错误情景的综合单元测试"
|
|
31
|
+
},
|
|
6
32
|
"0.3.1": {
|
|
7
33
|
"en": "Changed: Object creation now uses extendObjectAsync with proper roles and types instead of setObjectNotExistsAsync.",
|
|
8
34
|
"de": "Geändert: Objekt-Erstellung verwendet jetzt ExtendedObjectAsync mit richtigen Rollen und Typen anstelle von Set ObjectNotExistsAsync.",
|
|
@@ -67,32 +93,6 @@
|
|
|
67
93
|
"pl": "Dodano punkt danych dla byków\nDodano wynik flagi maximun triplehit\nAktualizuj konfigurację\nOstrzeżenie w dzienniku wyczyszczonym",
|
|
68
94
|
"uk": "Додано точку даних для биків-хіт\nДодано максимальний потрійний-hit прапорець бал\nНалаштування оновлення\nПопередження в журналі",
|
|
69
95
|
"zh-cn": "给 bull- hit 添加数据点\n增加最大值的三重旗分\n更新配置\n清除日志中的警告"
|
|
70
|
-
},
|
|
71
|
-
"0.1.0": {
|
|
72
|
-
"en": "Added datapoints for visit score, current dart score, triple-hit flag with configurable minimum score, and camera configuration (cam0–cam2).\nCleaned up adapter logic and internal polling/timing.\nUpdated translations.",
|
|
73
|
-
"de": "Weitere Datenpunkte für Besuchscore, aktuelle Dart-Score, Tripel-hit-Flag mit konfigurierbaren minimalen Punktzahl und Kamerakonfiguration (cam0–cam2).\nAufgereinigte Adapterlogik und interne Abfrage/timing.\nAktualisierte Übersetzungen.",
|
|
74
|
-
"ru": "Добавлены точки данных для оценки посещений, текущая оценка дарта, флаг тройного удара с настраиваемым минимальным баллом и конфигурация камеры (cam0-cam2).\nОчищена адаптерная логика и внутренний опрос/настройка.\nОбновленные переводы.",
|
|
75
|
-
"pt": "Adicionados pontos de dados para a pontuação de visita, pontuação de dardo atual, bandeira de triplo hit com pontuação mínima configurável, e configuração da câmera (cam0–cam2).\nLimpei a lógica do adaptador e as pesquisas internas.\nTradução atualizada.",
|
|
76
|
-
"nl": "Toegevoegd datapoints voor bezoek score, huidige dart score, triple-hit vlag met configureerbare minimum score, en camera configuratie (cam0.\nOpgeruimd adapter logica en interne peiling / timing.\nBijgewerkte vertalingen.",
|
|
77
|
-
"fr": "Ajout de points de données pour le score de visite, le score de fléchette actuel, le drapeau triple-hit avec le score minimum configurable et la configuration de la caméra (cam0–cam2).\nNettoyer la logique de l'adaptateur et effectuer des sondages internes/timing.\nTraductions actualisées.",
|
|
78
|
-
"it": "Aggiunti i datapoint per il punteggio di visita, il punteggio di freccette corrente, la bandiera a triplo punto con il punteggio minimo configurabile e la configurazione della fotocamera (cam0–cam2).\nPulito logica adattatore e polling/timing interno.\nTraduzione aggiornata.",
|
|
79
|
-
"es": "Puntos de datos añadidos para la puntuación de la visita, puntaje del dardo actual, bandera triple con puntaje mínimo configurable, y configuración de la cámara (cam0–cam2).\nLógica del adaptador limpiado y polinización interna / estimulación.\nTraducciones actualizadas.",
|
|
80
|
-
"pl": "Dodano punkty datapointowe dla wyniku odwiedzin, aktualny wynik dart, flagę trójuderzeniową z konfigurowalnym minimalnym wynikiem oraz konfigurację kamery (cam0- cam2).\nOczyszczona logika adaptera i wewnętrzny sondaż / czas.\nAktualizacja tłumaczeń.",
|
|
81
|
-
"uk": "Додано точки даних для облікового запису, поточний запис dart, потрійний прапор з налаштуванням мінімального балу та конфігурації камери (cam0–cam2).\nЗнімання логіки адаптера та внутрішнього опитування / термінів.\nОновлені переклади.",
|
|
82
|
-
"zh-cn": "添加了访问分数的数据点,当前飞镖分数,三重击旗可配置最小分数,以及相机配置(cam0–cam2).\n清理适配器逻辑和内部投票/计时.\n最新译名."
|
|
83
|
-
},
|
|
84
|
-
"0.0.14": {
|
|
85
|
-
"en": "fix",
|
|
86
|
-
"de": "fixieren",
|
|
87
|
-
"ru": "исправлять",
|
|
88
|
-
"pt": "corrigir",
|
|
89
|
-
"nl": "fix",
|
|
90
|
-
"fr": "correction",
|
|
91
|
-
"it": "correzione",
|
|
92
|
-
"es": "arregle",
|
|
93
|
-
"pl": "fix",
|
|
94
|
-
"uk": "фіксація",
|
|
95
|
-
"zh-cn": "固定"
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
"titleLang": {
|
|
@@ -164,7 +164,10 @@
|
|
|
164
164
|
"native": {
|
|
165
165
|
"host": "127.0.0.1",
|
|
166
166
|
"port": 3180,
|
|
167
|
-
"
|
|
167
|
+
"intervalSec": 1,
|
|
168
|
+
"triggerResetSec": 0,
|
|
169
|
+
"tripleMinScore": 1,
|
|
170
|
+
"tripleMaxScore": 20
|
|
168
171
|
},
|
|
169
172
|
"objects": [],
|
|
170
173
|
"instanceObjects": []
|
package/lib/adapter-config.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ type _AdapterConfig = typeof native;
|
|
|
10
10
|
declare global {
|
|
11
11
|
namespace ioBroker {
|
|
12
12
|
interface AdapterConfig extends _AdapterConfig {
|
|
13
|
-
//
|
|
13
|
+
// Additional properties defined in jsonConfig but not in io-package.json native
|
|
14
|
+
tripleMinScore?: number;
|
|
15
|
+
tripleMaxScore?: number;
|
|
16
|
+
triggerResetMs?: number;
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// lib/httpHelper.js
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const http = require("http");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Makes an HTTP request to the Autodarts Board Manager.
|
|
8
|
+
*
|
|
9
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter instance
|
|
10
|
+
* @param {string} path API path (e.g., "/api/state")
|
|
11
|
+
* @param {number} timeout Timeout in milliseconds
|
|
12
|
+
* @returns {Promise<string>} Response data as string
|
|
13
|
+
*/
|
|
14
|
+
function makeRequest(adapter, path, timeout = 1500) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
const options = {
|
|
17
|
+
host: adapter.config.host,
|
|
18
|
+
port: adapter.config.port,
|
|
19
|
+
path: path,
|
|
20
|
+
method: "GET",
|
|
21
|
+
timeout: timeout,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const req = http.request(options, res => {
|
|
25
|
+
let data = "";
|
|
26
|
+
|
|
27
|
+
res.on("data", chunk => (data += chunk));
|
|
28
|
+
res.on("end", () => resolve(data));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
req.on("error", error => reject(error));
|
|
32
|
+
req.on("timeout", () => {
|
|
33
|
+
req.destroy();
|
|
34
|
+
reject(new Error("Request timeout"));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
req.end();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
makeRequest,
|
|
43
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/* global describe, it, before, after */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { expect } = require("chai");
|
|
5
|
+
const http = require("http");
|
|
6
|
+
const httpHelper = require("./httpHelper");
|
|
7
|
+
|
|
8
|
+
describe("httpHelper", () => {
|
|
9
|
+
describe("makeRequest", () => {
|
|
10
|
+
let server;
|
|
11
|
+
let port;
|
|
12
|
+
|
|
13
|
+
before(done => {
|
|
14
|
+
// Create a test HTTP server
|
|
15
|
+
server = http.createServer((req, res) => {
|
|
16
|
+
if (req.url === "/api/test") {
|
|
17
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
18
|
+
res.end("test response");
|
|
19
|
+
} else if (req.url === "/api/json") {
|
|
20
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
21
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
22
|
+
} else if (req.url === "/api/timeout") {
|
|
23
|
+
// Don't respond - let it timeout
|
|
24
|
+
return;
|
|
25
|
+
} else if (req.url === "/api/error") {
|
|
26
|
+
req.socket.destroy();
|
|
27
|
+
} else {
|
|
28
|
+
res.writeHead(404);
|
|
29
|
+
res.end("Not found");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
server.listen(0, "127.0.0.1", () => {
|
|
34
|
+
port = server.address().port;
|
|
35
|
+
done();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
after(done => {
|
|
40
|
+
if (server) {
|
|
41
|
+
server.close(done);
|
|
42
|
+
} else {
|
|
43
|
+
done();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should successfully fetch data from a valid endpoint", async () => {
|
|
48
|
+
const mockAdapter = {
|
|
49
|
+
config: {
|
|
50
|
+
host: "127.0.0.1",
|
|
51
|
+
port: port,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
56
|
+
const result = await httpHelper.makeRequest(mockAdapter, "/api/test");
|
|
57
|
+
expect(result).to.equal("test response");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should successfully fetch JSON data", async () => {
|
|
61
|
+
const mockAdapter = {
|
|
62
|
+
config: {
|
|
63
|
+
host: "127.0.0.1",
|
|
64
|
+
port: port,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
69
|
+
const result = await httpHelper.makeRequest(mockAdapter, "/api/json");
|
|
70
|
+
const parsed = JSON.parse(result);
|
|
71
|
+
expect(parsed).to.deep.equal({ status: "ok" });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should reject with timeout error when request times out", async () => {
|
|
75
|
+
const mockAdapter = {
|
|
76
|
+
config: {
|
|
77
|
+
host: "127.0.0.1",
|
|
78
|
+
port: port,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
84
|
+
await httpHelper.makeRequest(mockAdapter, "/api/timeout", 100);
|
|
85
|
+
expect.fail("Should have thrown timeout error");
|
|
86
|
+
} catch (error) {
|
|
87
|
+
expect(error).to.be.an("error");
|
|
88
|
+
expect(error.message).to.equal("Request timeout");
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should reject with error when connection fails", async () => {
|
|
93
|
+
const mockAdapter = {
|
|
94
|
+
config: {
|
|
95
|
+
host: "127.0.0.1",
|
|
96
|
+
port: 99999, // Invalid port
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
102
|
+
await httpHelper.makeRequest(mockAdapter, "/api/test", 100);
|
|
103
|
+
expect.fail("Should have thrown connection error");
|
|
104
|
+
} catch (error) {
|
|
105
|
+
expect(error).to.be.an("error");
|
|
106
|
+
expect(error.code).to.match(/ECONNREFUSED|EADDRNOTAVAIL|ERR_SOCKET_BAD_PORT/);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should handle socket destruction gracefully", async () => {
|
|
111
|
+
const mockAdapter = {
|
|
112
|
+
config: {
|
|
113
|
+
host: "127.0.0.1",
|
|
114
|
+
port: port,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
120
|
+
await httpHelper.makeRequest(mockAdapter, "/api/error", 100);
|
|
121
|
+
expect.fail("Should have thrown error");
|
|
122
|
+
} catch (error) {
|
|
123
|
+
expect(error).to.be.an("error");
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should use custom timeout value", async () => {
|
|
128
|
+
const mockAdapter = {
|
|
129
|
+
config: {
|
|
130
|
+
host: "127.0.0.1",
|
|
131
|
+
port: port,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const startTime = Date.now();
|
|
136
|
+
try {
|
|
137
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
138
|
+
await httpHelper.makeRequest(mockAdapter, "/api/timeout", 200);
|
|
139
|
+
expect.fail("Should have thrown timeout error");
|
|
140
|
+
} catch (error) {
|
|
141
|
+
const elapsed = Date.now() - startTime;
|
|
142
|
+
expect(error.message).to.equal("Request timeout");
|
|
143
|
+
// Check that timeout happened roughly at the right time (with some tolerance)
|
|
144
|
+
expect(elapsed).to.be.at.least(150);
|
|
145
|
+
expect(elapsed).to.be.at.most(500);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("should use default timeout of 1500ms", async () => {
|
|
150
|
+
const mockAdapter = {
|
|
151
|
+
config: {
|
|
152
|
+
host: "127.0.0.1",
|
|
153
|
+
port: port,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const startTime = Date.now();
|
|
158
|
+
try {
|
|
159
|
+
// @ts-expect-error - mockAdapter is a partial mock for testing
|
|
160
|
+
await httpHelper.makeRequest(mockAdapter, "/api/timeout");
|
|
161
|
+
expect.fail("Should have thrown timeout error");
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const elapsed = Date.now() - startTime;
|
|
164
|
+
expect(error.message).to.equal("Request timeout");
|
|
165
|
+
// Check that default timeout of 1500ms was used (with tolerance)
|
|
166
|
+
expect(elapsed).to.be.at.least(1400);
|
|
167
|
+
expect(elapsed).to.be.at.most(2000);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|
package/lib/throw.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Legt Throw-Channel und States an.
|
|
6
6
|
*
|
|
7
|
-
* @param {import("@iobroker/adapter-core").
|
|
7
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
8
8
|
*/
|
|
9
9
|
async function init(adapter) {
|
|
10
10
|
await adapter.extendObjectAsync("throw", {
|
|
@@ -79,23 +79,24 @@ async function init(adapter) {
|
|
|
79
79
|
/**
|
|
80
80
|
* Aktualisiert die Throw-States für den letzten Dart inkl. Triple/Bull-Flags.
|
|
81
81
|
*
|
|
82
|
-
* @param {import("@iobroker/adapter-core").
|
|
82
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
83
83
|
* @param {any} lastDart Letzter Dart aus state.throws
|
|
84
84
|
*/
|
|
85
85
|
async function updateThrow(adapter, lastDart) {
|
|
86
|
+
// @ts-expect-error - calcScore is a custom method in the Autodarts adapter class
|
|
86
87
|
const score = adapter.calcScore(lastDart);
|
|
87
88
|
const segment = lastDart?.segment?.number || 0;
|
|
88
89
|
|
|
89
90
|
// Score-Range aus Adapter übernehmen
|
|
91
|
+
// @ts-expect-error - tripleMinScoreRuntime is a custom property in the Autodarts adapter class
|
|
90
92
|
let minScore = adapter.tripleMinScoreRuntime;
|
|
93
|
+
// @ts-expect-error - tripleMaxScoreRuntime is a custom property in the Autodarts adapter class
|
|
91
94
|
let maxScore = adapter.tripleMaxScoreRuntime;
|
|
92
95
|
|
|
93
96
|
if (!Number.isFinite(minScore)) {
|
|
94
|
-
// @ts-expect-error tripleMinScore is defined in io-package.json but not in AdapterConfig
|
|
95
97
|
minScore = Number(adapter.config.tripleMinScore) || 1;
|
|
96
98
|
}
|
|
97
99
|
if (!Number.isFinite(maxScore)) {
|
|
98
|
-
// @ts-expect-error tripleMaxScore is defined in io-package.json but not in AdapterConfig
|
|
99
100
|
maxScore = Number(adapter.config.tripleMaxScore) || 20;
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -114,29 +115,40 @@ async function updateThrow(adapter, lastDart) {
|
|
|
114
115
|
await adapter.setStateAsync("throw.current", { val: score, ack: true });
|
|
115
116
|
|
|
116
117
|
// Timer für Auto-Reset abbrechen
|
|
118
|
+
// @ts-expect-error - tripleResetTimer is a custom property in the Autodarts adapter class
|
|
117
119
|
if (adapter.tripleResetTimer) {
|
|
120
|
+
// @ts-expect-error - tripleResetTimer is a custom property in the Autodarts adapter class
|
|
118
121
|
clearTimeout(adapter.tripleResetTimer);
|
|
122
|
+
// @ts-expect-error - tripleResetTimer is a custom property in the Autodarts adapter class
|
|
119
123
|
adapter.tripleResetTimer = null;
|
|
120
124
|
}
|
|
125
|
+
// @ts-expect-error - bullResetTimer is a custom property in the Autodarts adapter class
|
|
121
126
|
if (adapter.bullResetTimer) {
|
|
127
|
+
// @ts-expect-error - bullResetTimer is a custom property in the Autodarts adapter class
|
|
122
128
|
clearTimeout(adapter.bullResetTimer);
|
|
129
|
+
// @ts-expect-error - bullResetTimer is a custom property in the Autodarts adapter class
|
|
123
130
|
adapter.bullResetTimer = null;
|
|
124
131
|
}
|
|
125
132
|
|
|
126
133
|
await adapter.setStateAsync("throw.isTriple", { val: isTriple, ack: true });
|
|
127
134
|
await adapter.setStateAsync("throw.isBullseye", { val: isBullseye, ack: true });
|
|
128
135
|
|
|
129
|
-
|
|
136
|
+
// @ts-expect-error - triggerResetSecRuntime is a custom property in the Autodarts adapter class
|
|
137
|
+
const timeoutMs = (Number(adapter.triggerResetSecRuntime) || 0) * 1000;
|
|
130
138
|
if (timeoutMs > 0) {
|
|
131
139
|
if (isTriple) {
|
|
140
|
+
// @ts-expect-error - tripleResetTimer is a custom property in the Autodarts adapter class
|
|
132
141
|
adapter.tripleResetTimer = setTimeout(() => {
|
|
133
142
|
adapter.setState("throw.isTriple", { val: false, ack: true });
|
|
143
|
+
// @ts-expect-error - tripleResetTimer is a custom property in the Autodarts adapter class
|
|
134
144
|
adapter.tripleResetTimer = null;
|
|
135
145
|
}, timeoutMs);
|
|
136
146
|
}
|
|
137
147
|
if (isBullseye) {
|
|
148
|
+
// @ts-expect-error - bullResetTimer is a custom property in the Autodarts adapter class
|
|
138
149
|
adapter.bullResetTimer = setTimeout(() => {
|
|
139
150
|
adapter.setState("throw.isBullseye", { val: false, ack: true });
|
|
151
|
+
// @ts-expect-error - bullResetTimer is a custom property in the Autodarts adapter class
|
|
140
152
|
adapter.bullResetTimer = null;
|
|
141
153
|
}, timeoutMs);
|
|
142
154
|
}
|
package/lib/trafficLight.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// lib/trafficLight.js
|
|
1
2
|
"use strict";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
* - trafficLightColor (HEX)
|
|
8
9
|
* - trafficLightState (String)
|
|
9
10
|
*
|
|
10
|
-
* @param {import("@iobroker/adapter-core").
|
|
11
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
11
12
|
*/
|
|
12
13
|
async function init(adapter) {
|
|
13
14
|
const baseId = "status";
|
|
@@ -73,7 +74,7 @@ async function init(adapter) {
|
|
|
73
74
|
/**
|
|
74
75
|
* Setzt Ampel-Status.
|
|
75
76
|
*
|
|
76
|
-
* @param {import("@iobroker/adapter-core").
|
|
77
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
77
78
|
* @param {"green"|"yellow"|"red"} status Gewünschter Ampelstatus (green/yellow/red)
|
|
78
79
|
*/
|
|
79
80
|
async function setStatus(adapter, status) {
|
package/lib/visit.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* Legt Visit-Channel und States an.
|
|
6
6
|
*
|
|
7
|
-
* @param {import("@iobroker/adapter-core").
|
|
7
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
8
8
|
*/
|
|
9
9
|
async function init(adapter) {
|
|
10
10
|
await adapter.extendObjectAsync("visit", {
|
|
@@ -41,7 +41,7 @@ async function init(adapter) {
|
|
|
41
41
|
/**
|
|
42
42
|
* Berechnet und schreibt die Visit-Summe, wenn ein Visit abgeschlossen ist.
|
|
43
43
|
*
|
|
44
|
-
* @param {import("@iobroker/adapter-core").
|
|
44
|
+
* @param {import("@iobroker/adapter-core").AdapterInstance} adapter Adapter-Instanz dieses Autodarts-Adapters
|
|
45
45
|
* @param {any[]} currentThrows Array der aktuellen Würfe aus /api/state
|
|
46
46
|
* @param {number} lastThrowsCount Anzahl Würfe beim letzten Poll (adapter.lastThrowsCount)
|
|
47
47
|
* @returns {Promise<number>} Neue lastThrowsCount, damit du ihn im Adapter speichern kannst
|
|
@@ -54,6 +54,7 @@ async function updateVisit(adapter, currentThrows, lastThrowsCount) {
|
|
|
54
54
|
// - vorher weniger als 3 waren (Visit gerade abgeschlossen)
|
|
55
55
|
if (currentCount === 3 && lastThrowsCount < 3) {
|
|
56
56
|
const lastThree = currentThrows.slice(-3);
|
|
57
|
+
// @ts-expect-error - calcScore is a custom method in the Autodarts adapter class
|
|
57
58
|
const visitSum = lastThree.reduce((sum, dart) => sum + adapter.calcScore(dart), 0);
|
|
58
59
|
|
|
59
60
|
await adapter.setStateAsync("visit.score", { val: visitSum, ack: true });
|
package/main.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const utils = require("@iobroker/adapter-core");
|
|
4
|
-
const http = require("http");
|
|
5
4
|
const throwLogic = require("./lib/throw");
|
|
6
5
|
const visit = require("./lib/visit");
|
|
7
6
|
const trafficLight = require("./lib/trafficLight");
|
|
7
|
+
const httpHelper = require("./lib/httpHelper");
|
|
8
8
|
|
|
9
9
|
class Autodarts extends utils.Adapter {
|
|
10
10
|
constructor(options) {
|
|
@@ -27,7 +27,7 @@ class Autodarts extends utils.Adapter {
|
|
|
27
27
|
this.tripleMaxScoreRuntime = null; // Laufzeitwert für Triple-Maxschwelle
|
|
28
28
|
|
|
29
29
|
// NEU: Reset-Timeout + Timer für isTriple/isBullseye
|
|
30
|
-
this.
|
|
30
|
+
this.triggerResetSecRuntime = null;
|
|
31
31
|
this.tripleResetTimer = null;
|
|
32
32
|
this.bullResetTimer = null;
|
|
33
33
|
}
|
|
@@ -38,16 +38,10 @@ class Autodarts extends utils.Adapter {
|
|
|
38
38
|
// Defaults aus io-package.json absichern
|
|
39
39
|
this.config.host ??= "127.0.0.1";
|
|
40
40
|
this.config.port ??= 3180;
|
|
41
|
-
this.config.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.config.
|
|
45
|
-
// eslint-disable-next-line jsdoc/check-tag-names
|
|
46
|
-
/** @ts-expect-error tripleMaxScore is defined in io-package.json but not in AdapterConfig */
|
|
47
|
-
this.config.tripleMaxScore ??= 20; // Maximalpunktzahl für Triple-Flag
|
|
48
|
-
// eslint-disable-next-line jsdoc/check-tag-names
|
|
49
|
-
/** @ts-expect-error triggerResetMs is defined in io-package.json/jsonConfig but not in AdapterConfig */
|
|
50
|
-
this.config.triggerResetMs ??= 0; // 0 = kein Auto-Reset
|
|
41
|
+
this.config.intervalSec ??= 1; // Sekunden
|
|
42
|
+
this.config.tripleMinScore ??= 1;
|
|
43
|
+
this.config.tripleMaxScore ??= 20;
|
|
44
|
+
this.config.triggerResetSec ??= 0; // 0 = kein Auto-Reset
|
|
51
45
|
|
|
52
46
|
// Visit-Struktur anlegen (ausgelagert)
|
|
53
47
|
await visit.init(this);
|
|
@@ -164,7 +158,7 @@ class Autodarts extends utils.Adapter {
|
|
|
164
158
|
native: {},
|
|
165
159
|
});
|
|
166
160
|
|
|
167
|
-
// Config-Channel und States für tripleMinScore / tripleMaxScore /
|
|
161
|
+
// Config-Channel und States für tripleMinScore / tripleMaxScore / triggerResetSec (zur Laufzeit änderbar)
|
|
168
162
|
await this.extendObjectAsync("config", {
|
|
169
163
|
type: "channel",
|
|
170
164
|
common: {
|
|
@@ -214,35 +208,29 @@ class Autodarts extends utils.Adapter {
|
|
|
214
208
|
native: {},
|
|
215
209
|
});
|
|
216
210
|
|
|
217
|
-
await this.extendObjectAsync("config.
|
|
211
|
+
await this.extendObjectAsync("config.triggerResetSec", {
|
|
218
212
|
type: "state",
|
|
219
213
|
common: {
|
|
220
214
|
name: {
|
|
221
|
-
en: "Triple/Bull reset (
|
|
222
|
-
de: "Triple/Bull Reset (
|
|
215
|
+
en: "Triple/Bull reset (s)",
|
|
216
|
+
de: "Triple/Bull Reset (s)",
|
|
223
217
|
},
|
|
224
218
|
type: "number",
|
|
225
219
|
role: "value",
|
|
226
220
|
read: true,
|
|
227
221
|
write: true,
|
|
228
222
|
desc: {
|
|
229
|
-
en: "Time in
|
|
230
|
-
de: "Zeit in
|
|
223
|
+
en: "Time in seconds after which isTriple and isBullseye are reset to false",
|
|
224
|
+
de: "Zeit in Sekunden, nach der isTriple und isBullseye wieder auf false gesetzt werden",
|
|
231
225
|
},
|
|
232
226
|
},
|
|
233
227
|
native: {},
|
|
234
228
|
});
|
|
235
229
|
|
|
236
230
|
// Laufzeitwerte initial aus Adapter-Config setzen
|
|
237
|
-
// eslint-disable-next-line jsdoc/check-tag-names
|
|
238
|
-
/** @ts-expect-error tripleMinScore is defined in io-package.json but not in AdapterConfig */
|
|
239
231
|
this.tripleMinScoreRuntime = Number(this.config.tripleMinScore) || 1;
|
|
240
|
-
// eslint-disable-next-line jsdoc/check-tag-names
|
|
241
|
-
/** @ts-expect-error tripleMaxScore is defined in io-package.json but not in AdapterConfig */
|
|
242
232
|
this.tripleMaxScoreRuntime = Number(this.config.tripleMaxScore) || 20;
|
|
243
|
-
//
|
|
244
|
-
/** @ts-expect-error triggerResetMs is defined in io-package.json/jsonConfig but not in AdapterConfig */
|
|
245
|
-
this.triggerResetMsRuntime = Number(this.config.triggerResetMs) || 0; // 0 = kein Auto-Reset
|
|
233
|
+
this.triggerResetSecRuntime = Number(this.config.triggerResetSec) || 0; // 0 = kein Auto-Reset
|
|
246
234
|
|
|
247
235
|
await this.setStateAsync("config.tripleMinScore", {
|
|
248
236
|
val: this.tripleMinScoreRuntime,
|
|
@@ -253,8 +241,8 @@ class Autodarts extends utils.Adapter {
|
|
|
253
241
|
ack: true,
|
|
254
242
|
});
|
|
255
243
|
|
|
256
|
-
await this.setStateAsync("config.
|
|
257
|
-
val: this.
|
|
244
|
+
await this.setStateAsync("config.triggerResetSec", {
|
|
245
|
+
val: this.triggerResetSecRuntime,
|
|
258
246
|
ack: true,
|
|
259
247
|
});
|
|
260
248
|
|
|
@@ -264,14 +252,17 @@ class Autodarts extends utils.Adapter {
|
|
|
264
252
|
// Auf Änderungen am Config-State hören
|
|
265
253
|
this.subscribeStates("config.tripleMinScore");
|
|
266
254
|
this.subscribeStates("config.tripleMaxScore");
|
|
267
|
-
this.subscribeStates("config.
|
|
255
|
+
this.subscribeStates("config.triggerResetSec");
|
|
268
256
|
|
|
269
257
|
// Zustand zurücksetzen
|
|
270
258
|
this.lastThrowsCount = 0;
|
|
271
259
|
this.lastSignature = "";
|
|
272
260
|
|
|
261
|
+
// Polling-Intervall aus Sekunden in Millisekunden umrechnen
|
|
262
|
+
const pollIntervalMs = (Number(this.config.intervalSec) || 1) * 1000;
|
|
263
|
+
|
|
273
264
|
// Polling starten
|
|
274
|
-
this.pollTimer = setInterval(() => this.fetchState(),
|
|
265
|
+
this.pollTimer = setInterval(() => this.fetchState(), pollIntervalMs);
|
|
275
266
|
this.fetchState();
|
|
276
267
|
|
|
277
268
|
// Boardmanager-Version und Kameras abfragen und alle 5 Minuten aktualisieren
|
|
@@ -300,12 +291,12 @@ class Autodarts extends utils.Adapter {
|
|
|
300
291
|
}
|
|
301
292
|
|
|
302
293
|
/**
|
|
303
|
-
* Reaktion auf State-Änderungen (z. B. config.tripleMinScore / config.tripleMaxScore / config.
|
|
294
|
+
* Reaktion auf State-Änderungen (z. B. config.tripleMinScore / config.tripleMaxScore / config.triggerResetSec)
|
|
304
295
|
*
|
|
305
296
|
* @param {string} id Full state id
|
|
306
297
|
* @param {ioBroker.State | null | undefined} state New state value (ack=false on user write)
|
|
307
298
|
*/
|
|
308
|
-
onStateChange(id, state) {
|
|
299
|
+
async onStateChange(id, state) {
|
|
309
300
|
if (!state) {
|
|
310
301
|
return;
|
|
311
302
|
}
|
|
@@ -328,7 +319,7 @@ class Autodarts extends utils.Adapter {
|
|
|
328
319
|
this.log.info(`Runtime tripleMinScore updated to ${val}`);
|
|
329
320
|
|
|
330
321
|
// Wert mit ack bestätigen
|
|
331
|
-
this.
|
|
322
|
+
await this.setStateAsync("config.tripleMinScore", { val, ack: true });
|
|
332
323
|
} else if (idShort === "config.tripleMaxScore") {
|
|
333
324
|
const val = Number(state.val);
|
|
334
325
|
if (!Number.isFinite(val) || val <= 0) {
|
|
@@ -340,194 +331,132 @@ class Autodarts extends utils.Adapter {
|
|
|
340
331
|
this.log.info(`Runtime tripleMaxScore updated to ${val}`);
|
|
341
332
|
|
|
342
333
|
// Wert mit ack bestätigen
|
|
343
|
-
this.
|
|
344
|
-
} else if (idShort === "config.
|
|
334
|
+
await this.setStateAsync("config.tripleMaxScore", { val, ack: true });
|
|
335
|
+
} else if (idShort === "config.triggerResetSec") {
|
|
345
336
|
const val = Number(state.val);
|
|
346
337
|
if (!Number.isFinite(val) || val < 0) {
|
|
347
|
-
this.log.warn(`Invalid
|
|
338
|
+
this.log.warn(`Invalid triggerResetSec value: ${state.val}`);
|
|
348
339
|
return;
|
|
349
340
|
}
|
|
350
341
|
|
|
351
|
-
this.
|
|
352
|
-
this.log.info(`Runtime
|
|
342
|
+
this.triggerResetSecRuntime = val;
|
|
343
|
+
this.log.info(`Runtime triggerResetSec updated to ${val} s`);
|
|
353
344
|
|
|
354
345
|
// Wert mit ack bestätigen
|
|
355
|
-
this.
|
|
346
|
+
await this.setStateAsync("config.triggerResetSec", { val, ack: true });
|
|
356
347
|
}
|
|
357
348
|
}
|
|
358
349
|
|
|
359
350
|
/**
|
|
360
351
|
* Autodarts API abfragen und Visit-Summe schreiben
|
|
361
352
|
*/
|
|
362
|
-
fetchState() {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
port: this.config.port,
|
|
366
|
-
path: "/api/state",
|
|
367
|
-
method: "GET",
|
|
368
|
-
timeout: 1500,
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
const req = http.request(options, res => {
|
|
372
|
-
let data = "";
|
|
373
|
-
|
|
374
|
-
res.on("data", chunk => (data += chunk));
|
|
375
|
-
res.on("end", async () => {
|
|
376
|
-
this.offline = false;
|
|
377
|
-
this.setState("online", true, true); // Server erreichbar
|
|
378
|
-
|
|
379
|
-
try {
|
|
380
|
-
const state = JSON.parse(data);
|
|
381
|
-
const boardStatus = state.status || ""; // z.B. "Throw" oder "Takeout"
|
|
382
|
-
|
|
383
|
-
if (boardStatus === "Throw") {
|
|
384
|
-
await trafficLight.setStatus(this, "green");
|
|
385
|
-
} else if (boardStatus === "Takeout") {
|
|
386
|
-
await trafficLight.setStatus(this, "yellow");
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Nur weiter, wenn throws existieren, Array ist und nicht leer
|
|
390
|
-
if (!state.throws || !Array.isArray(state.throws) || state.throws.length === 0) {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const currentThrows = state.throws;
|
|
395
|
-
|
|
396
|
-
// Prüfen, ob sich die Würfe geändert haben
|
|
397
|
-
const signature = JSON.stringify(
|
|
398
|
-
currentThrows.map(d => ({
|
|
399
|
-
name: d.segment?.name || "",
|
|
400
|
-
mult: d.segment?.multiplier || 0,
|
|
401
|
-
})),
|
|
402
|
-
);
|
|
403
|
-
|
|
404
|
-
if (signature === this.lastSignature) {
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
this.lastSignature = signature;
|
|
408
|
-
|
|
409
|
-
// letzten Dart in States schreiben (ausgelagert)
|
|
410
|
-
const lastDart = currentThrows[currentThrows.length - 1];
|
|
411
|
-
await throwLogic.updateThrow(this, lastDart);
|
|
412
|
-
|
|
413
|
-
// Visit-Summe aktualisieren (ausgelagert)
|
|
414
|
-
this.lastThrowsCount = await visit.updateVisit(this, currentThrows, this.lastThrowsCount);
|
|
415
|
-
} catch (e) {
|
|
416
|
-
this.log.warn(`Autodarts API Fehler: ${e.message} | Daten: ${data.substring(0, 200)}...`);
|
|
417
|
-
// Bei JSON-Fehler: Board war erreichbar, aber Antwort kaputt
|
|
418
|
-
this.setState("online", true, true);
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
});
|
|
353
|
+
async fetchState() {
|
|
354
|
+
try {
|
|
355
|
+
const data = await httpHelper.makeRequest(this, "/api/state");
|
|
422
356
|
|
|
423
|
-
|
|
424
|
-
if (
|
|
425
|
-
this.log.
|
|
426
|
-
this.offline = true;
|
|
357
|
+
// Log wenn Verbindung wiederhergestellt wurde
|
|
358
|
+
if (this.offline) {
|
|
359
|
+
this.log.info("Autodarts connection restored");
|
|
427
360
|
}
|
|
428
|
-
|
|
429
|
-
this.
|
|
430
|
-
|
|
361
|
+
this.offline = false;
|
|
362
|
+
await this.setStateAsync("online", true, true); // Server erreichbar
|
|
363
|
+
|
|
364
|
+
try {
|
|
365
|
+
const state = JSON.parse(data);
|
|
366
|
+
const boardStatus = state.status || ""; // z.B. "Throw" oder "Takeout"
|
|
367
|
+
|
|
368
|
+
if (boardStatus === "Throw") {
|
|
369
|
+
await trafficLight.setStatus(this, "green");
|
|
370
|
+
} else if (boardStatus === "Takeout") {
|
|
371
|
+
await trafficLight.setStatus(this, "yellow");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Nur weiter, wenn throws existieren, Array ist und nicht leer
|
|
375
|
+
if (!state.throws || !Array.isArray(state.throws) || state.throws.length === 0) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const currentThrows = state.throws;
|
|
380
|
+
|
|
381
|
+
// Prüfen, ob sich die Würfe geändert haben
|
|
382
|
+
const signature = JSON.stringify(
|
|
383
|
+
currentThrows.map(d => ({
|
|
384
|
+
name: d.segment?.name || "",
|
|
385
|
+
mult: d.segment?.multiplier || 0,
|
|
386
|
+
})),
|
|
387
|
+
);
|
|
431
388
|
|
|
432
|
-
|
|
433
|
-
|
|
389
|
+
if (signature === this.lastSignature) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
this.lastSignature = signature;
|
|
393
|
+
|
|
394
|
+
// letzten Dart in States schreiben (ausgelagert)
|
|
395
|
+
const lastDart = currentThrows[currentThrows.length - 1];
|
|
396
|
+
await throwLogic.updateThrow(this, lastDart);
|
|
397
|
+
|
|
398
|
+
// Visit-Summe aktualisieren (ausgelagert)
|
|
399
|
+
this.lastThrowsCount = await visit.updateVisit(this, currentThrows, this.lastThrowsCount);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
this.log.warn(`Autodarts API Fehler: ${e.message} | Daten: ${data.substring(0, 200)}...`);
|
|
402
|
+
// Bei JSON-Fehler: Board war erreichbar, aber Antwort kaputt
|
|
403
|
+
await this.setStateAsync("online", true, true);
|
|
404
|
+
}
|
|
405
|
+
} catch (error) {
|
|
434
406
|
if (!this.offline) {
|
|
435
|
-
this.log.warn(
|
|
407
|
+
this.log.warn(`Autodarts not reachable: ${error.message}`);
|
|
436
408
|
this.offline = true;
|
|
437
409
|
}
|
|
438
410
|
await trafficLight.setStatus(this, "red"); // Ampel = rot
|
|
439
|
-
this.
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
req.end();
|
|
411
|
+
await this.setStateAsync("online", false, true); // Server offline
|
|
412
|
+
}
|
|
443
413
|
}
|
|
444
414
|
|
|
445
415
|
/**
|
|
446
416
|
* Boardmanager Version abfragen
|
|
447
417
|
*/
|
|
448
|
-
fetchVersion() {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const req = http.request(options, res => {
|
|
458
|
-
let data = "";
|
|
459
|
-
res.on("data", chunk => (data += chunk));
|
|
460
|
-
res.on("end", () => {
|
|
461
|
-
try {
|
|
462
|
-
const version = data.trim();
|
|
463
|
-
this.setState("system.boardVersion", { val: version, ack: true });
|
|
464
|
-
} catch (e) {
|
|
465
|
-
this.log.warn(`Fehler beim Lesen der Version: ${e.message}`);
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
req.on("error", () => {
|
|
471
|
-
// Keine Log-Warnung, nur State leeren
|
|
472
|
-
this.setState("system.boardVersion", { val: "", ack: true });
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
req.on("timeout", () => {
|
|
476
|
-
req.destroy();
|
|
477
|
-
// Keine Log-Warnung, nur State leeren
|
|
478
|
-
this.setState("system.boardVersion", { val: "", ack: true });
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
req.end();
|
|
418
|
+
async fetchVersion() {
|
|
419
|
+
try {
|
|
420
|
+
const data = await httpHelper.makeRequest(this, "/api/version");
|
|
421
|
+
const version = data.trim();
|
|
422
|
+
await this.setStateAsync("system.boardVersion", { val: version, ack: true });
|
|
423
|
+
} catch {
|
|
424
|
+
// Bei Fehler State leeren (keine Log-Warnung)
|
|
425
|
+
await this.setStateAsync("system.boardVersion", { val: "", ack: true });
|
|
426
|
+
}
|
|
482
427
|
}
|
|
483
428
|
|
|
484
429
|
/**
|
|
485
430
|
* Board-Konfiguration abfragen (Kameras)
|
|
486
431
|
*/
|
|
487
|
-
fetchConfig() {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
} catch (e) {
|
|
516
|
-
this.log.warn(`Fehler beim Lesen der Config: ${e.message} | Daten: ${data.substring(0, 200)}...`);
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
req.on("error", () => {
|
|
522
|
-
// Keine Log-Warnung mehr
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
req.on("timeout", () => {
|
|
526
|
-
req.destroy();
|
|
527
|
-
// Keine Log-Warnung mehr
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
req.end();
|
|
432
|
+
async fetchConfig() {
|
|
433
|
+
try {
|
|
434
|
+
const data = await httpHelper.makeRequest(this, "/api/config");
|
|
435
|
+
const cfg = JSON.parse(data);
|
|
436
|
+
|
|
437
|
+
const cam = cfg.cam || {};
|
|
438
|
+
const camInfo = {
|
|
439
|
+
width: cam.width ?? 1280,
|
|
440
|
+
height: cam.height ?? 720,
|
|
441
|
+
fps: cam.fps ?? 20,
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const json = JSON.stringify(camInfo);
|
|
445
|
+
|
|
446
|
+
await this.setStateAsync("system.cam0", { val: json, ack: true });
|
|
447
|
+
await this.setStateAsync("system.cam1", { val: json, ack: true });
|
|
448
|
+
await this.setStateAsync("system.cam2", { val: json, ack: true });
|
|
449
|
+
} catch (error) {
|
|
450
|
+
// Bei Fehler keine Log-Warnung
|
|
451
|
+
if (
|
|
452
|
+
error &&
|
|
453
|
+
typeof error === "object" &&
|
|
454
|
+
typeof error.message === "string" &&
|
|
455
|
+
error.message.includes("JSON")
|
|
456
|
+
) {
|
|
457
|
+
this.log.debug(`Could not parse camera config: ${error.message}`);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
531
460
|
}
|
|
532
461
|
|
|
533
462
|
onUnload(callback) {
|