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 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
 
@@ -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 (ms)",
8
- "polling_help": "Abfrageintervall in Millisekunden zum Abrufen von Daten vom Autodarts Boardmanager.",
9
- "reset": "Trigger-Reset (ms)",
10
- "reset_help": "Setzt den Triple- und Bullseye-Trigger nach x ms zurück (0 = kein Reset).",
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.",
@@ -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 (ms)",
8
- "polling_help": "Polling interval in milliseconds to retrieve data from the Autodarts Boardmanager.",
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 (ms)",
14
- "reset_help": "Reset the triple and bullseye trigger after x ms (0 = no reset)."
13
+ "reset": "Trigger-Reset (s)",
14
+ "reset_help": "Reset the triple and bullseye trigger after x seconds (0 = no reset)."
15
15
  }
@@ -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 (ms)",
8
- "polling_help": "Intervalo de sondeo en milisegundos para recuperar datos del Autodarts Boardmanager.",
9
- "reset": "Restablecimiento del disparador (ms)",
10
- "reset_help": "Restablezca el disparador triple y de diana después de x ms (0 = sin reinicio).",
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.",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "host_ip": "Autodarts (Boardmanager) Hôte/IP",
3
- "host_ip_help": "Adresse IP de l'Autodarts Boardmanager local.",
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 (ms)",
8
- "polling_help": "Intervalle d'interrogation en millisecondes pour récupérer les données d'Autodarts Boardmanager.",
9
- "reset": "Déclencheur-réinitialisation (ms)",
10
- "reset_help": "Réinitialisez le déclencheur triple et bullseye après x ms (0 = pas de réinitialisation).",
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.",
@@ -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 (ms)",
8
- "polling_help": "Intervallo di polling in millisecondi per recuperare i dati da Autodarts Boardmanager.",
9
- "reset": "Ripristino trigger (ms)",
10
- "reset_help": "Ripristina il trigger triplo e bullseye dopo x ms (0 = nessun ripristino).",
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.",
@@ -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 (ms)",
8
- "polling_help": "Polling-interval in milliseconden om gegevens uit de Autodarts Boardmanager op te halen.",
9
- "reset": "Trigger-reset (ms)",
10
- "reset_help": "Reset de drievoudige en bullseye-trigger na x ms (0 = geen reset).",
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.",
@@ -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 (ms)",
8
- "polling_help": "Interwał odpytywania w milisekundach w celu pobrania danych z menedżera Autodarts Boardmanager.",
9
- "reset": "Reset wyzwalacza (ms)",
10
- "reset_help": "Zresetuj wyzwalacz potrójny i tarczy po x ms (0 = brak resetu).",
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.",
@@ -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 (ms)",
8
- "polling_help": "Intervalo de pesquisa em milissegundos para recuperar dados do Autodarts Boardmanager.",
9
- "reset": "Reinicialização do gatilho (ms)",
10
- "reset_help": "Redefina o gatilho triplo e alvo após x ms (0 = sem reinicialização).",
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.",
@@ -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 мс (0 = сброса нет).",
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": "Поле максимального результата для тройного триггера. Дартс с результатом выше этого значения не будет активировать точку данных тройного триггера.",
@@ -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": "Інтервал опитування в мілісекундах для отримання даних із Autodarts Boardmanager.",
9
- "reset": "Скидання тригера (мс)",
10
- "reset_help": "Скинути потрійний тригер і тригер «яблучко» через x мс (0 = без скидання).",
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.",
@@ -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 毫秒后重置三重触发器和牛眼触发器(0 = 不重置)。",
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": "三重触发器的最大分数字段。分数高于此值的飞镖将不会触发三重触发数据点。",
@@ -126,7 +126,7 @@
126
126
  "marginBottom": "10px"
127
127
  }
128
128
  },
129
- "triggerResetMs": {
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
- "interval": {
145
+ "intervalSec": {
146
146
  "type": "number",
147
147
  "label": "polling",
148
148
  "help": "polling_help",
149
- "default": 1000,
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.1",
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
- "interval": 1000
167
+ "intervalSec": 1,
168
+ "triggerResetSec": 0,
169
+ "tripleMinScore": 1,
170
+ "tripleMaxScore": 20
168
171
  },
169
172
  "objects": [],
170
173
  "instanceObjects": []
@@ -10,7 +10,10 @@ type _AdapterConfig = typeof native;
10
10
  declare global {
11
11
  namespace ioBroker {
12
12
  interface AdapterConfig extends _AdapterConfig {
13
- // Do not enter anything here!
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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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
- const timeoutMs = Number(adapter.triggerResetMsRuntime) || 0;
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
  }
@@ -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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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").Adapter} adapter Adapter-Instanz dieses Autodarts-Adapters
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.triggerResetMsRuntime = null;
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.interval ??= 1000;
42
- // eslint-disable-next-line jsdoc/check-tag-names
43
- /** @ts-expect-error tripleMinScore is defined in io-package.json but not in AdapterConfig */
44
- this.config.tripleMinScore ??= 1; // Mindestpunktzahl für Triple-Flag
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 / triggerResetMs (zur Laufzeit änderbar)
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.triggerResetMs", {
211
+ await this.extendObjectAsync("config.triggerResetSec", {
218
212
  type: "state",
219
213
  common: {
220
214
  name: {
221
- en: "Triple/Bull reset (ms)",
222
- de: "Triple/Bull Reset (ms)",
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 ms after which isTriple and isBullseye are reset to false",
230
- de: "Zeit in ms, nach der isTriple und isBullseye wieder auf false gesetzt werden",
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
- // eslint-disable-next-line jsdoc/check-tag-names
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.triggerResetMs", {
257
- val: this.triggerResetMsRuntime,
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.triggerResetMs");
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(), this.config.interval);
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.triggerResetMs)
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.setState("config.tripleMinScore", { val, ack: true });
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.setState("config.tripleMaxScore", { val, ack: true });
344
- } else if (idShort === "config.triggerResetMs") {
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 triggerResetMs value: ${state.val}`);
338
+ this.log.warn(`Invalid triggerResetSec value: ${state.val}`);
348
339
  return;
349
340
  }
350
341
 
351
- this.triggerResetMsRuntime = val;
352
- this.log.info(`Runtime triggerResetMs updated to ${val} ms`);
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.setState("config.triggerResetMs", { val, ack: true });
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
- const options = {
364
- host: this.config.host,
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
- req.on("error", async () => {
424
- if (!this.offline) {
425
- this.log.warn("Autodarts not reachable");
426
- this.offline = true;
357
+ // Log wenn Verbindung wiederhergestellt wurde
358
+ if (this.offline) {
359
+ this.log.info("Autodarts connection restored");
427
360
  }
428
- await trafficLight.setStatus(this, "red"); // Ampel = rot
429
- this.setState("online", false, true); // Server offline
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
- req.on("timeout", async () => {
433
- req.destroy();
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("Autodarts not reachable");
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.setState("online", false, true); // Server offline bei Timeout
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
- const options = {
450
- host: this.config.host,
451
- port: this.config.port,
452
- path: "/api/version",
453
- method: "GET",
454
- timeout: 1500,
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
- const options = {
489
- host: this.config.host,
490
- port: this.config.port,
491
- path: "/api/config",
492
- method: "GET",
493
- timeout: 1500,
494
- };
495
-
496
- const req = http.request(options, res => {
497
- let data = "";
498
- res.on("data", chunk => (data += chunk));
499
- res.on("end", () => {
500
- try {
501
- const cfg = JSON.parse(data);
502
-
503
- const cam = cfg.cam || {};
504
- const camInfo = {
505
- width: cam.width ?? 1280,
506
- height: cam.height ?? 720,
507
- fps: cam.fps ?? 20,
508
- };
509
-
510
- const json = JSON.stringify(camInfo);
511
-
512
- this.setState("system.cam0", { val: json, ack: true });
513
- this.setState("system.cam1", { val: json, ack: true });
514
- this.setState("system.cam2", { val: json, ack: true });
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.autodarts",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Autodarts Autoscoring",
5
5
  "author": "skvarel <skvarel@inventwo.com>",
6
6
  "contributors": [