iobroker.zigbee 3.1.2 → 3.1.4

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/lib/commands.js CHANGED
@@ -7,10 +7,12 @@ const fs = require('fs');
7
7
  const statesMapping = require('./devices');
8
8
  const utils = require('@iobroker/adapter-core'); // Get common adapter utils
9
9
  const colors = require('./colors.js');
10
+ /* currently not needed, kept for referencce
10
11
  const dns = require('dns');
11
12
  const net = require('net');
12
- const { access, constants } =require('fs');
13
-
13
+ const access = fs.access;
14
+ const constants = fs.constants;
15
+ */
14
16
  const disallowedDashStates = [
15
17
  'link_quality', 'available', 'battery', 'groups', 'device_query',
16
18
  'hue_move', 'color_temp_move', 'satuation_move', 'brightness_move', 'brightness_step', 'hue_calibration',
@@ -82,9 +84,9 @@ class Commands {
82
84
  this.renameDevice(obj.from, obj.command, obj.message, obj.callback);
83
85
  }
84
86
  break;
85
- case 'deleteDevice':
87
+ case 'deleteZigbeeDevice':
86
88
  if (obj.message && typeof obj.message === 'object') {
87
- this.deleteDevice(obj.from, obj.command, obj.message, obj.callback);
89
+ this.deleteZigbeeDevice(obj.from, obj.command, obj.message, obj.callback);
88
90
  }
89
91
  break;
90
92
  case 'getChannels':
@@ -163,15 +165,19 @@ class Commands {
163
165
  if (this.stController) this.adapter.sendTo(obj.from, obj.command, {clean:this.stController.CleanupRequired(), errors:this.stController.getStashedErrors()}, obj.callback);
164
166
  // NO Break - returning the debug-data as well is intentional
165
167
  case 'getDebugMessages':
166
- this.adapter.sendTo(obj.from, obj.command, {byId:this.adapter.deviceDebug.collectDebugData( obj.message.inlog)},obj.callback);
168
+ this.adapter.sendTo(obj.from, obj.command, {byId:this.adapter.deviceDebug.collectDebugData( obj.message.inlog, obj.message.del )},obj.callback);
167
169
  break;
168
170
  case 'testConnection':
169
171
  this.testConnection(obj.from, obj.command, obj.message, obj.callback);
170
172
  break;
171
173
  case 'readNVRam':
172
174
  this.readNvBackup(obj.from, obj.command, obj.message, obj.callback);
175
+ break;
176
+ case 'downloadIcons':
177
+ this.triggerIconDownload(obj);
178
+ break;
173
179
  default:
174
- //this.warn(`Commands: Command ${obj.command} is unknown`);
180
+ this.debug(`Commands: Command ${obj.command} is unknown`);
175
181
  //this.adapter.sendTo(obj.from, obj.command, obj.message, obj.callback);
176
182
  break;
177
183
  }
@@ -289,6 +295,7 @@ class Commands {
289
295
 
290
296
  if (await this.zbController.permitJoin(cTimer, devId)) {
291
297
  this.adapter.setState('info.pairingMode', cTimer > 0, true);
298
+ if (devId) this.zbController.emit(`Pairing started for ${devId}`);
292
299
  this.adapter.sendTo(from, command, cTimer ? 'Start pairing!':'Stop pairing!', callback);
293
300
  }
294
301
  else {
@@ -329,196 +336,229 @@ class Commands {
329
336
  }
330
337
  }
331
338
 
332
- async getDevices(from, command, id, callback) {
333
- if (this.zbController && this.zbController.herdsmanStarted) {
334
- this.debug(`getDevices called from ${from} with command ${JSON.stringify(command)} and id ${JSON.stringify(id)}`);
335
- const pairedDevices = await this.zbController.getClients(true);
336
- const groups = {};
337
- let rooms;
338
- this.adapter.getEnumsAsync('enum.rooms')
339
- .then(enums => {
340
- // rooms
341
- rooms = enums['enum.rooms'];
342
- })
343
- // get all adapter devices
344
- .then(() => this.adapter.getDevicesAsync())
345
- .then(async result => {
346
- const alls = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
347
- const allst = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
348
- result = result.filter(item => !id || id === item._id);
349
- // get device states and groups
350
- result.forEach(async devInfo => {
351
- if (devInfo._id) {
352
- // battery and link_quality
353
- const lqState = alls[`${devInfo._id}.link_quality`];
354
- devInfo.link_quality = lqState ? lqState.val : undefined;
355
- devInfo.link_quality_lc = lqState ? lqState.lc : undefined;
356
- const batState = alls[`${devInfo._id}.battery`];
357
- devInfo.battery = batState ? batState.val : undefined;
358
- // devInfo.states = states || {};
359
-
360
- const states = allst.filter(item => item._id.startsWith(devInfo._id));
361
-
362
- // put only allowed states
363
- devInfo.statesDef = (states || []).filter(stateDef => {
364
- const sid = stateDef._id.replace(this.adapter.namespace + '.', '');
365
- const names = sid.split('.');
366
- if (stateDef.common.color || names.length > 2) return false;
367
- return !disallowedDashStates.includes(names.pop());
368
-
369
- }).map(stateDef => {
370
- const name = stateDef.common.name;
371
- const devname = devInfo.common.name;
372
- // replace state
373
- return {
374
- id: stateDef._id,
375
- name: typeof name === 'string' ? name.replace(devname, '') : name,
376
- type: stateDef.common.type,
377
- read: stateDef.common.read,
378
- write: stateDef.common.write,
379
- val: alls[stateDef._id] ? alls[stateDef._id].val : undefined,
380
- role: stateDef.common.role,
381
- unit: stateDef.common.unit,
382
- states: stateDef.common.states,
383
- };
384
- });
385
- }
386
- });
387
- return result;
388
- })
389
- .then(async result => {
390
- // combine info
391
- const devices = [];
392
- for (const devInfo of result) {
393
- if (devInfo._id.indexOf('group') > 0) {
394
- devInfo.icon = 'img/group.png';
395
- devInfo.vendor = 'ioBroker';
396
- // get group members and store them
397
- const match = /zigbee.\d.group_([0-9]+)/.exec(devInfo._id);
398
- if (match && match.length > 1) {
399
- const groupID = Number(match[1]);
400
- const groupmembers = await this.zbController.getGroupMembersFromController(groupID);
401
- this.debug(`group members for group ${groupID}: ${JSON.stringify(groupmembers)}`);
402
- if (groupmembers && groupmembers.length > 0) {
403
- const memberinfo = [];
404
- for (const member of groupmembers) {
405
- if (member && typeof member.ieee === 'string') {
406
- if (groups) {
407
- const grouparray = groups[member.ieee];
408
- if (grouparray) {
409
- if (!grouparray.includes(groupID)) {
410
- groups[member.ieee].push(groupID);
411
- }
412
- } else {
413
- groups[member.ieee] = [groupID];
414
- }
415
- }
416
- const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
417
- if (device) {
418
- member.device = device.common.name;
419
- } else {
420
- member.device = 'unknown';
421
- }
422
- memberinfo.push(member);
423
- }
424
- }
425
- devInfo.memberinfo = memberinfo;
426
- this.debug(`memberinfo for ${match[1]}: ${JSON.stringify(devInfo.memberinfo)}`);
427
- }
428
- }
429
- } else {
430
- const modelDesc = statesMapping.findModel(devInfo.common.type);
431
- devInfo.icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
432
- devInfo.vendor = modelDesc ? modelDesc.vendor : '';
433
- const legacyDesc = statesMapping.findModel(devInfo.common.type, true);
434
- devInfo.legacyIcon = (legacyDesc && legacyDesc.icon) ? legacyDesc.icon : undefined;
435
- }
436
339
 
437
- const id = getZbId(devInfo._id);
438
- devInfo.info = await this.zbController.resolveEntity(id);
439
- // check configuration
440
- try {
441
- if (devInfo.info) {
442
- const result = await this.zbController.callExtensionMethod(
443
- 'shouldConfigure',
444
- [devInfo.info.device, devInfo.info.mapped],
445
- );
446
- if (result.length > 0) devInfo.isConfigured = !result[0];
447
- }
448
- } catch (error) {
449
- this.warn('error calling shouldConfigure: ' + error && error.message ? error.message : 'no error message');
450
- }
340
+ async handleDeviceforInfo(device, states) {
341
+ }
451
342
 
452
- devInfo.rooms = [];
453
- for (const room in rooms) {
454
- if (!rooms.hasOwnProperty(room) ||
455
- !rooms[room] ||
456
- !rooms[room].common ||
457
- !rooms[room].common.members
458
- ) {
459
- continue;
460
- }
461
- if (rooms[room].common.members.includes(devInfo._id)) {
462
- devInfo.rooms.push(rooms[room].common.name);
463
- }
464
- }
465
- devInfo.paired = !!devInfo.info;
466
- devices.push(devInfo);
467
- }
468
- return devices;
469
- })
470
- .then(async (devices) => {
471
- // fill group info
472
- for (const groupdev in groups) {
473
- const device = devices.find(dev => (groupdev === getZbId(dev._id)));
343
+ async handleGroupforInfo(group, groups) {
344
+ group.icon = 'img/group.png';
345
+ group.vendor = 'ioBroker';
346
+ // get group members and store them
347
+ const match = /zigbee.\d.group_([0-9]+)/.exec(group._id);
348
+ if (match && match.length > 1) {
349
+ const groupID = Number(match[1]);
350
+ const groupmembers = await this.zbController.getGroupMembersFromController(groupID);
351
+ this.debug(`group members for group ${groupID}: ${JSON.stringify(groupmembers)}`);
352
+ if (groupmembers && groupmembers.length > 0) {
353
+ const memberinfo = [];
354
+ for (const member of groupmembers) {
355
+ if (member && typeof member.ieee === 'string') {
356
+ const memberId = member.ieee.substr(2);
357
+ const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
358
+ if (groups.hasOwnProperty(memberId)) { if (!groups[memberId].includes(groupID)) groups[memberId].push(groupID)} else groups[memberId] = [groupID]
474
359
  if (device) {
475
- device.groups = groups[groupdev];
476
- }
477
- }
478
- // append devices that paired but not created
479
- if (!id) {
480
- for (const d of pairedDevices) {
481
- const device = await this.zbController.resolveEntity(d.ieeeAddr);
482
- if (!device || !device.device) {
483
- continue;
484
- }
485
- const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
486
- if (!exists) {
487
- devices.push({
488
- _id: device.device.ieeeAddr,
489
- icon: 'img/unknown.png',
490
- paired: true,
491
- info: device,
492
- common: {
493
- name: undefined,
494
- type: undefined,
495
- },
496
- native: {}
497
- });
498
- }
360
+ member.device = device.common.name;
361
+ } else {
362
+ member.device = 'unknown';
499
363
  }
364
+ memberinfo.push(member);
500
365
  }
501
- return devices;
502
- })
503
- .then(devices => {
504
- this.debug(`getDevices contains ${devices.length} Devices`);
505
- const rv = { devices:devices, inLog:this.adapter.deviceDebug.logStatus, byId:this.adapter.deviceDebug.collectDebugData() }
506
- if (this.stController) {
507
- rv.clean = this.stController.CleanupRequired();
508
- rv.errors = this.stController.getStashedErrors();
509
- rv.debugDevices = this.stController.debugDevices;
510
- }
511
- this.adapter.sendTo(from, command, rv, callback);
366
+ }
367
+ group.memberinfo = memberinfo;
368
+ this.debug(`memberinfo for ${match[1]}: ${JSON.stringify(group.memberinfo)}`);
369
+ }
370
+ }
371
+ }
372
+
373
+ async fillInfo(device, device_stateDefs, all_states) {
374
+ device.statesDef = (device_stateDefs || []).filter(stateDef => {
375
+ const sid = stateDef._id.replace(this.adapter.namespace + '.', '');
376
+ const names = sid.split('.');
377
+ if (stateDef.common.color || names.length > 2) return false;
378
+ return !disallowedDashStates.includes(names.pop());
379
+ }).map(stateDef => {
380
+ const name = stateDef.common.name;
381
+ const devname = device.common.name;
382
+ // replace state
383
+ return {
384
+ id: stateDef._id,
385
+ name: typeof name === 'string' ? name.replace(devname, '') : name,
386
+ type: stateDef.common.type,
387
+ read: stateDef.common.read,
388
+ write: stateDef.common.write,
389
+ val: all_states[stateDef._id] ? all_states[stateDef._id].val : undefined,
390
+ role: stateDef.common.role,
391
+ unit: stateDef.common.unit,
392
+ states: stateDef.common.states,
393
+ };
394
+ });
395
+
396
+ const id = getZbId(device._id);
397
+ device.info = this.buildDeviceInfo(await this.zbController.resolveEntity(id));
398
+ // check configuration
399
+ try {
400
+ if (device.info) {
401
+ const result = await this.zbController.callExtensionMethod(
402
+ 'shouldConfigure',
403
+ [device.info.device, device.info.mapped],
404
+ );
405
+ if (result.length > 0) device.isConfigured = !result[0];
406
+ }
407
+ } catch (error) {
408
+ this.warn('error calling shouldConfigure: ' + error && error.message ? error.message : 'no error message');
409
+ }
410
+ device.paired = !!device.info;
411
+
412
+
413
+ }
414
+
415
+ buildDeviceInfo(device) {
416
+ const rv = {};
417
+ try {
418
+ rv.device = {
419
+ modelZigbee:device.device.modelID,
420
+ type:device.device.type,
421
+ ieee:device.device.ieeeAddr,
422
+ nwk:device.device.networkAddress,
423
+ manuf_id:device.device.maufacturerID,
424
+ manuf_name:device.device.manufacturerName,
425
+ manufacturer:device.mapped.vendor,
426
+ power:device.device.powerSource,
427
+ app_version:device.device.applicationVersion,
428
+ hard_version:device.device.hardwareVersion,
429
+ zcl_version:device.device.zclVersion,
430
+ stack_version:device.device.stack_version,
431
+ date_code:device.device.dateCode,
432
+ build:device.device.softwareBuildID,
433
+ interviewstate:device.device.interviewState || 'UNKNOWN',
434
+ }
435
+ rv.endpoints = [];
436
+ for (const ep_idx in device.endpoints) {
437
+ const ep = device.endpoints[ep_idx];
438
+ rv.endpoints.push({
439
+ ID:ep.ID,
440
+ profile:ep.profileID,
441
+ input_clusters:ep.inputClusters,
442
+ output_clusters:ep.outputClusters,
512
443
  })
513
- .catch(err => {
514
- this.error(`getDevices error: ${err.stack}`);
515
- this.adapter.sendTo(from, command, {error: `Error enumerating devices : ${err && err.message ? err.message : ''}`}, callback);
516
- });
517
- } else {
518
- this.adapter.sendTo(from, command, {error: 'No active connection to Zigbee Hardware!'}, callback);
444
+ }
445
+ rv.mapped = {
446
+ model:device.mapped.model,
447
+ description:device.mapped.description,
448
+ //fingerprint:JSON.stringify(device.mapped.fingerprint),
449
+ vendor:device.mapped.vendor,
450
+ hasOnEvent:device.mapped.onEvent != undefined,
451
+ hasConfigure:device.mapped.configure != undefined,
452
+ options:[],
453
+ }
454
+ if (device.mapped.options && typeof (device.mapped.options == 'object')) {
455
+ const optionDesc = [];
456
+ for (const option of device.mapped.options) {
457
+ if (option.name)
458
+ rv.mapped.options.push(option.name);
459
+ }
460
+ }
461
+ }
462
+ catch (error) {
463
+ this.warn(`Error ${error && error.message + ' ' ? error.message : ''}building device info for ${JSON.stringify(device)}`);
519
464
  }
465
+ return rv;
520
466
  }
521
467
 
468
+ async appendDevicesWithoutObjects(devices, client) {
469
+ const device = await this.zbController.resolveEntity(client.ieeeAddr);
470
+ if (!device || !device.device) {
471
+ return;
472
+ }
473
+ const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
474
+ if (!exists) {
475
+ devices.push({
476
+ _id: device.device.ieeeAddr,
477
+ icon: 'img/unknown.png',
478
+ paired: true,
479
+ info: this.buildDeviceInfo(device),
480
+ common: {
481
+ name: undefined,
482
+ type: undefined,
483
+ },
484
+ native: {}
485
+ });
486
+ }
487
+
488
+ }
489
+
490
+ async getDevices(from, command, id, callback) {
491
+ this.debug(`getDevices called from ${from} with command ${JSON.stringify(command)}${id ? ' and id '+JSON.stringify(id) : ' without ID'}`);
492
+ if (!(this.zbController && this.zbController.herdsmanStarted)) {
493
+ this.adapter.sendTo(from, command, {error: 'No active connection to Zigbee Hardware!'}, callback);
494
+ return;
495
+ }
496
+ const rooms = await this.adapter.getEnumsAsync('enum.rooms') || {};
497
+ const deviceObjects = (id ? [await this.adapter.getObjectAsync(id)] : await this.adapter.getDevicesAsync());
498
+ const all_states = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
499
+ const all_stateDefs = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
500
+ const illegalDevices = [];
501
+ const groups = {};
502
+ const PromiseChain = [];
503
+ for (const devInfo of deviceObjects) {
504
+ if (devInfo._id.indexOf('group') > -1) {
505
+ PromiseChain.push(this.handleGroupforInfo(devInfo, groups));
506
+ }
507
+ else {
508
+ const modelDesc = statesMapping.findModel(devInfo.common.type);
509
+ devInfo.icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
510
+ devInfo.vendor = modelDesc ? modelDesc.vendor : '';
511
+ const legacyDesc = statesMapping.findModel(devInfo.common.type, true);
512
+ devInfo.legacyIcon = (legacyDesc && legacyDesc.icon) ? legacyDesc.icon : undefined;
513
+ const lq_state = all_states[`${devInfo._id}.link_quality`];
514
+ devInfo.link_quality = lq_state ? lq_state.val : -1;
515
+ devInfo.link_quality_lc = lq_state ? lq_state.lc : undefined;
516
+ const battery_state = all_states[`${devInfo._id}.battery`];
517
+ devInfo.battery = battery_state ? battery_state.val : undefined;
518
+ devInfo.rooms = [];
519
+ for (const room in rooms) {
520
+ if (!rooms.hasOwnProperty(room) ||
521
+ !rooms[room] ||
522
+ !rooms[room].common ||
523
+ !rooms[room].common.members
524
+ ) {
525
+ continue;
526
+ }
527
+ if (rooms[room].common.members.includes(devInfo._id)) {
528
+ devInfo.rooms.push(rooms[room].common.name);
529
+ }
530
+ }
531
+
532
+ }
533
+ PromiseChain.push(this.fillInfo(devInfo, all_stateDefs.filter(item => item._id.startsWith(devInfo._id)),all_states));
534
+ }
535
+ if (!id) {
536
+ for (const client of this.zbController.getClientIterator(false)) {
537
+ PromiseChain.push(this.appendDevicesWithoutObjects(deviceObjects,client))
538
+ }
539
+ }
540
+
541
+ await Promise.all(PromiseChain);
542
+
543
+ for (const groupmember in groups) {
544
+ const device = deviceObjects.find(dev => (groupmember === dev.native.id));
545
+ if (device) {
546
+ device.groups = groups[groupmember];
547
+ }
548
+ }
549
+
550
+
551
+ this.debug(`getDevices contains ${deviceObjects.length} Devices`);
552
+ const rv = { devices:deviceObjects, inLog:this.adapter.deviceDebug.logStatus, }
553
+ if (!id) rv.byId = this.adapter.deviceDebug.collectDebugData();
554
+ if (this.stController) {
555
+ rv.clean = this.stController.CleanupRequired();
556
+ rv.errors = this.stController.getStashedErrors();
557
+ rv.debugDevices = this.stController.debugDevices;
558
+ }
559
+ this.adapter.sendTo(from, command, rv, callback);
560
+
561
+ }
522
562
 
523
563
  async getCoordinatorInfo(from, command, callback) {
524
564
  const coordinatorinfo = {
@@ -548,6 +588,7 @@ class Commands {
548
588
  coordinatorinfo.port = obj.native.port;
549
589
  coordinatorinfo.type = obj.native.adapterType;
550
590
  coordinatorinfo.channel = obj.native.channel;
591
+ coordinatorinfo.autostart = this.adapter.config.autostart;
551
592
  coordinatorinfo.installedVersion = obj.common.version;
552
593
  if (coordinatorVersion && coordinatorVersion.type && coordinatorVersion.meta) {
553
594
  coordinatorinfo.type = coordinatorVersion.type;
@@ -588,8 +629,8 @@ class Commands {
588
629
  }
589
630
  }
590
631
  else {
591
- coordinatorinfo.version = 'not connected';
592
- coordinatorinfo.revision = 'not connected';
632
+ coordinatorinfo.version = this.adapter.config.autostart ? 'not connected' : 'autostart not set';
633
+ coordinatorinfo.revision = this.adapter.config.autostart ? 'not connected' : 'autostart not set';
593
634
 
594
635
  }
595
636
  } catch {
@@ -611,14 +652,14 @@ class Commands {
611
652
  }
612
653
  }
613
654
 
614
- deleteDevice(from, command, msg, callback) {
655
+ deleteZigbeeDevice(from, command, msg, callback) {
615
656
  if (this.zbController && this.zbController.herdsmanStarted && this.stController) {
616
- this.debug(`deleteDevice message: ${JSON.stringify(msg)}`);
657
+ this.debug(`deleteZigbeeDevice message: ${JSON.stringify(msg)}`);
617
658
  const id = msg.id;
618
659
  const force = msg.force;
619
660
  const sysid = id.replace(this.adapter.namespace + '.', '0x');
620
661
  const devId = id.replace(this.adapter.namespace + '.', '');
621
- this.debug(`deleteDevice sysid: ${sysid}`);
662
+ this.debug(`deleteZigbeeDevice sysid: ${sysid}`);
622
663
  const dev = this.zbController.getDevice(sysid);
623
664
  if (!dev) {
624
665
  this.info(`Attempted to delete device ${devId} - the device is not known to the zigbee controller.`);
@@ -744,6 +785,28 @@ class Commands {
744
785
  if (msg.data)
745
786
  {
746
787
  for (const prop in msg.data) {
788
+ if (prop==='options') {
789
+ // we need to trigger the option change
790
+ const changed_from = entity.options;
791
+ const changed_to = msg.data.prop;
792
+ /*
793
+ const allKeys = Object.keys(changed_from);
794
+ for (const nk of Object.keys(changed_to)) {
795
+ if (allKeys.includes(nk)) continue;
796
+ allKeys.push(nk);
797
+ }
798
+ for (const key of allKeys) {
799
+ if (changed_from.hasOwnProperty(key) && changed_to.hasOwnProperty(key) && changed_from[key] == changed_to[key])
800
+ {
801
+ delete changed_from[key];
802
+ delete changed_to[key];
803
+ }
804
+ }
805
+ */
806
+ this.zbController.callExtensionMethod(
807
+ 'onZigbeeEvent',
808
+ [{'device': entity.device, 'type': 'deviceOptionsChanged', from: changed_from, to:changed_to || {}, }, entity ? entity.mapped : null]);
809
+ }
747
810
  this.debug('enumerating data: ' + prop);
748
811
  await this.stController.localConfig.updateLocalOverride(target, (entity ? entity.mapped.model : 'group'), prop, msg.data[prop], msg.global);
749
812
  }
@@ -824,65 +887,32 @@ class Commands {
824
887
  this.adapter.logToPairing(`Error: ${result.error}`)
825
888
  }
826
889
  this.adapter.sendTo(from, command, result, callback);
827
- /*
828
- this.debug(`TestConnection with ${JSON.stringify(msg)}`);
829
- if (msg && msg.address) {
830
- const netAddress = getNetAddress(msg.address);
831
- if (netAddress && netAddress.host) {
832
- this.adapter.logToPairing(`attempting dns lookup for ${netAddress.host}`);
833
- this.debug(`attempting dns lookup for ${netAddress.host}`);
834
- dns.lookup(netAddress.host, (err, ip, _) => {
835
- if (err) {
836
- const msg = `Unable to resolve name: ${err && err.message ? err.message : 'no message'}`;
837
- this.error(msg);
838
- this.adapter.logToPairing(`Error: ${msg}`);
839
- this.adapter.sendTo(from, command, {error:msg}, callback);
840
- return;
841
- }
842
- this.debug(`dns lookup for ${msg.address} produced ${ip}`);
843
- this.adapter.logToPairing(`dns lookup for ${msg.address} produced ${ip}`);
844
- const client = new net.Socket();
845
- this.debug(`attempting to connect to ${ip} port ${netAddress.port ? netAddress.port : 80}`);
846
- client.connect(netAddress.port, ip, () => {
847
- client.destroy()
848
- this.adapter.logToPairing(`connected successfully to connect to ${ip} port ${netAddress.port ? netAddress.port : 80}`);
849
- this.debug(`connected successfully to connect to ${ip} port ${netAddress.port ? netAddress.port : 80}`);
850
- this.adapter.sendTo(from, command, {}, callback)
851
- })
852
- client.on('error', (error) => {
853
- const msg = `unable to connect to ${ip} port ${netAddress.port ? netAddress.port : 80} : ${error && error.message ? error.message : 'no message given'}`
854
- this.error(msg);
855
- this.adapter.logToPairing(`Error: ${msg}`);
856
- this.adapter.sendTo(from, command, {error:msg}, callback);
857
- });
858
- })
859
- }
860
- else
861
- {
862
- try {
863
- const port = msg.address.trim();
864
- this.adapter.logToPairing(`reading access rights for ${port}`);
865
- access(port, constants.R_OK | constants.W_OK, (error) => {
866
- if (error) {
867
- const msg = `unable to access ${port} : ${error && error.message ? error.message : 'no message given'}`;
868
- this.error(msg);
869
- this.adapter.logToPairing(`Error: ${msg}`);
870
- this.adapter.sendTo(from, command, {error:msg}, callback);
871
- return;
872
- }
873
- this.adapter.logToPairing(`read and write access available for ${port}`);
874
- this.adapter.sendTo(from, command, {}, callback);
875
- });
876
- }
877
- catch (error) {
878
- const msg = `File access error: ${error && error.message ? error.message : 'no message given'}`;
879
- this.error(msg);
880
- this.adapter.logToPairing(`Error: ${msg}`);
881
- this.adapter.sendTo(from, command, {error:msg}, callback);
882
- }
890
+ }
891
+
892
+ async triggerIconDownload(obj) {
893
+ if (!this.stController) {
894
+ this.adapter.sendTo(obj.from, obj.command, {msg:'No States controller'}, obj.callback);
895
+ return;
896
+ }
897
+ const clients = await this.adapter.getDevicesAsync();
898
+ const Promises = [];
899
+ for (const client of clients) {
900
+ if (client.common.modelIcon && client.common.icon && client.common.modelIcon.startsWith('http')) {
901
+ const filestatus = await this.adapter.fileExistsAsync(this.adapter.namespace, client.common.icon);
902
+ if (!filestatus)
903
+ Promises.push(this.stController.downloadIconToAdmin(client.common.modelIcon, client.common.icon))
883
904
  }
905
+
906
+ }
907
+ const NumDownloads = Promises.length;
908
+ if (NumDownloads) {
909
+ this.adapter.sendTo(obj.from, obj.command, {msg:`${NumDownloads} downloads triggered.`}, obj.callback);
910
+ Promise.all(Promises);
884
911
  }
885
- */
912
+ else {
913
+ this.adapter.sendTo(obj.from, obj.command, {msg:'Nothing to download'}, obj.callback);
914
+ }
915
+
886
916
  }
887
917
  }
888
918
 
package/lib/developer.js CHANGED
@@ -106,7 +106,7 @@ class Developer {
106
106
  const cfg = obj.message.hasOwnProperty('cfg') ? obj.message.cfg : null;
107
107
  let publishTarget;
108
108
  try {
109
- publishTarget = this.zbController.getDevice(devId) ? devId : this.zbController.getGroup(parseInt(devId));
109
+ publishTarget = await this.zbController.getDevice(devId) ? devId : await this.zbController.getGroup(parseInt(devId));
110
110
  if (!publishTarget) {
111
111
  this.adapter.sendTo(obj.from, obj.command, {localErr: `Device or group ${devId} not found!`}, obj.callback);
112
112
  return;
package/lib/devices.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const states = require('./states.js').states;
4
4
  const utils = require('./utils.js');
5
5
  const rgb = require('./rgb.js');
6
- const {applyExposes, applyExposeForDevice} = require('./exposes.js');
6
+ const { applyExposeForDevice} = require('./exposes.js');
7
7
 
8
8
 
9
9
  // return list of changing states when incoming state is changed
@@ -3105,7 +3105,7 @@ function fillStatesWithExposes(logger) {
3105
3105
  async function addExposeToDevices(device, logger, model) {
3106
3106
  const s = DevicesByModel.size;
3107
3107
  if (s < 1) getByModel();
3108
- const rv = await applyExposeForDevice(devices, DevicesByModel, device, logger, model);
3108
+ const rv = await applyExposeForDevice(devices, DevicesByModel, device, { logger, model, newCompositeMethod:true });
3109
3109
  removeEmptyStates(devices);
3110
3110
  return rv;
3111
3111
  }
package/lib/exclude.js CHANGED
@@ -91,7 +91,7 @@ class Exclude {
91
91
 
92
92
  async addExclude(from, command, params, callback) {
93
93
  try {
94
- //this.warn('addExclude message: ' + JSON.stringify(params));
94
+ this.debug('addExclude message: ' + JSON.stringify(params));
95
95
  const exclude_mod = params.exclude_model.common.type;
96
96
  this.localConfig.updateLocalOverride(exclude_mod, exclude_mod, 'legacy', exclude_mod, true);
97
97
  callback({});