iobroker.squeezeboxrpc 1.3.14 → 1.3.16

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
@@ -201,6 +201,15 @@ For more information visit the CLI-documentation:
201
201
  Placeholder for the next version (at the beginning of the line):
202
202
  ### **WORK IN PROGRESS**
203
203
  -->
204
+ ### 1.3.16 (2024-10-23)
205
+
206
+ - fixed icons of the favorites widget
207
+
208
+ ### 1.3.15 (2024-08-09)
209
+
210
+ - due to a adapter checker issue i have to remove the release 1.3.13 from npm.
211
+ but changes from 1.3.13 are included in 1.3.14
212
+
204
213
  ### 1.3.14 (2024-08-05)
205
214
 
206
215
  - fix formatting
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "squeezeboxrpc",
4
- "version": "1.3.14",
4
+ "version": "1.3.16",
5
5
  "news": {
6
+ "1.3.16": {
7
+ "en": "fixed icons of the favorites widget",
8
+ "de": "feste symbole der favoriten widget",
9
+ "ru": "фиксированные иконы любимого виджета",
10
+ "pt": "ícones fixos do widget favorito",
11
+ "nl": "vaste pictogrammen van de favorieten widget",
12
+ "fr": "icônes fixes du widget favori",
13
+ "it": "icone fisse del widget preferiti",
14
+ "es": "iconos fijos de los favoritos widget",
15
+ "pl": "stałe ikony ulubionego widgetu",
16
+ "uk": "фіксовані ікони улюбленого віджету",
17
+ "zh-cn": "最爱部件的固定图标"
18
+ },
19
+ "1.3.15": {
20
+ "en": "- due to a adapter checker issue i have to remove the release 1.3.13 from npm.\n but changes from 1.3.13 are included in 1.3.14",
21
+ "de": "- wegen eines adapter-checker-problems muss ich das release 1.3.13 von npm entfernen.\nänderungen von 1.3.13 sind in 1.3.14 enthalten",
22
+ "ru": "- из-за проблемы с адаптером, я должен удалить выпуск 1.3.13 из npm.\nно изменения от 1.3.13 включены в подраздел 1.3.14",
23
+ "pt": "- devido a um problema do verificador do adaptador eu tenho que remover a liberação 1.3.13 da npm.\nmas as alterações de 1.3.13 estão incluídas em 1.3.14",
24
+ "nl": "- vanwege een probleem met de adaptercontrole moet ik de release 1.3.13 van npm verwijderen.\nmaar wijzigingen van 1.3.13 zijn opgenomen in 1.3.14",
25
+ "fr": "- en raison d'un problème d'adaptateur, je dois supprimer la version 1.3.13 de npm.\nmais les changements par rapport au 1.3.13 sont inclus dans le 1.3.14",
26
+ "it": "- a causa di un problema dell'adattatore checker devo rimuovere il rilascio 1.3.13 da npm.\nma le modifiche da 1.3.13 sono incluse in 1.3.14",
27
+ "es": "- debido a un problema de control de adaptador tengo que eliminar la liberación 1.3.13 de npm.\npero los cambios de 1.3.13 se incluyen en 1.3.14",
28
+ "pl": "- ze względu na problem sprawdzania adaptera muszę usunąć zwolnienie 1.3.13 z npm.\nale zmiany z 1.3.13 są zawarte w 1.3.14",
29
+ "uk": "- через проблему перевірки адаптера я повинен видалити реліз 1.3.13 з npm.\nале зміни від 1.3.13 включені в 1.3.14",
30
+ "zh-cn": "- 因为适配器检查器的问题,我不得不从npm中移除1.3.13的发布.\n但从1.3.13到1.3.14的变动已包括在内"
31
+ },
6
32
  "1.3.14": {
7
33
  "en": "fix formatting",
8
34
  "de": "fixe formatierung",
@@ -16,19 +42,6 @@
16
42
  "uk": "фіксувати форматування",
17
43
  "zh-cn": "固定格式化"
18
44
  },
19
- "1.3.13": {
20
- "en": "revert the fix for artist handling due to negative effect of spotify",
21
- "de": "die fix für die künstlerhandhabung aufgrund negativer wirkung von spotify",
22
- "ru": "возвратить фиксацию для работы с художником из-за негативного эффекта спотификации",
23
- "pt": "reverter a correção para manipulação de artista devido ao efeito negativo de identificar",
24
- "nl": "terugzetten van de fix voor artist handling als gevolg van negatief effect van spotify",
25
- "fr": "retourner la correction pour la manipulation de l'artiste en raison de l'effet négatif de spotify",
26
- "it": "ripristinare la correzione per la gestione dell'artista a causa dell'effetto negativo di spotify",
27
- "es": "revertir la fijación para el manejo del artista debido al efecto negativo de spotify",
28
- "pl": "revert fix do obsługi artysty ze względu na negatywny efekt spotify",
29
- "uk": "перевернути фіксацію для обробки художника через негативний ефект плямистості",
30
- "zh-cn": "恢复对艺术家处理的固定,因为发现有负面影响"
31
- },
32
45
  "1.3.12": {
33
46
  "en": "improve cmdGoto handling by kairauer, close PR #74\nfix issues from adapter checker\nintegrate squeezenode lib",
34
47
  "de": "verbessern cmd Goto Handling von kairauer, close PR #74\nprobleme von adapter checker beheben\npressnode lib integrieren",
@@ -80,19 +93,6 @@
80
93
  "pl": "* napraw błąd przy usuwaniu ulubionych * napraw błędny typ punktu danych",
81
94
  "uk": "* виправити помилку з видаленням вибраного * виправити неправильний тип точки даних",
82
95
  "zh-cn": "* 修复删除收藏夹时的错误 * 修复数据点的错误类型"
83
- },
84
- "1.3.8": {
85
- "en": "* fix object forward btn widget",
86
- "de": "* Objekt-Weiterleitungs-BTN-Widget korrigiert",
87
- "ru": "* исправлен виджет кнопки вперед объекта",
88
- "pt": "* corrigir widget de btn de encaminhamento de objeto",
89
- "nl": "* fix object voorwaartse btn-widget",
90
- "fr": "* Correction du widget btn de transfert d'objet",
91
- "it": "* corretto il widget oggetto forward btn",
92
- "es": "* arreglar el widget btn de reenvío de objetos",
93
- "pl": "* napraw widget btn do przesyłania obiektów",
94
- "uk": "* виправити віджет btn для пересилання об’єктів",
95
- "zh-cn": "* 修复对象转发 btn 小部件"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/lib/iosbplayer.js CHANGED
@@ -499,9 +499,11 @@ function ioSBPlayer(server, playerdata) {
499
499
 
500
500
  }
501
501
  };
502
- this.init = function (playerdata) {
502
+ this.init = async function (playerdata) {
503
503
  this.doPlayerStatus(playerdata);
504
504
  this.logdebug("New Player found: " + this.playername + " with id " + this.playerid);
505
+ await this.createFolder(this.statePath);
506
+ await this.createDevice(this.playername, this.statePath);
505
507
  const delay = this.playerindex || 0;
506
508
  setTimeout(this.doObserverPlayer.bind(this), delay * 190);
507
509
  };
@@ -821,7 +823,7 @@ function ioSBPlayer(server, playerdata) {
821
823
  };
822
824
  this.createState = function (stateTemplate, level1path = false, level2path = false) {
823
825
  const name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + stateTemplate.name;
824
- this.logsilly("Create Key " + name);
826
+ this.logsilly("Create state " + name);
825
827
  if (!this.currentStates[name]) this.adapter.createState(level1path, level2path, stateTemplate.name, stateTemplate);
826
828
  stateTemplate.exist = true;
827
829
  return stateTemplate;
@@ -860,6 +862,52 @@ function ioSBPlayer(server, playerdata) {
860
862
  this.adapter.setState(name, value, true);
861
863
  }
862
864
  };
865
+ this.createFolder = async function (foldername, level1path, level2path) {
866
+ const id = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + foldername;
867
+ this.logsilly("createFolder " + id);
868
+ if (await this.existsObjectAsync(id)) {
869
+ this.logsilly("Folder exists: " + id);
870
+ } else {
871
+ const obj = {
872
+ type: "folder",
873
+ common: {
874
+ name: foldername
875
+ },
876
+ native: {}
877
+ };
878
+ this.adapter.setObject(id, obj);
879
+ }
880
+ };
881
+ this.createDevice = async function (devicename, level1path, level2path) {
882
+ const id = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + devicename;
883
+ this.logsilly("createDevice " + id);
884
+ if (await this.existsObjectAsync(id)) {
885
+ this.logsilly("Device exists: " + id);
886
+ } else {
887
+ const obj = {
888
+ type: "device",
889
+ common: {
890
+ name: devicename
891
+ },
892
+ native: {}
893
+ };
894
+ this.adapter.setObject(id, obj);
895
+ }
896
+ };
897
+ this.existsObjectAsync = function (id) {
898
+ return new Promise((resolve, reject) => {
899
+ id = this.adapter.namespace + "." + id;
900
+
901
+ this.adapter.getForeignObject(id, (err, obj) => {
902
+ if (err) {
903
+ reject(err);
904
+ } else {
905
+ resolve(!!obj);
906
+ }
907
+
908
+ });
909
+ });
910
+ };
863
911
  this.convertState = function (stateTemplate, value) {
864
912
  if (stateTemplate.type == "string") return String(value);
865
913
  if (stateTemplate.type == "number") return Number(value);
package/lib/iosbserver.js CHANGED
@@ -1,207 +1,206 @@
1
- /* eslint-disable quotes */
2
- 'use strict';
1
+ "use strict";
3
2
 
4
3
  //const utils = require('@iobroker/adapter-core');
5
- const dgram = require('dgram');
6
- const SqueezeServerNew = require(__dirname + '/squeezenode/squeezeserver');
7
- const ioSBPlayer = require(__dirname + '/iosbplayer');
4
+ const dgram = require("dgram");
5
+ const SqueezeServerNew = require(__dirname + "/squeezenode/squeezeserver");
6
+ const ioSBPlayer = require(__dirname + "/iosbplayer");
8
7
 
9
8
  function IoSbServer(adapter) {
10
9
 
11
10
 
12
11
  this.sbServerStatus = {
13
- 'lastscan': {
14
- name: 'LastScan',
12
+ "lastscan": {
13
+ name: "LastScan",
15
14
  read: true,
16
15
  write: false,
17
- type: 'string',
18
- role: 'value',
16
+ type: "string",
17
+ role: "value",
19
18
  exist: false
20
19
  },
21
- 'version': {
22
- name: 'Version',
20
+ "version": {
21
+ name: "Version",
23
22
  read: true,
24
23
  write: false,
25
- type: 'string',
26
- role: 'value',
24
+ type: "string",
25
+ role: "value",
27
26
  exist: false
28
27
  },
29
- 'uuid': {
30
- name: 'uuid',
28
+ "uuid": {
29
+ name: "uuid",
31
30
  read: true,
32
31
  write: false,
33
- type: 'string',
34
- role: 'value',
32
+ type: "string",
33
+ role: "value",
35
34
  exist: false
36
35
  },
37
- 'name': {
38
- name: 'Name',
36
+ "name": {
37
+ name: "Name",
39
38
  read: true,
40
39
  write: false,
41
- type: 'string',
42
- role: 'value',
40
+ type: "string",
41
+ role: "value",
43
42
  exist: false
44
43
  },
45
- 'mac': {
46
- name: 'mac',
44
+ "mac": {
45
+ name: "mac",
47
46
  read: true,
48
47
  write: false,
49
- type: 'string',
50
- role: 'info.mac',
48
+ type: "string",
49
+ role: "info.mac",
51
50
  exist: false
52
51
  },
53
- 'info total albums': {
54
- name: 'TotalAlbums',
52
+ "info total albums": {
53
+ name: "TotalAlbums",
55
54
  read: true,
56
55
  write: false,
57
- type: 'number',
58
- role: 'value',
56
+ type: "number",
57
+ role: "value",
59
58
  exist: false
60
59
  },
61
- 'info total artists': {
62
- name: 'TotalArtists',
60
+ "info total artists": {
61
+ name: "TotalArtists",
63
62
  read: true,
64
63
  write: false,
65
- type: 'number',
66
- role: 'value',
64
+ type: "number",
65
+ role: "value",
67
66
  exist: false
68
67
  },
69
- 'info total genres': {
70
- name: 'TotalGenres',
68
+ "info total genres": {
69
+ name: "TotalGenres",
71
70
  read: true,
72
71
  write: false,
73
- type: 'number',
74
- role: 'value',
72
+ type: "number",
73
+ role: "value",
75
74
  exist: false
76
75
  },
77
- 'info total songs': {
78
- name: 'TotalSongs',
76
+ "info total songs": {
77
+ name: "TotalSongs",
79
78
  read: true,
80
79
  write: false,
81
- type: 'number',
82
- role: 'value',
80
+ type: "number",
81
+ role: "value",
83
82
  exist: false
84
83
  },
85
- 'info total duration': {
86
- name: 'TotalDuration',
84
+ "info total duration": {
85
+ name: "TotalDuration",
87
86
  read: true,
88
87
  write: false,
89
- type: 'number',
90
- role: 'media.duration',
88
+ type: "number",
89
+ role: "media.duration",
91
90
  exist: false
92
91
  },
93
- 'player count': {
94
- name: 'PlayerCount',
92
+ "player count": {
93
+ name: "PlayerCount",
95
94
  read: true,
96
95
  write: false,
97
- type: 'number',
98
- role: 'value',
96
+ type: "number",
97
+ role: "value",
99
98
  exist: false
100
99
  },
101
- 'sn player count': {
102
- name: 'PlayerCountSN',
100
+ "sn player count": {
101
+ name: "PlayerCountSN",
103
102
  read: true,
104
103
  write: false,
105
- type: 'number',
106
- role: 'value',
104
+ type: "number",
105
+ role: "value",
107
106
  exist: false
108
107
  },
109
- 'other player count': {
110
- name: 'PlayerCountOther',
108
+ "other player count": {
109
+ name: "PlayerCountOther",
111
110
  read: true,
112
111
  write: false,
113
- type: 'number',
114
- role: 'value',
112
+ type: "number",
113
+ role: "value",
115
114
  exist: false
116
115
  },
117
- 'syncgroups': {
118
- name: 'SyncGroups',
116
+ "syncgroups": {
117
+ name: "SyncGroups",
119
118
  read: true,
120
119
  write: false,
121
- type: 'string',
122
- role: 'value',
120
+ type: "string",
121
+ role: "value",
123
122
  exist: false
124
123
  },
125
- 'otherServers': {
126
- name: 'otherServers',
124
+ "otherServers": {
125
+ name: "otherServers",
127
126
  read: true,
128
127
  write: true,
129
- type: 'string',
130
- role: 'value',
128
+ type: "string",
129
+ role: "value",
131
130
  exist: false
132
131
  },
133
- 'getFavorites': {
134
- name: 'getFavorites',
132
+ "getFavorites": {
133
+ name: "getFavorites",
135
134
  read: true,
136
135
  write: true,
137
- type: 'boolean',
138
- role: 'button',
136
+ type: "boolean",
137
+ role: "button",
139
138
  def: false,
140
139
  exist: false
141
140
  }
142
141
  };
143
142
  this.sbFavoritesState = {
144
- 'name': {
145
- name: 'Name',
143
+ "name": {
144
+ name: "Name",
146
145
  read: true,
147
146
  write: false,
148
- type: 'string',
149
- role: 'value',
147
+ type: "string",
148
+ role: "value",
150
149
  exist: false
151
150
  },
152
- 'type': {
153
- name: 'type',
151
+ "type": {
152
+ name: "type",
154
153
  read: true,
155
154
  write: false,
156
- type: 'string',
157
- role: 'value',
155
+ type: "string",
156
+ role: "value",
158
157
  exist: false
159
158
  },
160
- 'id': {
161
- name: 'id',
159
+ "id": {
160
+ name: "id",
162
161
  read: true,
163
162
  write: false,
164
- type: 'string',
165
- role: 'value',
163
+ type: "string",
164
+ role: "value",
166
165
  exist: false
167
166
  },
168
- 'hasitems': {
169
- name: 'hasitems',
167
+ "hasitems": {
168
+ name: "hasitems",
170
169
  read: true,
171
170
  write: false,
172
- type: 'number',
173
- role: 'value',
171
+ type: "number",
172
+ role: "value",
174
173
  exist: false
175
174
  },
176
- 'url': {
177
- name: 'url',
175
+ "url": {
176
+ name: "url",
178
177
  read: true,
179
178
  write: false,
180
- type: 'string',
181
- role: 'media.url',
179
+ type: "string",
180
+ role: "media.url",
182
181
  exist: false
183
182
  },
184
- 'image': {
185
- name: 'image',
183
+ "image": {
184
+ name: "image",
186
185
  read: true,
187
186
  write: false,
188
- type: 'string',
189
- role: 'url.icon',
187
+ type: "string",
188
+ role: "url.icon",
190
189
  exist: false
191
190
  },
192
- 'isaudio': {
193
- name: 'isaudio',
191
+ "isaudio": {
192
+ name: "isaudio",
194
193
  read: true,
195
194
  write: false,
196
- type: 'number',
197
- role: 'value',
195
+ type: "number",
196
+ role: "value",
198
197
  exist: false
199
198
  }
200
199
  };
201
200
 
202
- this.ServerStatePath = 'Server';
203
- this.FavoritesStatePath = 'Favorites';
204
- this.PlayersStatePath = 'Players';
201
+ this.ServerStatePath = "Server";
202
+ this.FavoritesStatePath = "Favorites";
203
+ this.PlayersStatePath = "Players";
205
204
 
206
205
  this.currentStates = {};
207
206
  this.players = [];
@@ -209,10 +208,10 @@ function IoSbServer(adapter) {
209
208
 
210
209
  this.adapter = adapter;
211
210
 
212
- this.adapter.setState('info.connection', false, true);
213
- this.adapter.subscribeStates('*');
211
+ this.adapter.setState("info.connection", false, true);
212
+ this.adapter.subscribeStates("*");
214
213
 
215
- this.sbServer = (adapter.config.username != "") ? new SqueezeServerNew('http://' + this.adapter.config.server, Number.parseInt(this.adapter.config.port), adapter.config.username, adapter.config.password) : new SqueezeServerNew('http://' + this.adapter.config.server, Number.parseInt(this.adapter.config.port));
214
+ this.sbServer = (adapter.config.username != "") ? new SqueezeServerNew("http://" + this.adapter.config.server, Number.parseInt(this.adapter.config.port), adapter.config.username, adapter.config.password) : new SqueezeServerNew("http://" + this.adapter.config.server, Number.parseInt(this.adapter.config.port));
216
215
 
217
216
  this.log = {};
218
217
  this.islogsilly = this.adapter.config.outputserversilly;
@@ -225,16 +224,17 @@ function IoSbServer(adapter) {
225
224
  this.telnet = null;
226
225
  this.otherserver = [];
227
226
 
228
- this.init = function () {
229
- this.setState('connection', true, 'info');
227
+ this.init = async function () {
228
+ this.logdebug("server init");
229
+ this.setState("connection", true, "info");
230
230
  this.doObserverServer();
231
231
  this.doObserverFavorites();
232
232
  this.doTelnet();
233
233
  };
234
234
  this.doObserverServer = function () {
235
- this.logsilly('doObserverServer');
235
+ this.logdebug("doObserverServer");
236
236
  this.getServerstatus();
237
- this.setTimeout('serverstatus', this.doObserverServer.bind(this), this.adapter.config.serverrefresh * 1000);
237
+ this.setTimeout("serverstatus", this.doObserverServer.bind(this), this.adapter.config.serverrefresh * 1000);
238
238
  };
239
239
  this.processMessages = function (msg) {
240
240
  this.logdebug("processMessages " + JSON.stringify(msg));
@@ -249,7 +249,7 @@ function IoSbServer(adapter) {
249
249
  for (const [, srv] of Object.entries(this.otherserver)) {
250
250
  data.push({ label: `${srv.NAME}/${srv.ADDRESS}`, value: srv.ADDRESS });
251
251
  }
252
- this.adapter.sendTo(msg.from, msg.command, [{ value: '', label: '---' }, ...data], msg.callback);
252
+ this.adapter.sendTo(msg.from, msg.command, [{ value: "", label: "---" }, ...data], msg.callback);
253
253
  };
254
254
  this.setTimeout = function (id, callback, time) {
255
255
  this.clearTimeout(id);
@@ -268,32 +268,31 @@ function IoSbServer(adapter) {
268
268
  delete this.observers[id];
269
269
  };
270
270
  this.doObserverFavorites = function () {
271
- this.logsilly('doObserverFavorites');
272
-
273
- if (!this.adapter.config.usefavorites) {
274
- this.newdelFavorites();
271
+ this.logdebug("doObserverFavorites");
272
+ this.delFavorites();
273
+ if (this.adapter.config.usefavorites) {
274
+ this.setFavorites();
275
275
  return;
276
276
  }
277
- this.newgetFavorites();
278
- this.setTimeout('favorites', this.doObserverFavorites.bind(this), this.adapter.config.favoriterefresh * 60 * 1000);
277
+ this.setTimeout("favorites", this.doObserverFavorites.bind(this), this.adapter.config.favoriterefresh * 60 * 1000);
279
278
  };
280
279
  this.getDiscoverServers = () => {
281
- this.logsilly('getDiscoverServers');
280
+ this.logdebug("getDiscoverServers");
282
281
  const that = this;
283
282
  if (!this.adapter.config.usediscovery) {
284
- this.delState(this.ServerStatePath, this.sbServerStatus['otherServers'].name, function () {
285
- that.delObject(that.ServerStatePath, that.sbServerStatus['otherServers'].name);
283
+ this.delState(this.ServerStatePath, this.sbServerStatus["otherServers"].name, function () {
284
+ that.delObject(that.ServerStatePath, that.sbServerStatus["otherServers"].name);
286
285
  });
287
286
  return;
288
287
  }
289
- this.server = dgram.createSocket({ type: 'udp4', reuseAddr: true });
288
+ this.server = dgram.createSocket({ type: "udp4", reuseAddr: true });
290
289
  const broadcastPort = 3483;
291
- this.server.bind(broadcastPort, '0.0.0.0', function () {
290
+ this.server.bind(broadcastPort, "0.0.0.0", function () {
292
291
  that.server && that.server.setBroadcast(true);
293
292
  }.bind(this));
294
- this.server.on('message', function (data, rinfo) {
295
- that.logsilly('getDiscoverServers: Message resceived ' + escape(data));
296
- if (data.toString().charAt() == 'E') {
293
+ this.server.on("message", async function (data, rinfo) {
294
+ that.logsilly("getDiscoverServers: Message resceived " + escape(data));
295
+ if (data.toString().charAt() == "E") {
297
296
  let msg = data.toString();
298
297
  msg = msg.substr(1);
299
298
  const srv = {};
@@ -307,23 +306,24 @@ function IoSbServer(adapter) {
307
306
  len = len - len2 - 5;
308
307
  srv[tag] = val;
309
308
  }
310
- srv['ADDRESS'] = rinfo.address;
311
- srv['TIMESTAMP'] = Date.now();
312
- that.otherserver[srv['ADDRESS']] = srv;
309
+ srv["ADDRESS"] = rinfo.address;
310
+ srv["TIMESTAMP"] = Date.now();
311
+ that.otherserver[srv["ADDRESS"]] = srv;
313
312
  const state = {};
314
- Object.assign(state, that.sbServerStatus['otherServers']);
315
- state.name = srv['ADDRESS'].replace(/\./g, '-');
313
+ Object.assign(state, that.sbServerStatus["otherServers"]);
314
+ state.name = srv["ADDRESS"].replace(/\./g, "-");
316
315
  state.def = JSON.stringify(srv);
317
- that.createObject(state, that.ServerStatePath, that.sbServerStatus['otherServers'].name, function () {
318
- that.setState(srv['ADDRESS'].replace(/\./g, '-'), JSON.stringify(srv), that.ServerStatePath, that.sbServerStatus['otherServers'].name, false);
316
+ await that.createFolder(that.sbServerStatus["otherServers"].name, that.ServerStatePath);
317
+ that.createObject(state, that.ServerStatePath, that.sbServerStatus["otherServers"].name, function () {
318
+ that.setState(srv["ADDRESS"].replace(/\./g, "-"), JSON.stringify(srv), that.ServerStatePath, that.sbServerStatus["otherServers"].name, false);
319
319
  });
320
- that.logdebug('Autodiscover: Server found ' + srv['NAME'] + ' IP: ' + srv['ADDRESS'] + ' Port ' + srv['JSON'] + ' UUID ' + srv['UUID']);
320
+ that.logdebug("Autodiscover: Server found " + srv["NAME"] + " IP: " + srv["ADDRESS"] + " Port " + srv["JSON"] + " UUID " + srv["UUID"]);
321
321
  }
322
322
  }.bind(this));
323
- this.server.on('error', function (err) {
324
- that.log.error("Error with Server discovery " + err.message);
323
+ this.server.on("error", function (err) {
324
+ that.logerror("Error with Server discovery " + err.message);
325
325
  if (err.message.includes("EADDRINUSE")) {
326
- that.log.info("use 'lsof -i -P' to check for ports used.");
326
+ that.loginfo("use 'lsof -i -P' to check for ports used.");
327
327
  }
328
328
  try {
329
329
  that.server && that.server.close(function () {
@@ -331,23 +331,23 @@ function IoSbServer(adapter) {
331
331
  that.server = null;
332
332
  });
333
333
  } catch (err) {
334
- that.log.error("server.close() " + err.message);
334
+ that.logerror("server.close() " + err.message);
335
335
  }
336
336
  });
337
337
  setTimeout(this.doDiscoverServerSearch, 1000);
338
338
  };
339
339
  this.doDiscoverServerSearch = () => {
340
- this.logsilly('doDiscoverServerSearch');
340
+ this.logdebug("doDiscoverServerSearch");
341
341
  const that = this;
342
- const msg = Buffer.from('eIPAD\0NAME\0JSON\0UUID\0VERS');
343
- const broadcastAddress = '255.255.255.255';
342
+ const msg = Buffer.from("eIPAD\0NAME\0JSON\0UUID\0VERS");
343
+ const broadcastAddress = "255.255.255.255";
344
344
  const broadcastPort = 3483;
345
- this.getStates('*', this.ServerStatePath, this.sbServerStatus['otherServers'].name, function (err, states) {
345
+ this.getStates("*", this.ServerStatePath, this.sbServerStatus["otherServers"].name, function (err, states) {
346
346
  for (const id in states) {
347
- const srv = JSON.parse(states[id].val);
347
+ const srv = JSON.parse(states[id]?.val || "{}");
348
348
  if (((Date.now() - srv.TIMESTAMP) / 1000) > 60) {
349
349
  that.delObject(id);
350
- that.logdebug('Autodiscover: Server removed ' + srv['NAME'] + ' IP: ' + srv['ADDRESS'] + ' Port ' + srv['JSON'] + ' UUID ' + srv['UUID']);
350
+ that.logdebug("Autodiscover: Server removed " + srv["NAME"] + " IP: " + srv["ADDRESS"] + " Port " + srv["JSON"] + " UUID " + srv["UUID"]);
351
351
  }
352
352
  }
353
353
  }.bind(this));
@@ -361,81 +361,84 @@ function IoSbServer(adapter) {
361
361
  if (err) that.log.error(err);
362
362
  }
363
363
  );
364
- this.setTimeout('discover', this.doDiscoverServerSearch.bind(this), this.adapter.config.discoveryrefresh * 1000);
364
+ this.setTimeout("discover", this.doDiscoverServerSearch.bind(this), this.adapter.config.discoveryrefresh * 1000);
365
365
  };
366
366
  this.doDiscoverServerClose = function () {
367
- this.logdebug('doDiscoverServerClose');
367
+ this.logdebug("doDiscoverServerClose");
368
368
  this.server && this.server.close();
369
369
  };
370
370
  this.doTelnet = () => {
371
+ this.logdebug("doTelnet");
371
372
  if (!this.adapter.config.usetelnet) return;
372
- const net = require('net');
373
+ const net = require("net");
373
374
  this.telnet = net.createConnection({ host: this.adapter.config.server, port: this.adapter.config.telnetport }, () => {
374
- this.logdebug('doTelnet connected to server!');
375
- this.telnet.write('login ' + this.adapter.config.username + ' ' + this.adapter.config.password + '\r\n');
376
- this.telnet.write('listen 1\r\n');
375
+ this.logdebug("doTelnet connected to server!");
376
+ this.telnet.write("login " + this.adapter.config.username + " " + this.adapter.config.password + "\r\n");
377
+ this.telnet.write("listen 1\r\n");
377
378
  });
378
- this.telnet.on('data', (data) => {
379
- this.logdebug('doTelnet received Data: ' + data.toString());
379
+ this.telnet.on("data", (data) => {
380
+ this.logdebug("doTelnet received Data: " + data.toString());
380
381
  const regex = /^((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2}))\s*(.*)/gm;
381
382
  let m;
382
383
  if ((m = regex.exec(decodeURIComponent(data.toString()))) !== null) {
383
- if (m[2] == 'client reconnect') {
384
- this.logdebug('doTelnet received reconnect for : ' + m[1]);
384
+ if (m[2] == "client reconnect") {
385
+ this.logdebug("doTelnet received reconnect for : " + m[1]);
385
386
  this.getServerstatus();
386
387
  }
387
- if (m[2] == 'client disconnect') {
388
- this.logdebug('doTelnet received disconnect for : ' + m[1]);
388
+ if (m[2] == "client disconnect") {
389
+ this.logdebug("doTelnet received disconnect for : " + m[1]);
389
390
  this.getServerstatus();
390
391
  }
391
- if (m[2] == 'client new') {
392
- this.logdebug('doTelnet received disconnect for : ' + m[1]);
392
+ if (m[2] == "client new") {
393
+ this.logdebug("doTelnet received disconnect for : " + m[1]);
393
394
  this.getServerstatus();
394
395
  }
395
- if (m[2] == 'power 0') {
396
- this.logdebug('doTelnet received power off : ' + m[1]);
396
+ if (m[2] == "power 0") {
397
+ this.logdebug("doTelnet received power off : " + m[1]);
397
398
  this.getServerstatus();
398
399
  }
399
- if (m[2] == 'power 1') {
400
- this.logdebug('doTelnet received power on : ' + m[1]);
400
+ if (m[2] == "power 1") {
401
+ this.logdebug("doTelnet received power on : " + m[1]);
401
402
  this.getServerstatus();
402
403
  }
403
404
  }
404
405
  });
405
- this.telnet.on('end', () => {
406
- this.logdebug('doTelnet disconnected from server');
406
+ this.telnet.on("end", () => {
407
+ this.logdebug("doTelnet disconnected from server");
407
408
  });
408
- this.telnet.on('timeout', () => {
409
- this.logdebug('doTelnet Socket timeout, closing');
409
+ this.telnet.on("timeout", () => {
410
+ this.logdebug("doTelnet Socket timeout, closing");
410
411
  this.telnet.close();
411
412
  });
412
- this.telnet.on('error', (err) => {
413
- this.logdebug('doTelnet Socket error: ' + err.message);
413
+ this.telnet.on("error", (err) => {
414
+ this.logdebug("doTelnet Socket error: " + err.message);
414
415
  });
415
- this.telnet.on('close', (err) => {
416
- this.logdebug('doTelnet Socket closed ' + err.message);
416
+ this.telnet.on("close", (err) => {
417
+ this.logdebug("doTelnet Socket closed " + err.message);
417
418
  });
418
419
  };
419
420
  this.doTelnetClose = function () {
420
- this.logdebug('doTelnetClose');
421
+ this.logdebug("doTelnetClose");
421
422
  this.telnet.end();
422
423
  };
423
424
  this.closeConnections = function () {
425
+ this.logdebug("closeConnections");
424
426
  if (this.adapter.config.usetelnet) this.doTelnetClose();
425
427
  if (this.adapter.config.usediscovery) this.doDiscoverServerClose();
426
428
  };
427
429
  this.getServerstatus = function () {
428
- this.logsilly('getServerstatus');
429
- this.request('', ['serverstatus', '0', '888'], this.doServerstatus.bind(this));
430
- this.request('', ['syncgroups', '?'], this.doSyncgroups.bind(this));
430
+ this.logdebug("getServerstatus");
431
+ this.request("", ["serverstatus", "0", "888"], this.doServerstatus.bind(this));
432
+ this.request("", ["syncgroups", "?"], this.doSyncgroups.bind(this));
431
433
  };
432
434
  this.doSyncgroups = function (result) {
435
+ this.logdebug("doSyncgroups");
433
436
  if (result.result && result.result.syncgroups_loop) {
434
- this.setState(this.sbServerStatus['syncgroups'].name, JSON.stringify(result.result.syncgroups_loop), this.ServerStatePath);
437
+ this.setState(this.sbServerStatus["syncgroups"].name, JSON.stringify(result.result.syncgroups_loop), this.ServerStatePath);
435
438
  }
436
439
  };
437
440
  this.doServerstatus = function (result) {
438
- this.logsilly('doServerstatus');
441
+ this.logdebug("doServerstatus");
439
442
  this.checkServerstatusStates(result);
440
443
  for (const key in this.sbServerStatus) {
441
444
  if (Object.prototype.hasOwnProperty.call(result.result, key)) {
@@ -445,162 +448,83 @@ function IoSbServer(adapter) {
445
448
  this.checkNewPlayer(result.result.players_loop);
446
449
  this.checkPlayer(result.result.players_loop);
447
450
  };
448
- this.newgetFavorites = function () {
449
- this.logsilly('newgetFavorites');
450
- this.newgetFavoritesDP(
451
- (states) => this.newdelFavoritesDP(states,
452
- () => this.newgetFavoritesLMS('',
453
- (result) => this.newsetFavoritesDP(result)
454
- )
455
- )
456
- );
457
- };
458
- this.newdelFavorites = function () {
459
- this.logsilly('newgetFavorites');
460
- this.newgetFavoritesDP(
461
- (states) => this.newdelFavoritesDP(states)
451
+ this.setFavorites = async function () {
452
+ this.logdebug("setFavorites");
453
+ this.getFavoritesLMS("",
454
+ (result) => this.setFavoritesDP(result)
462
455
  );
463
456
  };
464
- this.newgetFavoritesDP = function (callback) {
465
- this.logsilly('newgetFavoritesDPs');
466
-
467
- const id = this.FavoritesStatePath;
468
- this.adapter.getStates(id + '*', (err, states) => {
469
- if (!err) {
470
- callback(states);
471
- } else this.log.info(err);
472
- });
457
+ this.delFavorites = async function () {
458
+ this.logdebug("delFavorites");
459
+ let favobj = await this.getObjects(this.FavoritesStatePath);
460
+ favobj = favobj.rows.filter(obj => obj.value.type === "folder");
461
+ for (let i = 0; i < favobj.length; i++) {
462
+ await this.adapter.delForeignObjectAsync(favobj[i].id);
463
+ }
473
464
  };
474
- this.newgetFavoritesLMS = function (id = '', callback) {
475
- this.logsilly('newgetFavoritesLMS');
476
- this.request('', ['favorites', 'items', '0', '888', 'want_url:1', 'item_id:' + id],
465
+ this.getFavoritesLMS = function (id = "", callback) {
466
+ this.logdebug("getFavoritesLMS");
467
+ this.request("", ["favorites", "items", "0", "888", "want_url:1", "item_id:" + id],
477
468
  (result) => callback(result.result.loop_loop)//.bind(this);
478
469
  );
479
470
  };
480
- this.newdelFavoritesDP = (states, callback) => {
481
- const that = this;
482
- this.logsilly('newdelFavoritesDP');
483
- const promises = [];
484
- for (const id in states) {
485
- this.logdebug(`Start to delete object => ${id}`);
486
- promises.push(new Promise(function (resolve) {
487
- that.delObject(id, false, false, resolve);
488
- }.bind(this)));
489
- }
490
- Promise.all(promises).then(function () {
491
- that.logdebug(`All favorite objects deleted`);
492
- if (callback) callback();
493
- }.bind(this));
494
- };
495
- this.newsetFavoritesDP = function (favorites) {
496
- this.logsilly('newsetFavoritesDP');
471
+ this.setFavoritesDP = async function (favorites) {
472
+ this.logdebug("setFavoritesDP");
473
+ await this.createFolder(this.FavoritesStatePath);
497
474
  for (const favkey in favorites) {
498
475
  const favorite = favorites[favkey];
499
- const oid = this.getFavId(favorite['id'], false);
500
- const id = this.getFavId(favorite['id']);
476
+ const oid = this.getFavId(favorite["id"], false);
477
+ const id = this.getFavId(favorite["id"]);
501
478
  for (const key in this.sbFavoritesState) {
502
479
  if (Object.prototype.hasOwnProperty.call(favorite, key)) {
503
- if (key == 'id') favorite['id'] = oid;
504
- if (key == 'image') {
505
- const regex = /imageproxy\/(.*)\/[^/]/gm;
506
- const m = regex.exec(favorite[key]);
507
- if (m && m.index > 0) {
508
- favorite[key] = decodeURIComponent(m[1]);
480
+ if (key == "id") favorite["id"] = oid;
481
+ if (key == "image") {
482
+ let result = "http://" + this.adapter.config.server + ":" + this.adapter.config.port + "/html/images/favorites.png";
483
+ if (/music\/(.*)\/cover.png/gm.test(favorite[key])) {
484
+ result = "http://" + this.adapter.config.server + ":" + this.adapter.config.port + "/" + favorite[key];
485
+ }
486
+ else if (/imageproxy\/(.*)\/[^/]/gm.test(favorite[key])) {
487
+ const m = /imageproxy\/(.*)\/[^/]/gm.exec(favorite[key]);
488
+ if (m && m[1]) {
489
+ result = decodeURIComponent(m[1] || "");
490
+ }
509
491
  }
492
+ else if (favorite[key] === "html/images/radio.png") {
493
+ result = "http://" + this.adapter.config.server + ":" + this.adapter.config.port + "/html/images/radio.png";
494
+ }
495
+ else if (favorite[key] === "html/images/cover.png") {
496
+ result = "http://" + this.adapter.config.server + ":" + this.adapter.config.port + "/html/images/cover.png";
497
+ }
498
+ else if (favorite[key] === "html/images/favorites.png") {
499
+ result = "http://" + this.adapter.config.server + ":" + this.adapter.config.port + "/html/images/favorites.png";
500
+ }
501
+ favorite[key] = result;
510
502
  }
511
503
  const stateTemplate = this.sbFavoritesState[key];
504
+ await this.createFolder(id, this.FavoritesStatePath);
512
505
  this.createObject(stateTemplate, this.FavoritesStatePath, id,
513
506
  () => this.setState(this.sbFavoritesState[key].name, this.convertState(this.sbFavoritesState[key], favorite[key]), this.FavoritesStatePath, id, false)
514
507
  );
515
508
  }
516
509
  }
517
- if (favorite['hasitems'] > 0) this.newgetFavoritesLMS(oid,
518
- (result) => this.newsetFavoritesDP(result)
510
+ if (favorite["hasitems"] > 0) this.getFavoritesLMS(oid,
511
+ (result) => this.setFavoritesDP(result)
519
512
  );
520
513
  }
521
514
  };
522
- /*
523
- this.getFavorites = function(id='') {
524
- this.logsilly('getFavorites');
525
- this.deleteFavorites(id,function() {
526
- this.request('',['favorites', 'items', '0', '888','want_url:1','item_id:' + id], this.doFavorites1.bind(this));
527
- }.bind(this));
528
- };
529
- this.doFavorites1 = function(result){
530
- this.logsilly('doFavorites1');
531
- const favorites = result.result.loop_loop;
532
- this.checkFavoriteStates(favorites);
533
- };
534
- this.doFavorites2 = function(favorites){
535
- this.logsilly('doFavorites2');
536
- for (const favkey in favorites) {
537
- const favorite = favorites[favkey];
538
- const oid = this.getFavId(favorite['id'],false);
539
- const id = this.getFavId(favorite['id']);
540
- for (const key in this.sbFavoritesState){
541
- if (favorite.hasOwnProperty(key)) {
542
- if (key=='id') favorite['id'] = oid;
543
- if (key == 'image' ) {
544
- const regex = /imageproxy\/(.*)\/[^\/]/gm;
545
- let m = regex.exec(favorite[key]);
546
- if (m && m.index>0) {
547
- favorite[key] = decodeURIComponent(m[1]);
548
- }
549
- }
550
- this.setState(this.sbFavoritesState[key].name,favorite[key],this.FavoritesStatePath,id,false);
551
- }
552
- }
553
- if (favorite['hasitems']>0) this.getFavorites(oid);
554
- }
555
- };
556
- this.checkFavoriteStates = function(favorites) {
557
- this.logsilly('checkFavoriteStates');
558
- for (const favkey in favorites) {
559
- const favorite = favorites[favkey];
560
- const id = this.getFavId(favorite['id']);
561
- for (const key in this.sbFavoritesState){
562
- if (favorite.hasOwnProperty(key)) {
563
- const stateTemplate = this.sbFavoritesState[key];
564
- this.createObject(stateTemplate,this.FavoritesStatePath,id);
565
- }
566
- }
567
- }
568
- this.doFavorites2(favorites);
569
- };
570
- this.deleteFavorites = function(typ,callback) {
571
- if (typ!='') {
572
- callback();
573
- return;
574
- }
575
- var id = this.FavoritesStatePath;
576
- this.adapter.getStates(id + '*', (err, states) => {
577
- if(!err) {
578
- let promises = [];
579
- for (const id in states) {
580
- this.logdebug(`Delete state => ${id}`);
581
- promises.push( new Promise(function(resolve){
582
- this.delObject(id,false,false,resolve);
583
- }.bind(this)));
584
- }
585
- Promise.all(promises).then(function(){
586
- callback();
587
- });
588
- } else this.log.info(err);
589
- });
590
- };
591
- */
592
515
  this.getFavId = function (id, replace = true) {
593
516
  let ret;
594
- if (id.indexOf('.') == 8) {
517
+ if (id.indexOf(".") == 8) {
595
518
  ret = id.substr(9);
596
519
  } else {
597
520
  ret = id;
598
521
  }
599
- if (replace) ret = ret.replace(/\./g, '-');
522
+ if (replace) ret = ret.replace(/\./g, "-");
600
523
  return ret;
601
524
  };
602
- this.checkServerstatusStates = function (result) {
603
- this.logsilly('checkServerstatusStates');
525
+ this.checkServerstatusStates = async function (result) {
526
+ this.logdebug("checkServerstatusStates");
527
+ await this.createDevice(this.ServerStatePath);
604
528
  for (const key in this.sbServerStatus) {
605
529
  if (Object.prototype.hasOwnProperty.call(result.result, key)) {
606
530
  const stateTemplate = this.sbServerStatus[key];
@@ -611,18 +535,19 @@ function IoSbServer(adapter) {
611
535
  }
612
536
  }
613
537
  }
614
- let key = 'getFavorites';
538
+ let key = "getFavorites";
615
539
  let stateTemplate = this.sbServerStatus[key];
616
540
  if (!stateTemplate.exist) {
617
541
  this.sbServerStatus[key] = this.createObject(stateTemplate, this.ServerStatePath);
618
542
  }
619
- key = 'syncgroups';
543
+ key = "syncgroups";
620
544
  stateTemplate = this.sbServerStatus[key];
621
545
  if (!stateTemplate.exist) {
622
546
  this.sbServerStatus[key] = this.createObject(stateTemplate, this.ServerStatePath);
623
547
  }
624
548
  };
625
549
  this.checkNewPlayer = function (playersdata) {
550
+ this.logdebug("checkNewPlayer");
626
551
  for (const key in playersdata) {
627
552
  if (!Object.prototype.hasOwnProperty.call(this.players, playersdata[key].playerid)) {
628
553
  this.players[playersdata[key].playerid] = new ioSBPlayer(this, playersdata[key]);
@@ -630,6 +555,7 @@ function IoSbServer(adapter) {
630
555
  }
631
556
  };
632
557
  this.checkPlayer = function (playersdata) {
558
+ this.logdebug("checkPlayer");
633
559
  for (const key in playersdata) {
634
560
  if (this.players[playersdata[key].playerid].connected != playersdata[key].connected) {
635
561
  if (playersdata[key].connected == 0) {
@@ -642,11 +568,12 @@ function IoSbServer(adapter) {
642
568
  }
643
569
  };
644
570
  this.stateChange = function (id, state) {
571
+ this.logsilly("stateChange");
645
572
  // Warning, state can be null if it was deleted
646
573
  if (!id || !state || state.ack) {
647
574
  return;
648
575
  }
649
- const idParts = id.split('.');
576
+ const idParts = id.split(".");
650
577
  idParts.shift();
651
578
  idParts.shift();
652
579
  if (idParts[0] == this.ServerStatePath) this.doServerStateChange(idParts, state);
@@ -654,16 +581,22 @@ function IoSbServer(adapter) {
654
581
  if (idParts[0] == this.PlayersStatePath) this.doPlayersStateChange(idParts, state);
655
582
  };
656
583
  this.doServerStateChange = function (idParts, state) {
584
+ this.logdebug("doServerStateChange");
657
585
  idParts.shift();
658
- if (idParts[0] == 'getFavorites') {
659
- if (state.val == true) this.newgetFavorites();
586
+ if (idParts[0] == "getFavorites") {
587
+ if (state.val == true) {
588
+ this.delFavorites();
589
+ this.setFavorites();
590
+ }
660
591
  }
661
592
  };
662
593
  this.doFavoritesStateChange = function (idParts, state) {
594
+ this.logdebug("doFavoritesStateChange");
663
595
  idParts.shift();
664
596
  if (state) return;
665
597
  };
666
598
  this.doPlayersStateChange = function (idParts, state) {
599
+ this.logsilly("doPlayersStateChange");
667
600
  idParts.shift();
668
601
  const player = this.findPlayerByName(idParts[0]);
669
602
  if (player) player.doStateChange(idParts, state);
@@ -674,6 +607,7 @@ function IoSbServer(adapter) {
674
607
  }
675
608
  };
676
609
  this.request = function (playerid, params, callback) {
610
+ this.logsilly("request");
677
611
  const that = this;
678
612
  this.sbServer.request(playerid, params, function (callback, result) {
679
613
  if (result.ok) {
@@ -693,70 +627,80 @@ function IoSbServer(adapter) {
693
627
  }.bind(this, callback));
694
628
  };
695
629
  this.disconnect = () => {
696
- this.logdebug('Server disconnect');
630
+ this.logdebug("Server disconnect");
697
631
  this.firstStart = false;
698
632
  this.connected = 0;
699
- this.clearTimeout('serverstatus');
700
- this.clearTimeout('favorites');
701
- if (this.connected == 0 && this.observers['checkserver']) return;
702
- this.setState('connection', false, 'info');
633
+ this.clearTimeout("serverstatus");
634
+ this.clearTimeout("favorites");
635
+ if (this.connected == 0 && this.observers["checkserver"]) return;
636
+ this.setState("connection", false, "info");
703
637
  for (const key in this.players) {
704
638
  this.players[key].disconnect();
705
639
  }
706
- this.setInterval('checkserver', this.doCheckServer.bind(this), 10 * 1000);
640
+ this.setInterval("checkserver", this.doCheckServer.bind(this), 10 * 1000);
707
641
  };
708
642
  this.connect = () => {
709
- this.logdebug('Server connect');
710
- this.clearInterval('checkserver');
711
- this.setState('connection', true, 'info');
643
+ this.logdebug("Server connect");
644
+ this.clearInterval("checkserver");
645
+ this.setState("connection", true, "info");
712
646
  this.connected = 1;
713
647
  this.init();
714
648
  };
715
649
  this.doCheckServer = () => {
716
650
  const that = this;
717
- this.logsilly('doCheckServer');
718
- this.request('', ['serverstatus', '0', '888'], function (result) {
651
+ this.logdebug("doCheckServer");
652
+ this.request("", ["serverstatus", "0", "888"], function (result) {
719
653
  if (result.ok) {
720
654
  that.connect();
721
655
  }
722
656
  }.bind(this));
723
657
  };
724
658
  this.setState = function (name, value, level1path, level2path, check = true, callback) {
725
- name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + name;
659
+ name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + name;
726
660
  if (this.currentStates[name] !== value && check) {
727
661
  this.currentStates[name] = value;
728
- this.logsilly('setState name: ' + name + ' value: ' + value);
662
+ this.logsilly("setState name: " + name + " value: " + value);
729
663
  this.adapter.setState(name, value, true, callback);
730
664
  } else {
731
665
  this.currentStates[name] = value;
732
- this.logsilly('setState name: ' + name + ' value: ' + value);
666
+ this.logsilly("setState name: " + name + " value: " + value);
733
667
  this.adapter.setState(name, value, true, callback);
734
668
  }
735
669
  };
736
670
  this.getState = function (name, level1path = false, level2path = false, callback) {
737
- name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + name;
671
+ name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + name;
672
+ this.logsilly("getState " + name);
738
673
  this.adapter.getState(name, callback);
739
674
  };
740
675
  this.delObject = function (name, level1path, level2path, callback) {
741
- name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + name;
676
+ name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + name;
677
+ this.logsilly("delObject " + name);
742
678
  delete this.currentStates[name];
743
679
  this.adapter.delObject(name, callback);
744
680
  };
745
681
  this.delState = function (name, level1path, level2path, callback) {
746
- name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + name;
682
+ name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + name;
683
+ this.logsilly("delObject " + name);
747
684
  delete this.currentStates[name];
748
685
  this.adapter.delState(name, callback);
749
686
  };
750
687
  this.getStates = function (pattern, level1path, level2path, callback) {
751
- const name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + pattern;
688
+ const name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + pattern;
752
689
  this.adapter.getStates(name, callback);
753
690
  };
691
+ this.getObjects = async function (level1path, level2path) {
692
+ const name = this.adapter.namespace + "." + (level1path ? level1path + "." : "") + (level2path ? level2path : "");
693
+ return await this.adapter.getObjectListAsync({
694
+ startkey: name,
695
+ endkey: name + "\u9999"
696
+ });
697
+ };
754
698
  this.createObject = function (stateTemplate, level1path, level2path, callback) {
755
- const name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + stateTemplate.name;
756
- this.logdebug('createObject ' + name);
699
+ const name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + stateTemplate.name;
700
+ this.logsilly("createObject " + name);
757
701
  this.adapter.getObject(name, (err, obj) => {
758
702
  const newobj = {
759
- type: 'state',
703
+ type: "state",
760
704
  common: stateTemplate,
761
705
  native: {}
762
706
  };
@@ -770,16 +714,62 @@ function IoSbServer(adapter) {
770
714
  return stateTemplate;
771
715
  };
772
716
  this.createState = function (stateTemplate, level1path = false, level2path = false, callback) {
773
- const name = (level1path ? level1path + '.' : '') + (level2path ? level2path + '.' : '') + stateTemplate.name;
774
- this.logsilly('Create Key ' + name);
717
+ const name = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + stateTemplate.name;
718
+ this.logsilly("Create state " + name);
775
719
  this.adapter.createState(level1path, level2path, stateTemplate.name, stateTemplate, callback);
776
720
  stateTemplate.exist = true;
777
721
  return stateTemplate;
778
722
  };
723
+ this.createFolder = async function (foldername, level1path, level2path) {
724
+ const id = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + foldername;
725
+ this.logsilly("createFolder " + id);
726
+ if (await this.existsObjectAsync(id)) {
727
+ this.logsilly("Folder exists: " + id);
728
+ } else {
729
+ const obj = {
730
+ type: "folder",
731
+ common: {
732
+ name: foldername
733
+ },
734
+ native: {}
735
+ };
736
+ this.adapter.setObject(id, obj);
737
+ }
738
+ };
739
+ this.createDevice = async function (devicename, level1path, level2path) {
740
+ const id = (level1path ? level1path + "." : "") + (level2path ? level2path + "." : "") + devicename;
741
+ this.logsilly("createDevice " + id);
742
+ if (await this.existsObjectAsync(id)) {
743
+ this.logsilly("Device exists: " + id);
744
+ } else {
745
+ const obj = {
746
+ type: "device",
747
+ common: {
748
+ name: devicename
749
+ },
750
+ native: {}
751
+ };
752
+ this.adapter.setObject(id, obj);
753
+ }
754
+ };
755
+ this.existsObjectAsync = function (id) {
756
+ return new Promise((resolve, reject) => {
757
+ id = this.adapter.namespace + "." + id;
758
+
759
+ this.adapter.getForeignObject(id, (err, obj) => {
760
+ if (err) {
761
+ reject(err);
762
+ } else {
763
+ resolve(!!obj);
764
+ }
765
+
766
+ });
767
+ });
768
+ };
779
769
  this.convertState = function (stateTemplate, value) {
780
770
  if (stateTemplate.type == "string") return String(value);
781
771
  if (stateTemplate.type == "number") return Number(value);
782
- this.logdebug('Missing conversion function for type ' + stateTemplate.type + ' Please report.');
772
+ this.logdebug("Missing conversion function for type " + stateTemplate.type + " Please report.");
783
773
  return value;
784
774
  };
785
775
  this.logsilly = (s) => {
@@ -796,6 +786,6 @@ function IoSbServer(adapter) {
796
786
  this.adapter.log.info(s);
797
787
  };
798
788
  this.getDiscoverServers();
799
- this.sbServer.on('register', this.init.bind(this));
789
+ this.sbServer.on("register", this.init.bind(this));
800
790
  }
801
791
  module.exports = IoSbServer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.squeezeboxrpc",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "ioBroker Logitech Squeezebox Adapter over JSON/RPC-Protocol",
5
5
  "author": {
6
6
  "name": "oweitman",
@@ -51,7 +51,7 @@
51
51
  "eslint": "^8.57.0",
52
52
  "eslint-config-prettier": "^9.1.0",
53
53
  "eslint-plugin-prettier": "^5.2.1",
54
- "mocha": "^10.5.2",
54
+ "mocha": "^10.7.3",
55
55
  "prettier": "^3.3.3",
56
56
  "proxyquire": "^2.1.3",
57
57
  "sinon": "^18.0.0",