iobroker.heos 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -144,6 +144,14 @@ 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.2.2 (2024-10-30)
148
+ * (withstu) add workaround for tidal connect sid = 0 bug and fix audio format
149
+ * (withstu) increase minimum node.js version to recommended version 18
150
+ * (withstu) project maintenance
151
+
152
+ ### 2.2.1 (2024-01-14)
153
+ * (withstu) add workaround for node 19+ ECONNRESET bug #299
154
+
147
155
  ### 2.2.0 (2024-01-06)
148
156
  * (withstu) update dependencies
149
157
  * (withstu) add admin 5 UI support
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "i18n": true,
3
3
  "type": "tabs",
4
+ "tabsStyle": {
5
+ "width": "calc(100% - 100px)"
6
+ },
4
7
  "items": {
5
8
  "loginTab": {
6
9
  "type": "panel",
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "heos",
4
- "version": "2.2.0",
4
+ "version": "2.2.2",
5
5
  "news": {
6
+ "2.2.2": {
7
+ "en": "add workaround for tidal connect sid = 0 bug and fix audio format\nincrease minimum node.js version to recommended version 18\nproject maintenance",
8
+ "de": "fügen sie workaround für tidal connect sid = 0 bug hinzu und reparieren sie audioformat\nminimal node.js-version auf empfohlene version 18 erhöhen\nprojektwartung",
9
+ "ru": "добавить обход для приливного соединения sid = 0 клопов и исправить аудио формат\nувеличить минимальную версию node.js до рекомендуемой версии 18\nтехническое обслуживание проекта",
10
+ "pt": "adicionar solução alternativa para tidal conectar sid = 0 bug e corrigir o formato de áudio\naumentar a versão node.js mínima para a versão recomendada 18\nmanutenção do projeto",
11
+ "nl": "toe te voegen workaround voor getijdenverbinding sid = 0 bug en fix audio-formaat\nverhoog minimum node.js versie naar aanbevolen versie 18\nprojectonderhoud",
12
+ "fr": "ajouter une solution de rechange pour la connexion de marée sid = 0 bug et corriger le format audio\naugmenter la version minimum node.js à la version recommandée 18\nentretien des projets",
13
+ "it": "aggiungere workaround per tidal connect sid = 0 bug e correggere il formato audio\naumentare la versione minima node.js alla versione consigliata 18\nmanutenzione del progetto",
14
+ "es": "añadir workaround for tidal connect sid = 0 bug and fix audio format\naumentar la versión mínima node.js a la versión recomendada 18\nmantenimiento de proyectos",
15
+ "pl": "dodaj pracę dla połączenia pływowego sid = 0 błędów i napraw format audio\nzwiększenie minimalnej wersji node.js do zalecanej wersji 18\nutrzymanie projektu",
16
+ "uk": "add workaround for tidal connection sid = 0 помилка і виправити аудіо формат\nзбільшити мінімальний вузол.js версія для рекомендованої версії 18\nсупровід проекту",
17
+ "zh-cn": "添加潮汐连接 sid = 0 bug 的绕行并修正音频格式\n将最小节点.js版本增加到建议版本18\n项目维护"
18
+ },
19
+ "2.2.1": {
20
+ "en": "add workaround for node 19+ ECONNRESET bug #299",
21
+ "de": "workaround für Knoten hinzufügen 19+ ECONNRESET Bug #299",
22
+ "ru": "добавить обход для узла 19+ ECONNRESET bug #299",
23
+ "pt": "adicionar solução para o nó 19+ ECONNRESET bug #299",
24
+ "nl": "workaround toevoegen voor knooppunt 19+ ECONNRESET bug #299",
25
+ "fr": "ajouter une solution de rechange pour le noeud 19+ bug ECONNRESET #299",
26
+ "it": "aggiungere il lavoro per nodo 19+ ECONNRESET bug #299",
27
+ "es": "añadir trabajo alrededor del nodo 19+ ECONNRESET bug #299",
28
+ "pl": "dodaj pracę dla węzła 19 + ECONNRESET błąd # 299",
29
+ "uk": "add workaround для вершини 19+ ECONNRESET помилка #299",
30
+ "zh-cn": "为节点添加工作环路 19+ 经济错误 # 299"
31
+ },
6
32
  "2.2.0": {
7
33
  "en": "update dependencies\nadd admin 5 UI support\nimprove preferred IP handling\nimprove undefined station handling #299\nreduce upnp requests",
8
34
  "de": "aktualisierung der abhängigkeiten\nadmin 5 UI Unterstützung hinzufügen\nverbesserung der bevorzugten IP-Behandlung\nundefinierte stationshandling #299 verbessern\nreduzieren von upp-anfragen",
@@ -42,19 +68,6 @@
42
68
  "uk": "кріплення трубопроводів і видалення вузла 14.x",
43
69
  "zh-cn": "f 配件和取消14x的支助"
44
70
  },
45
- "1.12.3": {
46
- "en": "update dependencies",
47
- "de": "aktualisierung der abhängigkeiten",
48
- "ru": "обновление зависимостей",
49
- "pt": "dependências",
50
- "nl": "vertaling:",
51
- "fr": "mettre à jour les dépendances",
52
- "it": "aggiornamento dipendenze",
53
- "es": "dependencias de actualización",
54
- "pl": "zależności",
55
- "uk": "оновлення залежності",
56
- "zh-cn": "a. 最新受扶养人"
57
- },
58
71
  "1.12.2": {
59
72
  "en": "optimize error handling",
60
73
  "de": "optimierung der fehlerbehandlung",
@@ -80,19 +93,6 @@
80
93
  "pl": "lider optymalizacji wyborów",
81
94
  "uk": "оптимізація виборів лідера",
82
95
  "zh-cn": "优化领导人选举"
83
- },
84
- "1.12.0": {
85
- "en": "optimize scope handling\nswitch to HEOS default cmd delimiter\nadd configuration to prefer list of IPs for adapter connection\noptimize error handling",
86
- "de": "optimieren sie die handhabung des anwendungsbereichs\nschalter zu HEOS Standard cmd Begrenzung\nkonfiguration hinzufügen, um die Liste der IPs für Adapteranschluss zu bevorzugen\noptimierung der fehlerbehandlung",
87
- "ru": "оптимизация обработки сфер\nпереключиться на HEOS по умолчанию cmd delimiter\nдобавить конфигурацию, чтобы предпочитать список IP для подключения адаптера\nоптимизировать обработку ошибок",
88
- "pt": "otimizar o gerenciamento de escopo\nmudar para delimitador cmd padrão HEOS\nadicionar configuração para preferir lista de IPs para conexão de adaptador\notimizar o manuseio de erros",
89
- "nl": "vertaling:\nwissel naar HOS default cmd delimiter\nvoeg configuratie toe aan de lijst van IP's voor aanpassingsverbinding\nvertaling:",
90
- "fr": "optimiser la manipulation de la portée\npasser à HEOS délimiteur cmd par défaut\najouter la configuration pour préférer la liste des IP pour la connexion d'adaptateur\noptimiser la manipulation des erreurs",
91
- "it": "ottimizzare la gestione delle aree\npassare al delimitatore cmd predefinito HEOS\naggiungere la configurazione per preferire l'elenco degli IP per la connessione dell'adattatore\nottimizzare la gestione degli errori",
92
- "es": "optimizar el manejo del alcance\nconmutación al delimitador por defecto HEOS cmd\nañadir configuración para preferir la lista de IPs para la conexión del adaptador\noptimizar el manejo del error",
93
- "pl": "optymalizacja zakresu obsługi\nprzełącz do HEOS do domyślnie cm delimiter\ndodawanie konfiguracji do preferowania listy IP do połączenia adapterowego\noptymalizowanie błędów",
94
- "uk": "оптимізація управління обсягами\nпереключення до HEOS за замовчуванням cmd delimiter\nдодати конфігурацію для вибору IP-адреси адаптера\nоптимізація обробки помилок",
95
- "zh-cn": "优化处理范围\n转换到HEOS违约情况\n备选案文:\n优化错误处理"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -127,9 +127,11 @@
127
127
  "keywords": [
128
128
  "HEOS"
129
129
  ],
130
- "license": "MIT",
130
+ "licenseInformation": {
131
+ "license": "MIT",
132
+ "type": "free"
133
+ },
131
134
  "platform": "Javascript/Node.js",
132
- "main": "main.js",
133
135
  "icon": "heos.png",
134
136
  "enabled": true,
135
137
  "extIcon": "https://raw.githubusercontent.com/withstu/ioBroker.heos/main/admin/heos.png",
@@ -141,12 +143,13 @@
141
143
  "compact": true,
142
144
  "connectionType": "local",
143
145
  "dataSource": "poll",
146
+ "tier": 2,
144
147
  "adminUI": {
145
148
  "config": "json"
146
149
  },
147
150
  "dependencies": [
148
151
  {
149
- "js-controller": ">=3.3.22"
152
+ "js-controller": ">=5.0.19"
150
153
  }
151
154
  ],
152
155
  "globalDependencies": [
@@ -60,7 +60,7 @@ class HeosPlayer {
60
60
  this.restore_timeout = undefined;
61
61
  this.respond_timeout = undefined;
62
62
  this.now_playing_update_timeout = undefined;
63
-
63
+
64
64
  this.repeatStates = {
65
65
  0:'off',
66
66
  1:'on_all',
@@ -1417,6 +1417,12 @@ class HeosPlayer {
1417
1417
  this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1418
1418
  }
1419
1419
  }
1420
+
1421
+ if(leader_state){
1422
+ //TODO
1423
+ } else {
1424
+ //TODO
1425
+ }
1420
1426
  } else {
1421
1427
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
1422
1428
  }
@@ -1456,6 +1462,13 @@ class HeosPlayer {
1456
1462
  this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1457
1463
  }
1458
1464
  }
1465
+
1466
+ if(leader_state){
1467
+ //TODO
1468
+ } else {
1469
+ //TODO
1470
+ }
1471
+
1459
1472
  if(state
1460
1473
  && state.DevicePower
1461
1474
  && state.DevicePower['@_val']){
@@ -1503,6 +1516,12 @@ class HeosPlayer {
1503
1516
  this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1504
1517
  }
1505
1518
  }
1519
+
1520
+ if(leader_state){
1521
+ //TODO
1522
+ } else {
1523
+ //TODO
1524
+ }
1506
1525
  } else {
1507
1526
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
1508
1527
  }
@@ -1542,6 +1561,12 @@ class HeosPlayer {
1542
1561
  this.logDebug('[upnp] get ' + service + ' state failed: ' + err, false);
1543
1562
  }
1544
1563
  }
1564
+
1565
+ if(leader_state){
1566
+ //TODO
1567
+ } else {
1568
+ //TODO
1569
+ }
1545
1570
  } else {
1546
1571
  this.logDebug('[upnp] get ' + service + ' state is not supported by player ' + this.name + ' (' + this.ip + ')', false);
1547
1572
  }
@@ -1604,12 +1629,8 @@ class HeosPlayer {
1604
1629
  }
1605
1630
 
1606
1631
  let format = '';
1607
- if(meta.desc && Array.isArray(meta.desc)){
1608
- for(const desc of meta.desc){
1609
- if(desc['@_id'] == 'audioFormat'){
1610
- format = desc.value;
1611
- }
1612
- }
1632
+ if(meta.desc && meta.desc['@_id'] == 'audioFormat') {
1633
+ format = meta.desc.value;
1613
1634
  }
1614
1635
  this.heos.setState(this.state_path + 'current_audio_format', format, true);
1615
1636
  } else {
@@ -1669,6 +1690,12 @@ class HeosPlayer {
1669
1690
  }
1670
1691
  }
1671
1692
 
1693
+ if(leader_state){
1694
+ //TODO
1695
+ } else {
1696
+ //TODO
1697
+ }
1698
+
1672
1699
  if(state){
1673
1700
  this.power = (state == 'ON') ? true : false;
1674
1701
  this.heos.setState(this.state_path + 'power', this.power, true);
@@ -1689,7 +1716,7 @@ class HeosPlayer {
1689
1716
  };
1690
1717
  if(this.upnp.hasService(service) && this.upnp.hasServiceAction(service, action)){
1691
1718
  try{
1692
- const result = await this.upnp.sendCommand(service, action, data);
1719
+ await this.upnp.sendCommand(service, action, data);
1693
1720
  } catch(err){
1694
1721
  if(err.code != 'ECONNABORTED') {
1695
1722
  this.heos.raiseFailures(this.ip, ERROR_CODES.Upnp);
@@ -1711,8 +1738,8 @@ class HeosPlayer {
1711
1738
  * @param {String} cmd
1712
1739
  */
1713
1740
  async parseResponse(jdata, jmsg, cmd_group, cmd) {
1714
- const pid = jmsg.pid; // TODO: unused
1715
-
1741
+ //const pid = jmsg.pid;
1742
+
1716
1743
  this.detectHeosResponseTimeout();
1717
1744
  try {
1718
1745
  switch (cmd_group) {
@@ -1848,7 +1875,10 @@ class HeosPlayer {
1848
1875
  }, 30000);
1849
1876
 
1850
1877
  //Filter invalid responses
1851
- if(jdata.payload.hasOwnProperty('sid') && jdata.payload.sid != 0){
1878
+ if(jdata.payload.hasOwnProperty('sid') && (jdata.payload.sid != 0 || JSON.stringify(jdata.payload).includes('tidal.com'))){
1879
+ if(JSON.stringify(jdata.payload).includes('tidal.com')) {
1880
+ jdata.payload.sid = 10;
1881
+ }
1852
1882
  this.muteRegex(JSON.stringify(jdata.payload));
1853
1883
 
1854
1884
  if (jdata.payload.hasOwnProperty('sid')) {
@@ -1926,7 +1956,7 @@ class HeosPlayer {
1926
1956
  this.heos.setState(this.state_path + 'current_image_color_background', imageColors.backgroundColor, true);
1927
1957
  this.heos.setState(this.state_path + 'current_image_color_foreground', imageColors.foregroundColor, true);
1928
1958
  } catch(colorerr){
1929
- this.logDebug('Image color extraction failed');
1959
+ this.logDebug('Image color extraction failed: ' + colorerr);
1930
1960
  this.heos.setState(this.state_path + 'current_image_color_palette', '', true);
1931
1961
  this.heos.setState(this.state_path + 'current_image_color_background', '', true);
1932
1962
  this.heos.setState(this.state_path + 'current_image_color_foreground', '', true);
@@ -1991,7 +2021,7 @@ class HeosPlayer {
1991
2021
  if(this.isPlayerGroupLeader()){
1992
2022
  await this.updateUpnp();
1993
2023
  const group_players = this.getGroupPlayers();
1994
- for (var i = 0; i < group_players.length; i++) {
2024
+ for (let i = 0; i < group_players.length; i++) {
1995
2025
  await group_players[i].updateUpnp();
1996
2026
  }
1997
2027
  }
@@ -2014,9 +2044,9 @@ class HeosPlayer {
2014
2044
  };
2015
2045
  //Load previous
2016
2046
  if (jmsg.returned < jmsg.count) {
2017
- var start = 1;
2018
- var end = 50;
2019
- var pageCmd = '';
2047
+ let start = 1;
2048
+ let end = 50;
2049
+ let pageCmd = '';
2020
2050
  if(jmsg.hasOwnProperty('range')){
2021
2051
  const range = jmsg.range.split(',');
2022
2052
  start = parseInt(range[0]) + 1;
@@ -2051,7 +2081,7 @@ class HeosPlayer {
2051
2081
  }
2052
2082
 
2053
2083
  //Queue items
2054
- for (var i = 0; i < jdata.payload.length; i++) {
2084
+ for (let i = 0; i < jdata.payload.length; i++) {
2055
2085
  const payload = jdata.payload[i];
2056
2086
  payload['name'] = '';
2057
2087
  payload['type'] = 'media';
@@ -2064,9 +2094,9 @@ class HeosPlayer {
2064
2094
 
2065
2095
  //Load next
2066
2096
  if (jmsg.returned < jmsg.count) {
2067
- var start = 1;
2068
- var end = 50;
2069
- var pageCmd = '';
2097
+ let start = 1;
2098
+ let end = 50;
2099
+ let pageCmd = '';
2070
2100
  if(jmsg.hasOwnProperty('range')){
2071
2101
  const range = jmsg.range.split(',');
2072
2102
  start = parseInt(range[0]) + 1;
@@ -2218,7 +2248,7 @@ class HeosPlayer {
2218
2248
  Target: target
2219
2249
  };
2220
2250
  try{
2221
- const result = await this.upnp.sendCommand(service, action, data);
2251
+ await this.upnp.sendCommand(service, action, data);
2222
2252
  } catch(err){
2223
2253
  this.logWarn('seek failed:' + err, false);
2224
2254
  }
@@ -2253,9 +2283,9 @@ class HeosPlayer {
2253
2283
  }
2254
2284
 
2255
2285
  /**
2256
- *
2257
- * @param {*} object
2258
- * @param {*} value
2286
+ *
2287
+ * @param {*} object
2288
+ * @param {*} value
2259
2289
  * @returns {number|string|undefined}
2260
2290
  */
2261
2291
  getKeyByValue(object, value) {
package/lib/heos-upnp.js CHANGED
@@ -6,6 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  const { URL } = require('url');
9
+ const http = require('http');
9
10
  const axios = require('axios');
10
11
  const {decode} = require('html-entities');
11
12
  const keyInObject = require('./tools').keyInObject;
@@ -27,6 +28,7 @@ class HeosUPnP {
27
28
  async init() {
28
29
  this.logSilly('[init] Get UPNP details: ' + this.url);
29
30
  const response = await axios({
31
+ httpAgent: new http.Agent({ keepAlive: false }),
30
32
  method: 'get',
31
33
  url: this.url,
32
34
  timeout: 30000
@@ -79,6 +81,7 @@ class HeosUPnP {
79
81
  if(!this.hasService(id)){
80
82
  this.logSilly('[parseServices] Get Service: ' + service.SCPDURL);
81
83
  const response = await axios({
84
+ httpAgent: new http.Agent({ keepAlive: false }),
82
85
  method: 'get',
83
86
  url: service.SCPDURL,
84
87
  timeout: 30000
@@ -191,6 +194,7 @@ class HeosUPnP {
191
194
 
192
195
  this.logSilly('[sendCommand] Send command: ' + service.controlURL);
193
196
  const response = await axios({
197
+ httpAgent: new http.Agent({ keepAlive: false }),
194
198
  method: 'post',
195
199
  url: service.controlURL,
196
200
  headers: {
package/main.js CHANGED
@@ -195,11 +195,19 @@ class Heos extends utils.Adapter {
195
195
  }
196
196
 
197
197
  logDebug(msg, force) {
198
- this.log.debug(msg);
198
+ if (!force && this.silent_log_mode) {
199
+ this.log.debug(msg);
200
+ } else {
201
+ this.log.debug(msg);
202
+ }
199
203
  }
200
204
 
201
205
  logSilly(msg, force) {
202
- this.log.silly(msg);
206
+ if (!force && this.silent_log_mode) {
207
+ this.log.silly(msg);
208
+ } else {
209
+ this.log.silly(msg);
210
+ }
203
211
  }
204
212
 
205
213
  async onReady() {
@@ -708,7 +716,8 @@ class Heos extends utils.Adapter {
708
716
  }
709
717
 
710
718
  getAllIndexes(arr, val) {
711
- let indexes = [], i;
719
+ const indexes = [];
720
+ let i;
712
721
  for (i = 0; i < arr.length; i++)
713
722
  if (arr[i] === val)
714
723
  indexes.push(i);
@@ -738,7 +747,7 @@ class Heos extends utils.Adapter {
738
747
 
739
748
  const responses = data.split(/(?={"heos")/g);
740
749
 
741
- let parseQueue = [];
750
+ const parseQueue = [];
742
751
  for (let r = 0; r < responses.length; r++) {
743
752
  if (responses[r].trim().length > 0) {
744
753
  const response = responses[r].trim();
@@ -781,7 +790,7 @@ class Heos extends utils.Adapter {
781
790
  try {
782
791
  entry = decodeURI(entry);
783
792
  } catch (e) {
784
- // ignore a malformed URI
793
+ this.logSilly('ignore a malformed URI: ' + e);
785
794
  }
786
795
  const param = entry.split('=');
787
796
  if (param.length > 1) {
@@ -1330,7 +1339,7 @@ class Heos extends utils.Adapter {
1330
1339
  if (jmsg.hasOwnProperty('level')) {
1331
1340
  const leadHeosPlayer = this.players[jmsg.gid];
1332
1341
  if (leadHeosPlayer) {
1333
- var memberPids = leadHeosPlayer.group_pid.split(',');
1342
+ const memberPids = leadHeosPlayer.group_pid.split(',');
1334
1343
  for (let i = 0; i < memberPids.length; i++) {
1335
1344
  const pid = memberPids[i];
1336
1345
  const heosPlayer = this.players[pid];
@@ -1343,7 +1352,7 @@ class Heos extends utils.Adapter {
1343
1352
  if (jmsg.hasOwnProperty('mute')) {
1344
1353
  const leadHeosPlayer = this.players[jmsg.gid];
1345
1354
  if (leadHeosPlayer) {
1346
- var memberPids = leadHeosPlayer.group_pid.split(',');
1355
+ const memberPids = leadHeosPlayer.group_pid.split(',');
1347
1356
  for (let i = 0; i < memberPids.length; i++) {
1348
1357
  const pid = memberPids[i];
1349
1358
  const heosPlayer = this.players[pid];
@@ -1384,7 +1393,7 @@ class Heos extends utils.Adapter {
1384
1393
  switch (cmd) {
1385
1394
  case 'get_music_sources':
1386
1395
  if ((jdata.hasOwnProperty('payload'))) {
1387
- var folderPath = 'sources';
1396
+ const folderPath = 'sources';
1388
1397
  //Folder
1389
1398
  await this.setObjectAsync(folderPath, {
1390
1399
  type: 'folder',
@@ -1531,9 +1540,9 @@ class Heos extends utils.Adapter {
1531
1540
 
1532
1541
  //Load previous
1533
1542
  if (jmsg.returned < jmsg.count) {
1534
- var start = 1;
1535
- var end = 50;
1536
- var pageCmd = '';
1543
+ let start = 1;
1544
+ let end = 50;
1545
+ let pageCmd = '';
1537
1546
  if (jmsg.hasOwnProperty('range')) {
1538
1547
  const range = jmsg.range.split(',');
1539
1548
  start = parseInt(range[0]) + 1;
@@ -1567,9 +1576,10 @@ class Heos extends utils.Adapter {
1567
1576
  }
1568
1577
  }
1569
1578
 
1579
+ let folderPath = '';
1570
1580
  switch (sid) {
1571
1581
  case 1025:
1572
- var folderPath = 'sources.1025';
1582
+ folderPath = 'sources.1025';
1573
1583
  //Folder
1574
1584
  const playlists = [];
1575
1585
  for (i = 0; i < jdata.payload.length; i++) {
@@ -1609,7 +1619,7 @@ class Heos extends utils.Adapter {
1609
1619
  }
1610
1620
  break;
1611
1621
  case 1028:
1612
- var folderPath = 'sources.1028';
1622
+ folderPath = 'sources.1028';
1613
1623
  //Folder
1614
1624
  const presets = [];
1615
1625
  for (i = 0; i < jdata.payload.length; i++) {
@@ -1670,9 +1680,9 @@ class Heos extends utils.Adapter {
1670
1680
 
1671
1681
  //Load next
1672
1682
  if (jmsg.returned < jmsg.count) {
1673
- var start = 1;
1674
- var end = 50;
1675
- var pageCmd = '';
1683
+ let start = 1;
1684
+ let end = 50;
1685
+ let pageCmd = '';
1676
1686
  if (jmsg.hasOwnProperty('range')) {
1677
1687
  const range = jmsg.range.split(',');
1678
1688
  start = parseInt(range[0]) + 1;
@@ -1728,7 +1738,7 @@ class Heos extends utils.Adapter {
1728
1738
  if (jmsg.hasOwnProperty('level')) {
1729
1739
  const leadHeosPlayer = this.players[jmsg.gid];
1730
1740
  if (leadHeosPlayer) {
1731
- var memberPids = leadHeosPlayer.group_pid.split(',');
1741
+ const memberPids = leadHeosPlayer.group_pid.split(',');
1732
1742
  for (let i = 0; i < memberPids.length; i++) {
1733
1743
  const pid = memberPids[i];
1734
1744
  const heosPlayer = this.players[pid];
@@ -1747,7 +1757,7 @@ class Heos extends utils.Adapter {
1747
1757
  if (jmsg.hasOwnProperty('state')) {
1748
1758
  const leadHeosPlayer = this.players[jmsg.gid];
1749
1759
  if (leadHeosPlayer) {
1750
- var memberPids = leadHeosPlayer.group_pid.split(',');
1760
+ const memberPids = leadHeosPlayer.group_pid.split(',');
1751
1761
  for (let i = 0; i < memberPids.length; i++) {
1752
1762
  const pid = memberPids[i];
1753
1763
  const heosPlayer = this.players[pid];
@@ -2000,7 +2010,7 @@ class Heos extends utils.Adapter {
2000
2010
  for (let i = 0; i < payload.length; i++) {
2001
2011
  let playerConnected = true;
2002
2012
  const player = payload[i];
2003
- var pid = player.pid + ''; //Convert to String
2013
+ const pid = player.pid + ''; //Convert to String
2004
2014
  if (player.hasOwnProperty('ip') && player.ip != '127.0.0.1') {
2005
2015
  foundPlayerIps.push(player.ip);
2006
2016
  }
@@ -2025,9 +2035,9 @@ class Heos extends utils.Adapter {
2025
2035
  if (this.preferred_player_ips.length > 0
2026
2036
  && this.preferred_player_ips.indexOf(this.ip) === -1
2027
2037
  && this.preferred_player_ips.indexOf(player.ip) !== -1) {
2028
- this.manual_search_mode = true;
2029
- this.logInfo('preferred player ' + player.ip + ' found. Reconnect.');
2030
- this.reconnect();
2038
+ this.manual_search_mode = true;
2039
+ this.logInfo('preferred player ' + player.ip + ' found. Reconnect.');
2040
+ this.reconnect();
2031
2041
  }
2032
2042
  try {
2033
2043
  await heosPlayer.connect();
@@ -2046,8 +2056,8 @@ class Heos extends utils.Adapter {
2046
2056
  }
2047
2057
  }
2048
2058
  //Remove disconnected players && Update reboot times for not connected players
2049
- let connectedPlayerIps = [];
2050
- for (var pid in this.players) {
2059
+ const connectedPlayerIps = [];
2060
+ for (const pid in this.players) {
2051
2061
  if (!connectedPlayers.includes(pid)) {
2052
2062
  await this.stopPlayer(pid);
2053
2063
  } else {
@@ -2953,13 +2963,17 @@ class Heos extends utils.Adapter {
2953
2963
  this.registerChangeEvents(false);
2954
2964
  this.net_client.destroy();
2955
2965
  this.net_client.unref();
2956
- }catch(e){}
2966
+ }catch(e){
2967
+ this.logSilly('disconnect failed: ' + e);
2968
+ }
2957
2969
  this.net_client = undefined;
2958
2970
  }
2959
2971
  if (typeof this.nodessdp_client !== 'undefined') {
2960
2972
  try {
2961
2973
  this.nodessdp_client.stop();
2962
- }catch(e){}
2974
+ }catch(e){
2975
+ this.logSilly('nodessdp client stop failed: ' + e);
2976
+ }
2963
2977
  this.nodessdp_client = undefined;
2964
2978
  }
2965
2979
  await this.setStateAsync('error', false, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.heos",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "The adapter lets control HEOS from ioBroker",
5
5
  "author": {
6
6
  "name": "withstu",
@@ -23,39 +23,39 @@
23
23
  "url": "https://github.com/withstu/ioBroker.heos"
24
24
  },
25
25
  "engines": {
26
- "node": ">= 16"
26
+ "node": ">= 18"
27
27
  },
28
28
  "dependencies": {
29
- "@iobroker/adapter-core": "^3.0.4",
30
- "fast-xml-parser": "^4.2.7",
31
- "axios": "^1.6.3",
32
- "html-entities": "^2.3.3",
29
+ "@iobroker/adapter-core": "^3.2.2",
30
+ "fast-xml-parser": "^4.5.0",
31
+ "axios": "^1.7.7",
32
+ "html-entities": "^2.5.2",
33
33
  "node-ssdp": "^4.0.1",
34
34
  "node-vibrant": "^3.1.6"
35
35
  },
36
36
  "devDependencies": {
37
- "@alcalzone/release-script": "^3.6.0",
38
- "@alcalzone/release-script-plugin-iobroker": "^3.6.0",
39
- "@alcalzone/release-script-plugin-license": "^3.5.9",
40
- "@alcalzone/release-script-plugin-manual-review": "^3.5.9",
41
- "@iobroker/adapter-dev": "^1.2.0",
42
- "@iobroker/testing": "^4.1.0",
43
- "@tsconfig/node16": "^16.1.1",
37
+ "@alcalzone/release-script": "^3.8.0",
38
+ "@alcalzone/release-script-plugin-iobroker": "^3.7.2",
39
+ "@alcalzone/release-script-plugin-license": "^3.7.0",
40
+ "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
41
+ "@iobroker/adapter-dev": "^1.3.0",
42
+ "@iobroker/testing": "^5.0.0",
43
+ "@tsconfig/node16": "^16.1.3",
44
44
  "@types/chai": "^4.3.6",
45
45
  "@types/chai-as-promised": "^7.1.8",
46
- "@types/mocha": "^10.0.1",
47
- "@types/node": "^20.8.3",
48
- "@types/proxyquire": "^1.3.28",
46
+ "@types/mocha": "^10.0.9",
47
+ "@types/node": "^22.8.4",
48
+ "@types/proxyquire": "^1.3.31",
49
49
  "@types/sinon": "^17.0.2",
50
50
  "@types/sinon-chai": "^3.2.12",
51
- "chai": "^4.3.10",
51
+ "chai": "^4.4.1",
52
52
  "chai-as-promised": "^7.1.1",
53
- "eslint": "^8.48.0",
54
- "mocha": "^10.2.0",
53
+ "eslint": "^9.13.0",
54
+ "mocha": "^10.8.2",
55
55
  "proxyquire": "^2.1.3",
56
- "sinon": "^17.0.1",
56
+ "sinon": "^19.0.2",
57
57
  "sinon-chai": "^3.7.0",
58
- "typescript": "~5.2.2"
58
+ "typescript": "~5.6.3"
59
59
  },
60
60
  "main": "main.js",
61
61
  "files": [