matterbridge 1.6.6-dev.1 → 1.6.6-dev.13

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.
@@ -26,6 +26,7 @@ export class MatterbridgeEndpoint extends Endpoint {
26
26
  static logLevel = "info";
27
27
  log;
28
28
  plugin = undefined;
29
+ configUrl = undefined;
29
30
  deviceName = undefined;
30
31
  serialNumber = undefined;
31
32
  uniqueId = undefined;
@@ -41,6 +42,7 @@ export class MatterbridgeEndpoint extends Endpoint {
41
42
  deviceType;
42
43
  uniqueStorageKey = undefined;
43
44
  tagList = undefined;
45
+ subType = '';
44
46
  deviceTypes = new Map();
45
47
  clusterServers = new Map();
46
48
  clusterClients = new Map();
@@ -115,7 +117,7 @@ export class MatterbridgeEndpoint extends Endpoint {
115
117
  });
116
118
  return behaviorTypes;
117
119
  }
118
- static getBehaviourTypeFromClusterServerId(clusterId, type) {
120
+ static getBehaviourTypeFromClusterServerId(clusterId, subType) {
119
121
  if (clusterId === Identify.Cluster.id)
120
122
  return MatterbridgeIdentifyServer;
121
123
  if (clusterId === Groups.Cluster.id)
@@ -123,30 +125,36 @@ export class MatterbridgeEndpoint extends Endpoint {
123
125
  if (clusterId === OnOff.Cluster.id)
124
126
  return MatterbridgeOnOffServer.with('Lighting');
125
127
  if (clusterId === LevelControl.Cluster.id)
126
- return MatterbridgeLevelControlServer;
127
- if (clusterId === ColorControl.Cluster.id && type === 'CompleteColorControl')
128
+ return MatterbridgeLevelControlServer.with('OnOff', 'Lighting');
129
+ if (clusterId === ColorControl.Cluster.id && subType === undefined)
128
130
  return MatterbridgeColorControlServer;
129
- if (clusterId === ColorControl.Cluster.id && type === 'XyColorControl')
131
+ if (clusterId === ColorControl.Cluster.id && subType === 'CompleteColorControl')
132
+ return MatterbridgeColorControlServer;
133
+ if (clusterId === ColorControl.Cluster.id && subType === 'XyColorControl')
130
134
  return MatterbridgeColorControlServer.with('Xy');
131
- if (clusterId === ColorControl.Cluster.id && type === 'HueSaturationColorControl')
135
+ if (clusterId === ColorControl.Cluster.id && subType === 'HueSaturationColorControl')
132
136
  return MatterbridgeColorControlServer.with('HueSaturation');
133
- if (clusterId === ColorControl.Cluster.id && type === 'ColorTemperatureColorControl')
137
+ if (clusterId === ColorControl.Cluster.id && subType === 'ColorTemperatureColorControl')
134
138
  return MatterbridgeColorControlServer.with('ColorTemperature');
135
139
  if (clusterId === DoorLock.Cluster.id)
136
140
  return MatterbridgeDoorLockServer;
137
- if (clusterId === Thermostat.Cluster.id && type === 'AutoModeThermostat')
141
+ if (clusterId === Thermostat.Cluster.id && subType === undefined)
142
+ return MatterbridgeThermostatServer.with('AutoMode', 'Heating', 'Cooling');
143
+ if (clusterId === Thermostat.Cluster.id && subType === 'AutoModeThermostat')
138
144
  return MatterbridgeThermostatServer.with('AutoMode', 'Heating', 'Cooling');
139
- if (clusterId === Thermostat.Cluster.id && type === 'HeatingThermostat')
145
+ if (clusterId === Thermostat.Cluster.id && subType === 'HeatingThermostat')
140
146
  return MatterbridgeThermostatServer.with('Heating');
141
- if (clusterId === Thermostat.Cluster.id && type === 'CoolingThermostat')
147
+ if (clusterId === Thermostat.Cluster.id && subType === 'CoolingThermostat')
142
148
  return MatterbridgeThermostatServer.with('Cooling');
143
149
  if (clusterId === WindowCovering.Cluster.id)
144
150
  return MatterbridgeWindowCoveringServer;
145
151
  if (clusterId === FanControl.Cluster.id)
146
152
  return MatterbridgeFanControlServer;
147
- if (clusterId === Switch.Cluster.id && type === 'MomentarySwitch')
153
+ if (clusterId === Switch.Cluster.id && subType === undefined)
154
+ return SwitchServer.with('MomentarySwitch', 'MomentarySwitchRelease', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress');
155
+ if (clusterId === Switch.Cluster.id && subType === 'MomentarySwitch')
148
156
  return SwitchServer.with('MomentarySwitch', 'MomentarySwitchRelease', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress');
149
- if (clusterId === Switch.Cluster.id && type === 'LatchingSwitch')
157
+ if (clusterId === Switch.Cluster.id && subType === 'LatchingSwitch')
150
158
  return SwitchServer.with('LatchingSwitch');
151
159
  if (clusterId === TemperatureMeasurement.Cluster.id)
152
160
  return TemperatureMeasurementServer;
@@ -200,11 +208,13 @@ export class MatterbridgeEndpoint extends Endpoint {
200
208
  return ElectricalPowerMeasurementServer.with('AlternatingCurrent');
201
209
  if (clusterId === ElectricalEnergyMeasurement.Cluster.id)
202
210
  return ElectricalEnergyMeasurementServer.with('ImportedEnergy', 'ExportedEnergy', 'CumulativeEnergy');
203
- if (clusterId === PowerSource.Cluster.id && type === 'WiredPowerSource')
211
+ if (clusterId === PowerSource.Cluster.id && subType === undefined)
212
+ return PowerSourceServer;
213
+ if (clusterId === PowerSource.Cluster.id && subType === 'WiredPowerSource')
204
214
  return PowerSourceServer.with(PowerSource.Feature.Wired);
205
- if (clusterId === PowerSource.Cluster.id && type === 'BatteryReplaceablePowerSource')
215
+ if (clusterId === PowerSource.Cluster.id && subType === 'BatteryReplaceablePowerSource')
206
216
  return PowerSourceServer.with(PowerSource.Feature.Battery, PowerSource.Feature.Replaceable);
207
- if (clusterId === PowerSource.Cluster.id && type === 'BatteryRechargeablePowerSource')
217
+ if (clusterId === PowerSource.Cluster.id && subType === 'BatteryRechargeablePowerSource')
208
218
  return PowerSourceServer.with(PowerSource.Feature.Battery, PowerSource.Feature.Rechargeable);
209
219
  if (clusterId === BasicInformation.Cluster.id)
210
220
  return BasicInformationServer;
@@ -410,40 +420,32 @@ export class MatterbridgeEndpoint extends Endpoint {
410
420
  if (this.clusterServers.has(cluster.id)) {
411
421
  this.log.debug(`****cluster ${hk}${'0x' + cluster.id.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(cluster.id)}${db} already added`);
412
422
  }
413
- let type = undefined;
423
+ this.subType = '';
414
424
  if (cluster.id === ColorControl.Cluster.id && cluster.isAttributeSupportedByName('currentX') && !cluster.isAttributeSupportedByName('currentHue') && !cluster.isAttributeSupportedByName('colorTemperatureMireds'))
415
- type = 'XyColorControl';
425
+ this.subType = 'XyColorControl';
416
426
  else if (cluster.id === ColorControl.Cluster.id && cluster.isAttributeSupportedByName('currentHue') && !cluster.isAttributeSupportedByName('currentX') && !cluster.isAttributeSupportedByName('colorTemperatureMireds'))
417
- type = 'HueSaturationColorControl';
427
+ this.subType = 'HueSaturationColorControl';
418
428
  else if (cluster.id === ColorControl.Cluster.id && cluster.isAttributeSupportedByName('colorTemperatureMireds') && !cluster.isAttributeSupportedByName('currentHue') && !cluster.isAttributeSupportedByName('currentX'))
419
- type = 'ColorTemperatureColorControl';
429
+ this.subType = 'ColorTemperatureColorControl';
420
430
  else
421
- type = 'CompleteColorControl';
431
+ this.subType = 'CompleteColorControl';
422
432
  if (cluster.id === SwitchCluster.id && cluster.isEventSupportedByName('multiPressComplete'))
423
- type = 'MomentarySwitch';
433
+ this.subType = 'MomentarySwitch';
424
434
  if (cluster.id === SwitchCluster.id && cluster.isEventSupportedByName('switchLatched'))
425
- type = 'LatchingSwitch';
435
+ this.subType = 'LatchingSwitch';
426
436
  if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('wiredCurrentType'))
427
- type = 'WiredPowerSource';
437
+ this.subType = 'WiredPowerSource';
428
438
  if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('batReplacementDescription'))
429
- type = 'BatteryReplaceablePowerSource';
439
+ this.subType = 'BatteryReplaceablePowerSource';
430
440
  if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('batChargeState'))
431
- type = 'BatteryRechargeablePowerSource';
441
+ this.subType = 'BatteryRechargeablePowerSource';
432
442
  if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('occupiedCoolingSetpoint'))
433
- type = 'CoolingThermostat';
443
+ this.subType = 'CoolingThermostat';
434
444
  if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('occupiedHeatingSetpoint'))
435
- type = 'HeatingThermostat';
445
+ this.subType = 'HeatingThermostat';
436
446
  if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('minSetpointDeadBand'))
437
- type = 'AutoModeThermostat';
438
- const behavior = MatterbridgeEndpoint.getBehaviourTypeFromClusterServerId(cluster.id, type);
439
- if (cluster.id === PowerTopologyCluster.id && this.clusterServers.has(cluster.id))
440
- return;
441
- if (cluster.id === ElectricalPowerMeasurementCluster.id && this.clusterServers.has(cluster.id))
442
- return;
443
- if (cluster.id === ElectricalEnergyMeasurementCluster.id && this.clusterServers.has(cluster.id))
444
- return;
445
- if (cluster.id === ThermostatCluster.id && this.clusterServers.has(cluster.id))
446
- return;
447
+ this.subType = 'AutoModeThermostat';
448
+ const behavior = MatterbridgeEndpoint.getBehaviourTypeFromClusterServerId(cluster.id, this.subType);
447
449
  this.clusterServers.set(cluster.id, cluster);
448
450
  if (cluster.id === BasicInformationCluster.id)
449
451
  return;
@@ -707,6 +709,7 @@ export class MatterbridgeEndpoint extends Endpoint {
707
709
  vendorName: vendorName.slice(0, 32),
708
710
  productId: productId,
709
711
  productName: productName.slice(0, 32),
712
+ productUrl: 'https://www.npmjs.com/package/matterbridge',
710
713
  productLabel: deviceName.slice(0, 64),
711
714
  nodeLabel: deviceName.slice(0, 32),
712
715
  serialNumber: serialNumber.slice(0, 32),
@@ -751,6 +754,7 @@ export class MatterbridgeEndpoint extends Endpoint {
751
754
  vendorId: vendorId !== undefined ? VendorId(vendorId) : undefined,
752
755
  vendorName: vendorName.slice(0, 32),
753
756
  productName: productName.slice(0, 32),
757
+ productUrl: 'https://www.npmjs.com/package/matterbridge',
754
758
  productLabel: deviceName.slice(0, 64),
755
759
  nodeLabel: deviceName.slice(0, 32),
756
760
  serialNumber: serialNumber.slice(0, 32),
@@ -854,47 +858,39 @@ export class MatterbridgeEndpoint extends Endpoint {
854
858
  createDefaultOnOffClusterServer(onOff = false, globalSceneControl = false, onTime = 0, offWaitTime = 0, startUpOnOff = null) {
855
859
  this.addClusterServer(this.getDefaultOnOffClusterServer(onOff, globalSceneControl, onTime, offWaitTime, startUpOnOff));
856
860
  }
857
- getDefaultLevelControlClusterServer(currentLevel = 254, minLevel = 0, maxLevel = 254, onLevel = 254) {
858
- return ClusterServer(LevelControlCluster.with(LevelControl.Feature.OnOff), {
861
+ getDefaultLevelControlClusterServer(currentLevel = 254, minLevel = 1, maxLevel = 254, onLevel = null, startUpCurrentLevel = null) {
862
+ return ClusterServer(LevelControlCluster.with(LevelControl.Feature.OnOff, LevelControl.Feature.Lighting), {
859
863
  currentLevel,
860
864
  minLevel,
861
865
  maxLevel,
862
866
  onLevel,
867
+ remainingTime: 0,
868
+ startUpCurrentLevel,
863
869
  options: {
864
870
  executeIfOff: false,
865
871
  coupleColorTempToLevel: false,
866
872
  },
867
873
  }, {
868
874
  moveToLevel: async (data) => {
869
- this.log.debug('Matter command: moveToLevel request:', data.request, 'attributes.currentLevel:', data.attributes.currentLevel.getLocal());
870
- await this.commandHandler.executeHandler('moveToLevel', data);
871
875
  },
872
876
  move: async () => {
873
- this.log.error('Matter command: move not implemented');
874
877
  },
875
878
  step: async () => {
876
- this.log.error('Matter command: step not implemented');
877
879
  },
878
880
  stop: async () => {
879
- this.log.error('Matter command: stop not implemented');
880
881
  },
881
882
  moveToLevelWithOnOff: async (data) => {
882
- this.log.debug('Matter command: moveToLevelWithOnOff request:', data.request, 'attributes.currentLevel:', data.attributes.currentLevel.getLocal());
883
- await this.commandHandler.executeHandler('moveToLevelWithOnOff', data);
884
883
  },
885
884
  moveWithOnOff: async () => {
886
- this.log.error('Matter command: moveWithOnOff not implemented');
887
885
  },
888
886
  stepWithOnOff: async () => {
889
- this.log.error('Matter command: stepWithOnOff not implemented');
890
887
  },
891
888
  stopWithOnOff: async () => {
892
- this.log.error('Matter command: stopWithOnOff not implemented');
893
889
  },
894
890
  });
895
891
  }
896
- createDefaultLevelControlClusterServer(currentLevel = 254, minLevel = 0, maxLevel = 254, onLevel = 254) {
897
- this.addClusterServer(this.getDefaultLevelControlClusterServer(currentLevel, minLevel, maxLevel, onLevel));
892
+ createDefaultLevelControlClusterServer(currentLevel = 254, minLevel = 1, maxLevel = 254, onLevel = null, startUpCurrentLevel = null) {
893
+ this.addClusterServer(this.getDefaultLevelControlClusterServer(currentLevel, minLevel, maxLevel, onLevel, startUpCurrentLevel));
898
894
  }
899
895
  getDefaultColorControlClusterServer(currentX = 0, currentY = 0, currentHue = 0, currentSaturation = 0, colorTemperatureMireds = 500, colorTempPhysicalMinMireds = 147, colorTempPhysicalMaxMireds = 500) {
900
896
  return ClusterServer(ColorControlCluster.with(ColorControl.Feature.Xy, ColorControl.Feature.HueSaturation, ColorControl.Feature.ColorTemperature), {
@@ -913,54 +909,36 @@ export class MatterbridgeEndpoint extends Endpoint {
913
909
  colorTempPhysicalMinMireds,
914
910
  colorTempPhysicalMaxMireds,
915
911
  coupleColorTempToLevelMinMireds: colorTempPhysicalMinMireds,
912
+ remainingTime: 0,
916
913
  startUpColorTemperatureMireds: null,
917
914
  }, {
918
915
  moveToColor: async (data) => {
919
- this.log.debug('Matter command: moveToColor request:', data.request, 'attributes.currentX:', data.attributes.currentX.getLocal(), 'attributes.currentY:', data.attributes.currentY.getLocal());
920
- this.commandHandler.executeHandler('moveToColor', data);
921
916
  },
922
917
  moveColor: async () => {
923
- this.log.error('Matter command: moveColor not implemented');
924
918
  },
925
919
  stepColor: async () => {
926
- this.log.error('Matter command: stepColor not implemented');
927
920
  },
928
921
  moveToHue: async (data) => {
929
- this.log.debug('Matter command: moveToHue request:', data.request, 'attributes.currentHue:', data.attributes.currentHue.getLocal());
930
- this.commandHandler.executeHandler('moveToHue', data);
931
922
  },
932
923
  moveHue: async () => {
933
- this.log.error('Matter command: moveHue not implemented');
934
924
  },
935
925
  stepHue: async () => {
936
- this.log.error('Matter command: stepHue not implemented');
937
926
  },
938
927
  moveToSaturation: async (data) => {
939
- this.log.debug('Matter command: moveToSaturation request:', data.request, 'attributes.currentSaturation:', data.attributes.currentSaturation.getLocal());
940
- this.commandHandler.executeHandler('moveToSaturation', data);
941
928
  },
942
929
  moveSaturation: async () => {
943
- this.log.error('Matter command: moveSaturation not implemented');
944
930
  },
945
931
  stepSaturation: async () => {
946
- this.log.error('Matter command: stepSaturation not implemented');
947
932
  },
948
933
  moveToHueAndSaturation: async (data) => {
949
- this.log.debug('Matter command: moveToHueAndSaturation request:', data.request, 'attributes.currentHue:', data.attributes.currentHue.getLocal(), 'attributes.currentSaturation:', data.attributes.currentSaturation.getLocal());
950
- this.commandHandler.executeHandler('moveToHueAndSaturation', data);
951
934
  },
952
935
  stopMoveStep: async () => {
953
- this.log.error('Matter command: stopMoveStep not implemented');
954
936
  },
955
937
  moveToColorTemperature: async (data) => {
956
- this.log.debug('Matter command: moveToColorTemperature request:', data.request, 'attributes.colorTemperatureMireds:', data.attributes.colorTemperatureMireds.getLocal());
957
- this.commandHandler.executeHandler('moveToColorTemperature', data);
958
938
  },
959
939
  moveColorTemperature: async () => {
960
- this.log.error('Matter command: moveColorTemperature not implemented');
961
940
  },
962
941
  stepColorTemperature: async () => {
963
- this.log.error('Matter command: stepColorTemperature not implemented');
964
942
  },
965
943
  }, {});
966
944
  }
@@ -978,6 +956,7 @@ export class MatterbridgeEndpoint extends Endpoint {
978
956
  numberOfPrimaries: null,
979
957
  currentX,
980
958
  currentY,
959
+ remainingTime: 0,
981
960
  }, {
982
961
  moveToColor: async () => {
983
962
  },
@@ -989,7 +968,7 @@ export class MatterbridgeEndpoint extends Endpoint {
989
968
  },
990
969
  }, {});
991
970
  }
992
- createXyControlClusterServer(currentX = 0, currentY = 0) {
971
+ createXyColorControlClusterServer(currentX = 0, currentY = 0) {
993
972
  this.addClusterServer(this.getXyColorControlClusterServer(currentX, currentY));
994
973
  }
995
974
  getHsColorControlClusterServer(currentHue = 0, currentSaturation = 0) {
@@ -1003,6 +982,7 @@ export class MatterbridgeEndpoint extends Endpoint {
1003
982
  numberOfPrimaries: null,
1004
983
  currentHue,
1005
984
  currentSaturation,
985
+ remainingTime: 0,
1006
986
  }, {
1007
987
  moveToHue: async ({ request, attributes, endpoint }) => {
1008
988
  },
@@ -1037,6 +1017,9 @@ export class MatterbridgeEndpoint extends Endpoint {
1037
1017
  colorTemperatureMireds,
1038
1018
  colorTempPhysicalMinMireds,
1039
1019
  colorTempPhysicalMaxMireds,
1020
+ coupleColorTempToLevelMinMireds: colorTempPhysicalMinMireds,
1021
+ remainingTime: 0,
1022
+ startUpColorTemperatureMireds: null,
1040
1023
  }, {
1041
1024
  stopMoveStep: async () => {
1042
1025
  },
@@ -1101,21 +1084,12 @@ export class MatterbridgeEndpoint extends Endpoint {
1101
1084
  currentPositionLiftPercent100ths: positionPercent100ths ?? 0,
1102
1085
  }, {
1103
1086
  upOrOpen: async (data) => {
1104
- this.log.debug('Matter command: upOrOpen');
1105
- await this.commandHandler.executeHandler('upOrOpen', data);
1106
1087
  },
1107
1088
  downOrClose: async (data) => {
1108
- this.log.debug('Matter command: downOrClose');
1109
- await this.commandHandler.executeHandler('downOrClose', data);
1110
1089
  },
1111
1090
  stopMotion: async (data) => {
1112
- this.log.debug('Matter command: stopMotion');
1113
- await this.commandHandler.executeHandler('stopMotion', data);
1114
1091
  },
1115
1092
  goToLiftPercentage: async (data) => {
1116
- this.log.debug(`Matter command: goToLiftPercentage: ${data.request.liftPercent100thsValue} current: ${data.attributes.currentPositionLiftPercent100ths?.getLocal()} ` +
1117
- `target: ${data.attributes.targetPositionLiftPercent100ths?.getLocal()} status: ${data.attributes.operationalStatus.getLocal().lift}`);
1118
- await this.commandHandler.executeHandler('goToLiftPercentage', data);
1119
1093
  },
1120
1094
  }, {});
1121
1095
  }
@@ -1181,12 +1155,8 @@ export class MatterbridgeEndpoint extends Endpoint {
1181
1155
  supportedOperatingModes: { normal: true, vacation: false, privacy: false, noRemoteLockUnlock: false, passage: false },
1182
1156
  }, {
1183
1157
  lockDoor: async (data) => {
1184
- this.log.debug('Matter command: lockDoor', data.request);
1185
- await this.commandHandler.executeHandler('lockDoor', data);
1186
1158
  },
1187
1159
  unlockDoor: async (data) => {
1188
- this.log.debug('Matter command: unlockDoor', data.request);
1189
- await this.commandHandler.executeHandler('unlockDoor', data);
1190
1160
  },
1191
1161
  }, {
1192
1162
  doorLockAlarm: true,
@@ -1301,8 +1271,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1301
1271
  startUpMode: startUpMode,
1302
1272
  }, {
1303
1273
  changeToMode: async (data) => {
1304
- this.log.debug('Matter command: ModeSelectCluster.changeToMode', data.request);
1305
- await this.commandHandler.executeHandler('changeToMode', data);
1306
1274
  },
1307
1275
  });
1308
1276
  }
@@ -1398,8 +1366,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1398
1366
  sensorFault: { generalFault: sensorFault },
1399
1367
  }, {
1400
1368
  enableDisableAlarm: async (data) => {
1401
- this.log.debug('Matter command: enableDisableAlarm', data.request);
1402
- await this.commandHandler.executeHandler('enableDisableAlarm', data);
1403
1369
  },
1404
1370
  }, {
1405
1371
  alarmsStateChanged: true,
@@ -1498,8 +1464,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1498
1464
  absMaxHeatSetpointLimit: maxHeatSetpointLimit * 100,
1499
1465
  }, {
1500
1466
  setpointRaiseLower: async (data) => {
1501
- this.log.debug('Matter command: setpointRaiseLower', data.request);
1502
- await this.commandHandler.executeHandler('setpointRaiseLower', data);
1503
1467
  },
1504
1468
  }, {});
1505
1469
  }
@@ -1518,8 +1482,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1518
1482
  absMaxCoolSetpointLimit: maxCoolSetpointLimit * 100,
1519
1483
  }, {
1520
1484
  setpointRaiseLower: async (data) => {
1521
- this.log.debug('Matter command: setpointRaiseLower', data.request);
1522
- await this.commandHandler.executeHandler('setpointRaiseLower', data);
1523
1485
  },
1524
1486
  }, {});
1525
1487
  }
@@ -1545,8 +1507,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1545
1507
  thermostatRunningMode: Thermostat.ThermostatRunningMode.Off,
1546
1508
  }, {
1547
1509
  setpointRaiseLower: async (data) => {
1548
- this.log.debug('Matter command: setpointRaiseLower', data.request);
1549
- await this.commandHandler.executeHandler('setpointRaiseLower', data);
1550
1510
  },
1551
1511
  }, {});
1552
1512
  }
@@ -1567,8 +1527,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1567
1527
  interconnectCoAlarm: SmokeCoAlarm.AlarmState.Normal,
1568
1528
  }, {
1569
1529
  selfTestRequest: async (data) => {
1570
- this.log.debug('Matter command: selfTestRequest');
1571
- await this.commandHandler.executeHandler('selfTestRequest', data);
1572
1530
  },
1573
1531
  }, {
1574
1532
  smokeAlarm: true,
@@ -1715,8 +1673,6 @@ export class MatterbridgeEndpoint extends Endpoint {
1715
1673
  speedCurrent: 0,
1716
1674
  }, {
1717
1675
  step: async (data) => {
1718
- this.log.debug('Matter command: step', data.request);
1719
- await this.commandHandler.executeHandler('step', data);
1720
1676
  },
1721
1677
  }, {});
1722
1678
  }
@@ -1,5 +1,7 @@
1
1
  import { MatterbridgeDevice } from './matterbridgeDevice.js';
2
+ import { CYAN, nf, wr } from 'node-ansi-logger';
2
3
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
4
+ import { isValidArray, isValidObject } from './utils/utils.js';
3
5
  export class MatterbridgePlatform {
4
6
  matterbridge;
5
7
  log;
@@ -39,13 +41,16 @@ export class MatterbridgePlatform {
39
41
  await this.matterbridge.removeBridgedEndpoint(this.name, device);
40
42
  }
41
43
  async unregisterAllDevices() {
42
- await this.matterbridge.removeAllBridgedDevices(this.name);
44
+ if (this.matterbridge.edge)
45
+ await this.matterbridge.removeAllBridgedEndpoints(this.name);
46
+ else
47
+ await this.matterbridge.removeAllBridgedDevices(this.name);
43
48
  }
44
49
  verifyMatterbridgeVersion(requiredVersion) {
45
50
  const compareVersions = (matterbridgeVersion, requiredVersion) => {
46
51
  const stripTag = (v) => {
47
52
  const parts = v.split('-');
48
- return parts.length > 0 ? parts[0] : v;
53
+ return parts[0];
49
54
  };
50
55
  const v1Parts = stripTag(matterbridgeVersion).split('.').map(Number);
51
56
  const v2Parts = stripTag(requiredVersion).split('.').map(Number);
@@ -65,4 +70,30 @@ export class MatterbridgePlatform {
65
70
  return false;
66
71
  return true;
67
72
  }
73
+ validateDeviceWhiteBlackList(device, log = true) {
74
+ if (isValidArray(this.config.whiteList, 1) && !this.config.whiteList.includes(device)) {
75
+ if (log)
76
+ this.log.info(`Skipping device ${CYAN}${device}${nf} because not in whitelist`);
77
+ return false;
78
+ }
79
+ if (isValidArray(this.config.blackList, 1) && this.config.blackList.includes(device)) {
80
+ if (log)
81
+ this.log.info(`Skipping device ${CYAN}${device}${nf} because in blacklist`);
82
+ return false;
83
+ }
84
+ return true;
85
+ }
86
+ validateEntityBlackList(device, entity, log = true) {
87
+ if (isValidArray(this.config.entityBlackList, 1) && this.config.entityBlackList.find((e) => e === entity)) {
88
+ if (log)
89
+ this.log.info(`Skipping entity ${CYAN}${entity}${nf} because in entityBlackList`);
90
+ return false;
91
+ }
92
+ if (isValidObject(this.config.deviceEntityBlackList, 1) && device in this.config.deviceEntityBlackList && this.config.deviceEntityBlackList[device].includes(entity)) {
93
+ if (log)
94
+ this.log.info(`Skipping entity ${CYAN}${entity}${wr} for device ${CYAN}${device}${nf} because in deviceEntityBlackList`);
95
+ return false;
96
+ }
97
+ return true;
98
+ }
68
99
  }
@@ -81,6 +81,9 @@ export async function wsMessageHandler(client, message) {
81
81
  this.matterbridgeInformation.mattermdnsinterface = (await this.nodeContext?.get('mattermdnsinterface', '')) || '';
82
82
  this.matterbridgeInformation.matteripv4address = (await this.nodeContext?.get('matteripv4address', '')) || '';
83
83
  this.matterbridgeInformation.matteripv6address = (await this.nodeContext?.get('matteripv6address', '')) || '';
84
+ this.matterbridgeInformation.matterPort = (await this.nodeContext?.get('matterport', 5540)) ?? 5540;
85
+ this.matterbridgeInformation.matterDiscriminator = await this.nodeContext?.get('matterdiscriminator');
86
+ this.matterbridgeInformation.matterPasscode = await this.nodeContext?.get('matterpasscode');
84
87
  this.matterbridgeInformation.matterbridgePaired = this.matterbridgePaired;
85
88
  this.matterbridgeInformation.matterbridgeConnected = this.matterbridgeConnected;
86
89
  this.matterbridgeInformation.matterbridgeQrPairingCode = this.matterbridgeQrPairingCode;
@@ -108,6 +111,9 @@ export async function wsMessageHandler(client, message) {
108
111
  let serial = device.getClusterServer(BasicInformationCluster)?.attributes.serialNumber?.getLocal();
109
112
  if (!serial)
110
113
  serial = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.serialNumber?.getLocal() ?? 'Unknown';
114
+ let productUrl = device.getClusterServer(BasicInformationCluster)?.attributes.productUrl?.getLocal();
115
+ if (!productUrl)
116
+ productUrl = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.productUrl?.getLocal() ?? 'Unknown';
111
117
  let uniqueId = device.getClusterServer(BasicInformationCluster)?.attributes.uniqueId?.getLocal();
112
118
  if (!uniqueId)
113
119
  uniqueId = device.getClusterServer(BridgedDeviceBasicInformationCluster)?.attributes.uniqueId?.getLocal() ?? 'Unknown';
@@ -118,6 +124,8 @@ export async function wsMessageHandler(client, message) {
118
124
  endpoint: device.number,
119
125
  name,
120
126
  serial,
127
+ productUrl,
128
+ configUrl: device.configUrl,
121
129
  uniqueId,
122
130
  cluster: cluster,
123
131
  });
@@ -139,99 +139,43 @@ export function xyToHsl(x, y) {
139
139
  const rgb = xyColorToRgbColor(x, y);
140
140
  return rgbColorToHslColor(rgb);
141
141
  }
142
- export function testColors() {
143
- const colors = [
144
- { name: 'Pure Red 0', hsl: { h: 0, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 0 }, xy: { x: 0.7006, y: 0.2993 } },
145
- { name: 'Bright Orange 30', hsl: { h: 30, s: 100, l: 50 }, rgb: { r: 255, g: 128, b: 0 }, xy: { x: 0.6112, y: 0.375 } },
146
- { name: 'Pure Yellow 60', hsl: { h: 60, s: 100, l: 50 }, rgb: { r: 255, g: 255, b: 0 }, xy: { x: 0.4442, y: 0.5166 } },
147
- { name: 'Lime Green 90', hsl: { h: 90, s: 100, l: 50 }, rgb: { r: 128, g: 255, b: 0 }, xy: { x: 0.2707, y: 0.6635 } },
148
- { name: 'Pure Green 120', hsl: { h: 120, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 0 }, xy: { x: 0.1724, y: 0.7468 } },
149
- { name: 'Light Sea Green 150', hsl: { h: 150, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 128 }, xy: { x: 0.1642, y: 0.5886 } },
150
- { name: 'Pure Cyan 180', hsl: { h: 180, s: 100, l: 50 }, rgb: { r: 0, g: 255, b: 255 }, xy: { x: 0.1513, y: 0.3425 } },
151
- { name: 'Deep Sky Blue 210', hsl: { h: 210, s: 100, l: 50 }, rgb: { r: 0, g: 128, b: 255 }, xy: { x: 0.1406, y: 0.1382 } },
152
- { name: 'Pure Blue 240', hsl: { h: 240, s: 100, l: 50 }, rgb: { r: 0, g: 0, b: 255 }, xy: { x: 0.1355, y: 0.0399 } },
153
- { name: 'Blue Violet 270', hsl: { h: 270, s: 100, l: 50 }, rgb: { r: 128, g: 0, b: 255 }, xy: { x: 0.2181, y: 0.0778 } },
154
- { name: 'Pure Magenta 300', hsl: { h: 300, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 255 }, xy: { x: 0.3855, y: 0.1546 } },
155
- { name: 'Deep Pink 330', hsl: { h: 330, s: 100, l: 50 }, rgb: { r: 255, g: 0, b: 128 }, xy: { x: 0.5797, y: 0.2438 } },
156
- { name: 'Pure Red 50% 0', hsl: { h: 0, s: 50, l: 50 }, rgb: { r: 192, g: 64, b: 64 }, xy: { x: 0.6036, y: 0.3069 } },
157
- { name: 'Bright Orange 50% 30', hsl: { h: 30, s: 50, l: 50 }, rgb: { r: 192, g: 128, b: 64 }, xy: { x: 0.5194, y: 0.3928 } },
158
- { name: 'Pure Yellow 50% 60', hsl: { h: 60, s: 50, l: 50 }, rgb: { r: 192, g: 192, b: 64 }, xy: { x: 0.4258, y: 0.4883 } },
159
- { name: 'Lime Green 50% 90', hsl: { h: 90, s: 50, l: 50 }, rgb: { r: 128, g: 192, b: 64 }, xy: { x: 0.3159, y: 0.5639 } },
160
- { name: 'Pure Green 50% 120', hsl: { h: 120, s: 50, l: 50 }, rgb: { r: 64, g: 192, b: 64 }, xy: { x: 0.2127, y: 0.6349 } },
161
- { name: 'Light Sea Green 50% 150', hsl: { h: 150, s: 50, l: 50 }, rgb: { r: 64, g: 192, b: 128 }, xy: { x: 0.1932, y: 0.4845 } },
162
- { name: 'Pure Cyan 50% 180', hsl: { h: 180, s: 50, l: 50 }, rgb: { r: 64, g: 192, b: 192 }, xy: { x: 0.1745, y: 0.3407 } },
163
- { name: 'Deep Sky Blue 50% 210', hsl: { h: 210, s: 50, l: 50 }, rgb: { r: 64, g: 128, b: 192 }, xy: { x: 0.1752, y: 0.211 } },
164
- { name: 'Pure Blue 50% 240', hsl: { h: 240, s: 50, l: 50 }, rgb: { r: 64, g: 64, b: 192 }, xy: { x: 0.1758, y: 0.102 } },
165
- { name: 'Blue Violet 50% 270', hsl: { h: 270, s: 50, l: 50 }, rgb: { r: 128, g: 64, b: 192 }, xy: { x: 0.2688, y: 0.137 } },
166
- { name: 'Pure Magenta 50% 300', hsl: { h: 300, s: 50, l: 50 }, rgb: { r: 192, g: 64, b: 192 }, xy: { x: 0.3772, y: 0.1777 } },
167
- { name: 'Deep Pink 50% 330', hsl: { h: 330, s: 50, l: 50 }, rgb: { r: 192, g: 64, b: 128 }, xy: { x: 0.489, y: 0.2416 } },
168
- ];
169
- colors.forEach((color) => {
170
- console.log(`\x1b[48;2;${color.rgb.r};${color.rgb.g};${color.rgb.b}mColor: ${color.name}\x1b[0m, hsl: { h: ${color.hsl.h}, s: ${color.hsl.s}, l: ${color.hsl.l} }, rgb: { r: ${color.rgb.r}, g: ${color.rgb.g}, b: ${color.rgb.b} }, xy: { x: ${color.xy.x}, y: ${color.xy.y} }`);
171
- const rgb = hslColorToRgbColor(color.hsl.h, color.hsl.s, color.hsl.l);
172
- assert(rgb.r === color.rgb.r && rgb.g === color.rgb.g && rgb.b === color.rgb.b, `\x1b[48;2;${rgb.r};${rgb.g};${rgb.b}mColor: ${color.name}\x1b[0m hslColorToRgbColor { r: ${rgb.r}, g: ${rgb.g}, b: ${rgb.b} } conversion error`);
173
- const hsl = rgbColorToHslColor({ r: color.rgb.r, g: color.rgb.g, b: color.rgb.b });
174
- assert(hsl.h === color.hsl.h && hsl.s === color.hsl.s && hsl.l === color.hsl.l, `Color: ${color.name} rgbColorToHslColor conversion error`);
175
- const xy = rgbColorToXYColor({ r: color.rgb.r, g: color.rgb.g, b: color.rgb.b });
176
- assert(xy.x === color.xy.x && xy.y === color.xy.y, `Color: ${color.name} rgbColorToXYColor conversion error got x ${xy.x} y ${xy.y}`);
177
- const rgb2 = xyColorToRgbColor(color.xy.x, color.xy.y);
178
- assert(rgb2.r === color.rgb.r && rgb2.g === color.rgb.g && rgb2.b === color.rgb.b, `\x1b[48;2;${rgb2.r};${rgb2.g};${rgb2.b}mColor: ${color.name}\x1b[0m xyColorToRgbColor(${color.xy.x}, ${color.xy.y}) conversion error -> r: ${rgb2.r} g: ${rgb2.g} b: ${rgb2.g}`);
179
- });
142
+ export function miredToKelvin(mired) {
143
+ return Math.round(1000000 / mired);
180
144
  }
181
- export function cie_to_rgb(x, y, brightness = 254) {
182
- const z = 1.0 - x - y;
183
- const Y = (brightness / 254).toFixed(2);
184
- const X = (Number(Y) / y) * x;
185
- const Z = (Number(Y) / y) * z;
186
- let red = X * 1.656492 - Number(Y) * 0.354851 - Z * 0.255038;
187
- let green = -X * 0.707196 + Number(Y) * 1.655397 + Z * 0.036152;
188
- let blue = X * 0.051713 - Number(Y) * 0.121364 + Z * 1.01153;
189
- if (red > blue && red > green && red > 1.0) {
190
- green = green / red;
191
- blue = blue / red;
192
- red = 1.0;
145
+ export function kelvinToMired(kelvin) {
146
+ return Math.round(1000000 / kelvin);
147
+ }
148
+ export function kelvinToRGB(kelvin) {
149
+ kelvin = Math.max(1000, Math.min(40000, kelvin)) / 100;
150
+ let r, g, b;
151
+ if (kelvin <= 66) {
152
+ r = 255;
193
153
  }
194
- else if (green > blue && green > red && green > 1.0) {
195
- red = red / green;
196
- blue = blue / green;
197
- green = 1.0;
154
+ else {
155
+ r = kelvin - 60;
156
+ r = 329.698727446 * Math.pow(r, -0.1332047592);
157
+ r = Math.max(0, Math.min(255, r));
198
158
  }
199
- else if (blue > red && blue > green && blue > 1.0) {
200
- red = red / blue;
201
- green = green / blue;
202
- blue = 1.0;
159
+ if (kelvin <= 66) {
160
+ g = kelvin;
161
+ g = 99.4708025861 * Math.log(g) - 161.1195681661;
162
+ g = Math.max(0, Math.min(255, g));
203
163
  }
204
- red = red <= 0.0031308 ? 12.92 * red : (1.0 + 0.055) * Math.pow(red, 1.0 / 2.4) - 0.055;
205
- green = green <= 0.0031308 ? 12.92 * green : (1.0 + 0.055) * Math.pow(green, 1.0 / 2.4) - 0.055;
206
- blue = blue <= 0.0031308 ? 12.92 * blue : (1.0 + 0.055) * Math.pow(blue, 1.0 / 2.4) - 0.055;
207
- red = Math.round(red * 255);
208
- green = Math.round(green * 255);
209
- blue = Math.round(blue * 255);
210
- if (isNaN(red) || red < 0) {
211
- red = 0;
164
+ else {
165
+ g = kelvin - 60;
166
+ g = 288.1221695283 * Math.pow(g, -0.0755148492);
167
+ g = Math.max(0, Math.min(255, g));
212
168
  }
213
- if (isNaN(green) || green < 0) {
214
- green = 0;
169
+ if (kelvin >= 66) {
170
+ b = 255;
215
171
  }
216
- if (isNaN(blue) || blue < 0) {
217
- blue = 0;
172
+ else if (kelvin <= 19) {
173
+ b = 0;
218
174
  }
219
- return { r: red, g: green, b: blue };
220
- }
221
- export function rgb_to_cie(red, green, blue) {
222
- red = red > 0.04045 ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : red / 12.92;
223
- green = green > 0.04045 ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : green / 12.92;
224
- blue = blue > 0.04045 ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : blue / 12.92;
225
- const X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
226
- const Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
227
- const Z = red * 0.000088 + green * 0.07231 + blue * 0.986039;
228
- let x = (X / (X + Y + Z)).toFixed(4);
229
- let y = (Y / (X + Y + Z)).toFixed(4);
230
- if (isNaN(Number(x))) {
231
- x = '0';
232
- }
233
- if (isNaN(Number(y))) {
234
- y = '0';
235
- }
236
- return { x: Number(x), y: Number(y) };
175
+ else {
176
+ b = kelvin - 10;
177
+ b = 138.5177312231 * Math.log(b) - 305.0447927307;
178
+ b = Math.max(0, Math.min(255, b));
179
+ }
180
+ return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };
237
181
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "./static/css/main.823e08b6.css",
4
- "main.js": "./static/js/main.0ab89802.js",
4
+ "main.js": "./static/js/main.a742de4e.js",
5
5
  "static/js/453.abd36b29.chunk.js": "./static/js/453.abd36b29.chunk.js",
6
6
  "static/media/roboto-latin-700-normal.woff2": "./static/media/roboto-latin-700-normal.4535474e1cf8598695ad.woff2",
7
7
  "static/media/roboto-latin-500-normal.woff2": "./static/media/roboto-latin-500-normal.7077203b1982951ecf76.woff2",
@@ -61,11 +61,11 @@
61
61
  "static/media/roboto-greek-ext-400-normal.woff": "./static/media/roboto-greek-ext-400-normal.16eb83b4a3b1ea994243.woff",
62
62
  "index.html": "./index.html",
63
63
  "main.823e08b6.css.map": "./static/css/main.823e08b6.css.map",
64
- "main.0ab89802.js.map": "./static/js/main.0ab89802.js.map",
64
+ "main.a742de4e.js.map": "./static/js/main.a742de4e.js.map",
65
65
  "453.abd36b29.chunk.js.map": "./static/js/453.abd36b29.chunk.js.map"
66
66
  },
67
67
  "entrypoints": [
68
68
  "static/css/main.823e08b6.css",
69
- "static/js/main.0ab89802.js"
69
+ "static/js/main.a742de4e.js"
70
70
  ]
71
71
  }