iobroker.heos 1.12.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,9 +10,6 @@ updates:
10
10
  assignees:
11
11
  - withstu
12
12
  versioning-strategy: increase
13
- ignore:
14
- - dependency-name: "got"
15
- update-types: ["version-update:semver-major"]
16
13
 
17
14
  - package-ecosystem: github-actions
18
15
  directory: "/"
@@ -38,7 +38,7 @@ jobs:
38
38
  runs-on: ${{ matrix.os }}
39
39
  strategy:
40
40
  matrix:
41
- node-version: ["14.x", "16.x", "18.x"]
41
+ node-version: ["16.x", "18.x", "20.x"]
42
42
  os: [ubuntu-latest, windows-latest, macos-latest]
43
43
 
44
44
  steps:
package/README.md CHANGED
@@ -144,6 +144,17 @@ Alternative you can use the script from Uhula: https://forum.iobroker.net/post/4
144
144
  Placeholder for the next version (at the beginning of the line):
145
145
  ### **WORK IN PROGRESS**
146
146
  -->
147
+ ### 2.1.0 (2023-08-05)
148
+ * (withstu) replace got with axios
149
+ * (withstu) improve upnp handling
150
+ * (withstu) prevent duplicate connect messages
151
+
152
+ ### 2.0.0 (2023-08-05)
153
+ * (withstu) fix pipelines and remove node 14.x support
154
+
155
+ ### 1.12.3 (2023-08-05)
156
+ * (withstu) update dependencies
157
+
147
158
  ### 1.12.2 (2023-05-13)
148
159
  * (withstu) optimize error handling
149
160
 
package/io-package.json CHANGED
@@ -1,8 +1,47 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "heos",
4
- "version": "1.12.2",
4
+ "version": "2.1.0",
5
5
  "news": {
6
+ "2.1.0": {
7
+ "en": "replace got with axios\nimprove upnp handling\nprevent duplicate connect messages",
8
+ "de": "ersetzen mit axios\nverbesserte upnp-behandlung\ndoppelte verbindungsnachrichten verhindern",
9
+ "ru": "заменить получилось с axios\nулучшить работу upnp\nпредотвратить дублирование сообщений подключения",
10
+ "pt": "substituir adquirido com axios\nmelhorar o manuseio de upnp\nevitar mensagens de conexão duplicadas",
11
+ "nl": "vertaling:\nverbeter de bovenste hand\nverhinder dubbele berichten",
12
+ "fr": "remplacer obtenu par axios\naméliorer la manutention des ailes\nempêcher les messages de connexion",
13
+ "it": "sostituire ottenuto con assios\nmigliorare la gestione della upnp\nimpedire i messaggi di connessione duplicati",
14
+ "es": "reemplazado por axios\nmejorar el manejo de upnp\nevitar duplicados mensajes de conexión",
15
+ "pl": "zastępować\npoprawić\nlinkować",
16
+ "uk": "заміну отримав з аксіосом\nполіпшити процес обробки\nзапобігання дублікатів повідомлень з'єднання",
17
+ "zh-cn": "改为\n改进处理\n防止信息重复"
18
+ },
19
+ "2.0.0": {
20
+ "en": "fix pipelines and remove node 14.x support",
21
+ "de": "pipelines fixieren und knoten 14.x-unterstützung entfernen",
22
+ "ru": "исправить трубопроводы и удалить node 14.x поддержка",
23
+ "pt": "corrigir pipelines e remover o nó 14.x suporte",
24
+ "nl": "verwijder node 14.x ondersteuning",
25
+ "fr": "fixer les pipelines et retirer le support node 14.x",
26
+ "it": "fissare le tubazioni e rimuovere il supporto nodo 14.x",
27
+ "es": "arreglar los oleoductos y eliminar el nodo 14.x soporte",
28
+ "pl": "ustawienie rurociągów i usunięcie węzła 14x",
29
+ "uk": "кріплення трубопроводів і видалення вузла 14.x",
30
+ "zh-cn": "f 配件和取消14x的支助"
31
+ },
32
+ "1.12.3": {
33
+ "en": "update dependencies",
34
+ "de": "aktualisierung der abhängigkeiten",
35
+ "ru": "обновление зависимостей",
36
+ "pt": "dependências",
37
+ "nl": "vertaling:",
38
+ "fr": "mettre à jour les dépendances",
39
+ "it": "aggiornamento dipendenze",
40
+ "es": "dependencias de actualización",
41
+ "pl": "zależności",
42
+ "uk": "оновлення залежності",
43
+ "zh-cn": "a. 最新受扶养人"
44
+ },
6
45
  "1.12.2": {
7
46
  "en": "optimize error handling",
8
47
  "de": "optimierung der fehlerbehandlung",
@@ -54,45 +93,6 @@
54
93
  "pl": "ulepszenie przycisków w przeglądarce",
55
94
  "uk": "покращувати відтворення всіх кнопок у функції перегляду",
56
95
  "zh-cn": "b. 代管特区改善所有但顿作用"
57
- },
58
- "1.11.3": {
59
- "en": "update some dependencies\nimprove failure handling\nimprove play all button in browse feature",
60
- "de": "einige abhängigkeiten aktualisieren\nverbesserung der fehlerbehebung\nverbessern spielen alle taste in der browser-funktion",
61
- "ru": "обновить некоторые зависимости\nулучшить обработку сбоев\nулучшить играть все кнопки в функции просмотра",
62
- "pt": "atualizar algumas dependências\nmelhorar o manuseio de falhas\nmelhorar jogar todos os botões em procurar recurso",
63
- "nl": "vertaling:\nverbeter falen\nverbeter alle knoppen in browse",
64
- "fr": "mettre à jour certaines dépendances\naméliorer la manipulation des défaillances\naméliorer jouer tous les boutons dans la fonction de navigation",
65
- "it": "aggiornare alcune dipendenze\nmigliorare la gestione dei guasti\nmigliorare giocare tutto il pulsante nella funzione di navigazione",
66
- "es": "actualizar algunas dependencias\nmejorar el manejo de fallos\nmejorar el juego de todos los botones en la función de navegación",
67
- "pl": "aktualizacja\npolepszenie\nulepszenie przycisków w przeglądarce",
68
- "uk": "оновлення деяких залежностей\nполіпшення безпеки\nпокращувати відтворення всіх кнопок у функції перегляду",
69
- "zh-cn": "二. 更新一些依赖性\n改进失败\nb. 代管特区改善所有但顿作用"
70
- },
71
- "1.11.2": {
72
- "en": "adopt to new adapter structure",
73
- "de": "neue adapterstruktur übernehmen",
74
- "ru": "принять к новой структуре адаптера",
75
- "pt": "adotar a nova estrutura do adaptador",
76
- "nl": "adopteren",
77
- "fr": "adopter à la nouvelle structure de l'adaptateur",
78
- "it": "adottare per la nuova struttura adattatore",
79
- "es": "adoptar a nueva estructura de adaptador",
80
- "pl": "zaadoptowanie nowej struktury adapterowej",
81
- "uk": "прийняти до нової структури адаптера",
82
- "zh-cn": "通过新的适应结构"
83
- },
84
- "1.11.1": {
85
- "en": "fix release",
86
- "de": "zurück zur übersicht",
87
- "ru": "исправить релиз",
88
- "pt": "liberação de correção",
89
- "nl": "loslaten",
90
- "fr": "correction",
91
- "it": "rilascio corretto",
92
- "es": "corrección de liberación",
93
- "pl": "naprawa",
94
- "uk": "фіксувати реліз",
95
- "zh-cn": "f 固定释放"
96
96
  }
97
97
  },
98
98
  "title": "HEOS",
@@ -86,7 +86,9 @@ class HeosPlayer {
86
86
  this.heos.initPlayerStatistics(this.ip);
87
87
 
88
88
  //Init Upnp
89
- this.upnp = new HeosUPnP(this.heos, player.ip);
89
+ if(this.upnp === undefined) {
90
+ this.upnp = new HeosUPnP(this.heos, player.ip);
91
+ }
90
92
 
91
93
  //Channel
92
94
  await this.heos.setObjectAsync(this.base_state_path, {
@@ -1355,15 +1357,26 @@ class HeosPlayer {
1355
1357
  }
1356
1358
 
1357
1359
  async updateUpnp(){
1358
- if(this.upnp.getServiceList() && Object.keys(this.upnp.getServiceList()).length === 0){
1359
- await this.upnp.init();
1360
+ if(this.connected){
1361
+ if(this.upnp.getServiceList() && Object.keys(this.upnp.getServiceList()).length === 0){
1362
+ try{
1363
+ await this.upnp.init();
1364
+ } catch(err){
1365
+ if(err.code != 'ECONNABORTED') {
1366
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1367
+ this.logWarn('[upnp] failed to init upnp: ' + err, false);
1368
+ } else {
1369
+ this.logDebug('[upnp] failed to init upnp: ' + err, false);
1370
+ }
1371
+ }
1372
+ }
1373
+ this.logDebug('[upnp] Allowed Services: ' + JSON.stringify(this.upnp.getServiceList()));
1374
+ await this.getUpnpRenderingControlState();
1375
+ await this.getUpnpACTState();
1376
+ await this.getUpnpGroupControlState();
1377
+ await this.getUpnpZoneControlState();
1378
+ await this.getUpnpAVTransportState();
1360
1379
  }
1361
- this.logDebug('[upnp] Allowed Services: ' + JSON.stringify(this.upnp.getServiceList()));
1362
- await this.getUpnpRenderingControlState();
1363
- await this.getUpnpACTState();
1364
- await this.getUpnpGroupControlState();
1365
- await this.getUpnpZoneControlState();
1366
- await this.getUpnpAVTransportState();
1367
1380
  }
1368
1381
 
1369
1382
  async getUpnpRenderingControlState(){
@@ -1391,8 +1404,12 @@ class HeosPlayer {
1391
1404
  }
1392
1405
  }
1393
1406
  } catch(err){
1394
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1395
- this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1407
+ if(err.code != 'ECONNABORTED') {
1408
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1409
+ this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1410
+ } else {
1411
+ this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1412
+ }
1396
1413
  }
1397
1414
  } else {
1398
1415
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
@@ -1424,8 +1441,12 @@ class HeosPlayer {
1424
1441
  }
1425
1442
  }
1426
1443
  } catch(err){
1427
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1428
- this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1444
+ if(err.code != 'ECONNABORTED') {
1445
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1446
+ this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1447
+ } else {
1448
+ this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1449
+ }
1429
1450
  }
1430
1451
  if(state
1431
1452
  && state.DevicePower
@@ -1465,8 +1486,12 @@ class HeosPlayer {
1465
1486
  }
1466
1487
  }
1467
1488
  } catch(err){
1468
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1469
- this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1489
+ if(err.code != 'ECONNABORTED') {
1490
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1491
+ this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1492
+ } else {
1493
+ this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1494
+ }
1470
1495
  }
1471
1496
  } else {
1472
1497
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
@@ -1498,8 +1523,12 @@ class HeosPlayer {
1498
1523
  }
1499
1524
  }
1500
1525
  } catch(err){
1501
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1502
- this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1526
+ if(err.code != 'ECONNABORTED') {
1527
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1528
+ this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1529
+ } else {
1530
+ this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1531
+ }
1503
1532
  }
1504
1533
  } else {
1505
1534
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
@@ -1531,8 +1560,12 @@ class HeosPlayer {
1531
1560
  }
1532
1561
  }
1533
1562
  } catch(err){
1534
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1535
- this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1563
+ if(err.code != 'ECONNABORTED') {
1564
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1565
+ this.logWarn('[upnp] get ' + service + ' state failed: ' + err, false);
1566
+ } else {
1567
+ this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1568
+ }
1536
1569
  }
1537
1570
 
1538
1571
  //Track Meta
@@ -1598,8 +1631,12 @@ class HeosPlayer {
1598
1631
  try{
1599
1632
  const result = await this.upnp.sendCommand(service, action, data);
1600
1633
  } catch(err){
1601
- this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1602
- this.logWarn('[upnp] set device power state failed: ' + err, false);
1634
+ if(err.code != 'ECONNABORTED') {
1635
+ this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
1636
+ this.logWarn('[upnp] set device power state failed: ' + err, false);
1637
+ } else {
1638
+ this.logDebug('[upnp] set device power state failed: ' + err, false);
1639
+ }
1603
1640
  }
1604
1641
  } else {
1605
1642
  this.logWarn('[upnp] set device power state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
package/lib/heos-upnp.js CHANGED
@@ -6,14 +6,12 @@
6
6
  'use strict';
7
7
 
8
8
  const { URL } = require('url');
9
- const got = require('got');
9
+ const axios = require('axios');
10
10
  const {decode} = require('html-entities');
11
11
  const keyInObject = require('./tools').keyInObject;
12
12
 
13
13
  const {XMLParser, XMLBuilder} = require('fast-xml-parser');
14
14
 
15
- const USER_AGENT = 'LINUX UPnP/1.0 Denon-Heos/149200';
16
-
17
15
  class HeosUPnP {
18
16
  /**
19
17
  * @param {string} ip IP address of player
@@ -24,23 +22,20 @@ class HeosUPnP {
24
22
 
25
23
  this.ip = ip;
26
24
  this.url = 'http://' + this.ip + ':60006/upnp/desc/aios_device/aios_device.xml';
27
-
28
- this.client = got.extend({
29
- headers: {
30
- 'user-agent': USER_AGENT
31
- }
32
- });
33
25
  }
34
26
 
35
27
  async init() {
36
- this.services = {};
37
- const response = await this.client(this.url);
28
+ const response = await axios({
29
+ method: 'get',
30
+ url: this.url,
31
+ timeout: 30000
32
+ });
38
33
  const options = {
39
34
  parseTrueNumberOnly: true,
40
35
  processEntities: false
41
36
  };
42
37
  const parser = new XMLParser(options);
43
- const device = parser.parse(response.body).root.device;
38
+ const device = parser.parse(response.data).root.device;
44
39
 
45
40
  this.deviceType = device.deviceType;
46
41
  this.friendlyName = device.friendlyName;
@@ -80,17 +75,23 @@ class HeosUPnP {
80
75
  }
81
76
  const id = service.serviceType.split(':')[3];
82
77
 
83
- const response = await this.client(service.SCPDURL);
84
- const options = {
85
- parseTrueNumberOnly: true,
86
- processEntities: false
87
- };
88
- const parser = new XMLParser(options);
89
- const serviceDefinition = await parser.parse(response.body).scpd;
90
- service.actions = await this.parseActions(serviceDefinition);
91
-
92
- services[id] = service;
93
- this.services[id] = service;
78
+ if(!this.hasService(id)){
79
+ const response = await axios({
80
+ method: 'get',
81
+ url: service.SCPDURL,
82
+ timeout: 30000
83
+ });
84
+ const options = {
85
+ parseTrueNumberOnly: true,
86
+ processEntities: false
87
+ };
88
+ const parser = new XMLParser(options);
89
+ const serviceDefinition = await parser.parse(response.data).scpd;
90
+ service.actions = await this.parseActions(serviceDefinition);
91
+
92
+ this.services[id] = service;
93
+ }
94
+ services[id] = this.getService(id);
94
95
  }
95
96
  return services;
96
97
  }
@@ -186,23 +187,19 @@ class HeosUPnP {
186
187
  }
187
188
  const soapBody = this.getSOAPBody(service, action, data);
188
189
 
189
- const res = await this.client({
190
- throwHttpErrors: false,
190
+ const response = await axios({
191
+ method: 'post',
191
192
  url: service.controlURL,
192
- method: 'POST',
193
- body: soapBody,
194
193
  headers: {
195
194
  'Content-Type': 'text/xml; charset="utf-8"',
196
195
  'Content-Length': soapBody.length,
197
196
  'Connection': 'close',
198
197
  'SOAPACTION': `"${service.serviceType}#${action.name}"`
199
- }
198
+ },
199
+ data: soapBody,
200
+ timeout: 30000
200
201
  });
201
-
202
- if (res.statusCode !== 200) {
203
- throw Error('soap command ' + action.name + ' failure: ' + res.statusCode);
204
- }
205
- const result = this.parseSOAPResponse(res.body, action.name, action.argOut);
202
+ const result = this.parseSOAPResponse(response.data, action.name, action.argOut);
206
203
 
207
204
  const options = {
208
205
  parseTrueNumberOnly: true,
package/main.js CHANGED
@@ -46,7 +46,7 @@ class Heos extends utils.Adapter {
46
46
 
47
47
  this.start_players_errors = 0;
48
48
  this.ssdp_retry_counter = 0;
49
- this.player_ips = [];
49
+ this.known_player_ips = [];
50
50
 
51
51
  this.ssdp_player_ips = [];
52
52
 
@@ -2014,15 +2014,15 @@ class Heos extends utils.Adapter {
2014
2014
  throw new Error('HEOS responded with invalid data.');
2015
2015
  } else {
2016
2016
  if (!(pid in this.players)) {
2017
- const heosPlayer = new HeosPlayer(this, player);
2017
+ const heosPlayer = this.players[pid] = new HeosPlayer(this, player);
2018
2018
  // wait until objects are created before connecting, because states shouldn't be set before objects exist
2019
2019
  await heosPlayer.initMetaData(player);
2020
- this.players[pid] = heosPlayer;
2021
2020
  try {
2022
2021
  await heosPlayer.connect();
2023
2022
  } catch (err) {
2024
2023
  this.logDebug("can't connect error: " + err, false);
2025
2024
  this.logWarn("can't connect player " + player.name + ' (' + player.ip + '). Skip.', false);
2025
+ this.raiseFailures(player.ip, ERROR_CODES.General);
2026
2026
  playerConnected = false;
2027
2027
  }
2028
2028
  } else {
@@ -2039,7 +2039,7 @@ class Heos extends utils.Adapter {
2039
2039
  if (!connectedPlayers.includes(pid)) {
2040
2040
  await this.stopPlayer(pid);
2041
2041
  } else {
2042
- connectedPlayerIps.push(this.players[pid].ip)
2042
+ connectedPlayerIps.push(this.players[pid].ip);
2043
2043
  }
2044
2044
  }
2045
2045
  for(const ip in this.reboot_time){
@@ -2049,7 +2049,7 @@ class Heos extends utils.Adapter {
2049
2049
  }
2050
2050
 
2051
2051
  //Check for players in fail state
2052
- let playerInFailState = false
2052
+ let playerInFailState = false;
2053
2053
  for (const id in this.ssdp_player_ips) {
2054
2054
  const ip = this.ssdp_player_ips[id];
2055
2055
  if (this.getUptime(ip) >= 5 && !foundPlayerIps.includes(ip)) {
@@ -2071,7 +2071,7 @@ class Heos extends utils.Adapter {
2071
2071
  }
2072
2072
  } else {
2073
2073
  this.getGroups();
2074
- await this.updatePlayerIPs();
2074
+ await this.updateKnownPlayerIPs();
2075
2075
  }
2076
2076
  } catch (err) {
2077
2077
  this.logError('[startPlayers] ' + err);
@@ -2080,15 +2080,15 @@ class Heos extends utils.Adapter {
2080
2080
  }
2081
2081
  }
2082
2082
 
2083
- async updatePlayerIPs() {
2083
+ async updateKnownPlayerIPs() {
2084
2084
  const states = await this.getStatesAsync('players.*');
2085
- this.player_ips = [];
2085
+ this.known_player_ips = [];
2086
2086
  for (const id in states) {
2087
2087
  if (states[id] && states[id].val) {
2088
2088
  const idSplit = id.split('.');
2089
2089
  const state = idSplit[idSplit.length - 1];
2090
2090
  if (state == 'ip') {
2091
- this.player_ips.push(states[id].val);
2091
+ this.known_player_ips.push(states[id].val);
2092
2092
  }
2093
2093
  }
2094
2094
  }
@@ -2256,8 +2256,8 @@ class Heos extends utils.Adapter {
2256
2256
  rebootAll() {
2257
2257
  this.logWarn('rebooting all players', false);
2258
2258
  this.reboot_ips = [];
2259
- for (let i = 0; i < this.player_ips.length; i++) {
2260
- this.addRebootIp(this.player_ips[i]);
2259
+ for (let i = 0; i < this.known_player_ips.length; i++) {
2260
+ this.addRebootIp(this.known_player_ips[i]);
2261
2261
  }
2262
2262
  this.reboot();
2263
2263
  }
@@ -2478,7 +2478,7 @@ class Heos extends utils.Adapter {
2478
2478
  this.state = STATES.Searching;
2479
2479
 
2480
2480
  //Update Player IPs
2481
- await this.updatePlayerIPs();
2481
+ await this.updateKnownPlayerIPs();
2482
2482
  this.updatePreferedPlayerIPs();
2483
2483
  if (this.reboot_ips.length == 0) {
2484
2484
  this.silent_log_mode = false;
@@ -2507,7 +2507,7 @@ class Heos extends utils.Adapter {
2507
2507
  this.ssdp_retry_counter += 1;
2508
2508
  }
2509
2509
  this.ssdpLeaderElection();
2510
- if (this.ssdp_retry_initPlayerStatisticscounter > 10 && this.player_ips.length > 0) {
2510
+ if (this.ssdp_retry_counter > 10 && this.known_player_ips.length > 0) {
2511
2511
  this.manual_search_mode = true;
2512
2512
  this.silent_log_mode = true;
2513
2513
  this.logWarn("can't find any HEOS devices. Try to connect known device IPs and reboot them to exclude device failure...", false);
@@ -2516,6 +2516,7 @@ class Heos extends utils.Adapter {
2516
2516
  this.logDebug('searching for HEOS devices ...', true);
2517
2517
  this.ssdp_player_ips = [];
2518
2518
  this.nodessdp_client.search(this.ssdp_search_target_name);
2519
+ this.getPlayers();
2519
2520
  }
2520
2521
  }, this.config.searchInterval);
2521
2522
  }
@@ -2551,14 +2552,14 @@ class Heos extends utils.Adapter {
2551
2552
  let ips = [];
2552
2553
  let minFailures = 999;
2553
2554
 
2554
- for (let i = 0; i < this.player_ips.length; i++) {
2555
- const failures = this.getOverallFailures(this.player_ips[i]);
2555
+ for (let i = 0; i < this.known_player_ips.length; i++) {
2556
+ const failures = this.getOverallFailures(this.known_player_ips[i]);
2556
2557
  if (failures < minFailures) {
2557
2558
  ips = [];
2558
- ips.push(this.player_ips[i]);
2559
+ ips.push(this.known_player_ips[i]);
2559
2560
  minFailures = failures;
2560
2561
  } else if (failures == minFailures) {
2561
- ips.push(this.player_ips[i]);
2562
+ ips.push(this.known_player_ips[i]);
2562
2563
  }
2563
2564
  }
2564
2565
  return ips.filter(n => n);
@@ -2730,7 +2731,7 @@ class Heos extends utils.Adapter {
2730
2731
  }
2731
2732
 
2732
2733
  raiseFailures(ip, code) {
2733
- if (ip.length > 0 && this.getUptime(ip) >= 5) {
2734
+ if (ip.length > 0 && (this.state != STATES.Connected || this.getUptime(ip) >= 5)) {
2734
2735
  if (!(ip in this.failure_counter)) {
2735
2736
  this.initFailures(ip);
2736
2737
  }
@@ -2828,7 +2829,7 @@ class Heos extends utils.Adapter {
2828
2829
  }
2829
2830
 
2830
2831
  raiseLeaderFailures(ip) {
2831
- if (ip.length > 0 && this.getUptime(ip) >= 5) {
2832
+ if (ip.length > 0 && (this.state != STATES.Connected || this.getUptime(ip) >= 5)) {
2832
2833
  if (ip in this.leader_failure_counter) {
2833
2834
  this.leader_failure_counter[ip] += 1;
2834
2835
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.heos",
3
- "version": "1.12.2",
3
+ "version": "2.1.0",
4
4
  "description": "The adapter lets control HEOS from ioBroker",
5
5
  "author": {
6
6
  "name": "withstu",
@@ -23,12 +23,12 @@
23
23
  "url": "https://github.com/withstu/ioBroker.heos"
24
24
  },
25
25
  "engines": {
26
- "node": ">= 14"
26
+ "node": ">= 16"
27
27
  },
28
28
  "dependencies": {
29
29
  "@iobroker/adapter-core": "^2.6.8",
30
- "fast-xml-parser": "^4.0.15",
31
- "got": "^11.8.6",
30
+ "fast-xml-parser": "^4.2.7",
31
+ "axios": "^1.4.0",
32
32
  "html-entities": "^2.3.3",
33
33
  "node-ssdp": "^4.0.1",
34
34
  "node-vibrant": "^3.1.6"
@@ -41,20 +41,20 @@
41
41
  "@iobroker/adapter-dev": "^1.2.0",
42
42
  "@iobroker/testing": "^4.1.0",
43
43
  "@tsconfig/node14": "^1.0.3",
44
- "@types/chai": "^4.3.4",
44
+ "@types/chai": "^4.3.5",
45
45
  "@types/chai-as-promised": "^7.1.5",
46
46
  "@types/mocha": "^10.0.1",
47
- "@types/node": "^18.16.3",
47
+ "@types/node": "^20.4.8",
48
48
  "@types/proxyquire": "^1.3.28",
49
49
  "@types/sinon": "^10.0.8",
50
50
  "@types/sinon-chai": "^3.2.9",
51
- "axios": "^1.3.4",
51
+ "axios": "^1.4.0",
52
52
  "chai": "^4.3.7",
53
53
  "chai-as-promised": "^7.1.1",
54
54
  "eslint": "^8.39.0",
55
55
  "mocha": "^10.2.0",
56
56
  "proxyquire": "^2.1.3",
57
- "sinon": "^15.0.4",
57
+ "sinon": "^15.2.0",
58
58
  "sinon-chai": "^3.7.0",
59
59
  "typescript": "~5.0.4"
60
60
  },