@riddix/hamh 2.1.0-alpha.759 → 2.1.0-alpha.761

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
@@ -524,6 +524,7 @@ Newest first.
524
524
 
525
525
  | Contributor | Contributions |
526
526
  |-------------|---------------|
527
+ | [@qbattersby](https://github.com/qbattersby) | 🤖 **Code Contributor** - LevelControl transitionTime patch for matter.js 0.17, so Google Home can dim already-on lights ([#383](https://github.com/RiDDiX/home-assistant-matter-hub/pull/383)) |
527
528
  | [@Yllelder](https://github.com/Yllelder) | 🌐 **Translator** - Spanish translation ([#314](https://github.com/RiDDiX/home-assistant-matter-hub/pull/314)) |
528
529
  | [@MStankiewiczOfficial](https://github.com/MStankiewiczOfficial) | 🌐 **Translator** - Polish translation ([#288](https://github.com/RiDDiX/home-assistant-matter-hub/pull/288), [#329](https://github.com/RiDDiX/home-assistant-matter-hub/pull/329)) |
529
530
  | [@aetasoul](https://github.com/aetasoul) | 🤖 **Code Contributor** - Immediate force sync on startup to beat stale Alexa queues ([#282](https://github.com/RiDDiX/home-assistant-matter-hub/pull/282)) |
@@ -7,8 +7,13 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
  if (typeof require !== "undefined") return require.apply(this, arguments);
8
8
  throw Error('Dynamic require of "' + x + '" is not supported');
9
9
  });
10
- var __esm = (fn, res) => function __init() {
11
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ var __esm = (fn, res, err) => function __init() {
11
+ if (err) throw err[0];
12
+ try {
13
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
14
+ } catch (e) {
15
+ throw err = [e], e;
16
+ }
12
17
  };
13
18
  var __export = (target, all) => {
14
19
  for (var name in all)
@@ -123872,6 +123877,7 @@ var init_home_assistant_filter = __esm({
123872
123877
  HomeAssistantMatcherType2["EntityCategory"] = "entity_category";
123873
123878
  HomeAssistantMatcherType2["DeviceName"] = "device_name";
123874
123879
  HomeAssistantMatcherType2["ProductName"] = "product_name";
123880
+ HomeAssistantMatcherType2["Manufacturer"] = "manufacturer";
123875
123881
  HomeAssistantMatcherType2["DeviceClass"] = "device_class";
123876
123882
  })(HomeAssistantMatcherType || (HomeAssistantMatcherType = {}));
123877
123883
  }
@@ -125055,7 +125061,7 @@ var init_bridge_config_schema = __esm({
125055
125061
  {
125056
125062
  const: "any_field_regex",
125057
125063
  title: "any_field_regex",
125058
- description: "Regex tested against a single-line key=value haystack covering entity_id, domain, platform, area, entity_category, device_class, entity_labels, entity_label_names, device_labels, device_label_names, device_name, product_name. Use lookaheads for AND, alternation for OR. Example: '(?=.*domain=light)(?=.*area=living_room)|(?=.*domain=switch)(?=.*entity_labels=.*\\bvoice\\b)'."
125064
+ description: "Regex tested against a single-line key=value haystack covering entity_id, domain, platform, area, entity_category, device_class, entity_labels, entity_label_names, device_labels, device_label_names, device_name, product_name, manufacturer. Use lookaheads for AND, alternation for OR. Example: '(?=.*domain=light)(?=.*area=living_room)|(?=.*domain=switch)(?=.*entity_labels=.*\\bvoice\\b)'."
125059
125065
  },
125060
125066
  {
125061
125067
  const: "area",
@@ -125077,6 +125083,11 @@ var init_bridge_config_schema = __esm({
125077
125083
  title: "product_name",
125078
125084
  description: "Match entities by their product/model name. Supports wildcards. Example: 'Hue*Bulb'."
125079
125085
  },
125086
+ {
125087
+ const: "manufacturer",
125088
+ title: "manufacturer",
125089
+ description: "Match entities by their device manufacturer. Supports wildcards. Handy for MQTT or other generic integrations. Example: '*Sonoff*'."
125090
+ },
125080
125091
  {
125081
125092
  const: "device_class",
125082
125093
  title: "device_class",
@@ -127986,6 +127997,8 @@ function testMatcher(matcher, device, entity, entityState, labels) {
127986
127997
  return testDeviceName(matcher.value, device);
127987
127998
  case "product_name":
127988
127999
  return testProductName(matcher.value, device);
128000
+ case "manufacturer":
128001
+ return testManufacturer(matcher.value, device);
127989
128002
  case "device_class":
127990
128003
  return entityState?.attributes?.device_class === matcher.value;
127991
128004
  }
@@ -128059,7 +128072,8 @@ function buildEntityHaystack(entity, device, entityState, labels) {
128059
128072
  `device_labels=${deviceLabelSlugs.join(",")}`,
128060
128073
  `device_label_names=${deviceLabelNames.join(",")}`,
128061
128074
  `device_name=${deviceName}`,
128062
- `product_name=${productName}`
128075
+ `product_name=${productName}`,
128076
+ `manufacturer=${device?.manufacturer ?? device?.default_manufacturer ?? ""}`
128063
128077
  ].join(" ");
128064
128078
  }
128065
128079
  function testDeviceName(pattern2, device) {
@@ -128092,6 +128106,21 @@ function testProductName(pattern2, device) {
128092
128106
  }
128093
128107
  return lowerProductName.includes(lowerPattern);
128094
128108
  }
128109
+ function testManufacturer(pattern2, device) {
128110
+ if (!device) {
128111
+ return false;
128112
+ }
128113
+ const manufacturer = device.manufacturer ?? device.default_manufacturer;
128114
+ if (!manufacturer) {
128115
+ return false;
128116
+ }
128117
+ const lowerPattern = pattern2.toLowerCase();
128118
+ const lowerManufacturer = manufacturer.toLowerCase();
128119
+ if (lowerPattern.includes("*")) {
128120
+ return patternToRegex(lowerPattern).test(lowerManufacturer);
128121
+ }
128122
+ return lowerManufacturer.includes(lowerPattern);
128123
+ }
128095
128124
  function resolveLabelValue(value, labels) {
128096
128125
  if (labels) {
128097
128126
  const match = labels.find(
@@ -162046,7 +162075,10 @@ var matterDeviceTypeFactories = {
162046
162075
  },
162047
162076
  dishwasher: DishwasherEndpoint,
162048
162077
  dimmable_plugin_unit: (ha) => DimmablePlugInUnitType.set({ homeAssistantEntity: ha }),
162049
- on_off_switch: SwitchDevice,
162078
+ // Expose as On/Off Light (0x0100, an OnOff server) so controllers show a
162079
+ // switch instead of a plug. Plain SwitchDevice is 0x010A (a plug), so the
162080
+ // override had no effect before (#380).
162081
+ on_off_switch: (ha) => OnOffLightType.set({ homeAssistantEntity: ha }),
162050
162082
  door_lock: LockDevice,
162051
162083
  window_covering: CoverDevice,
162052
162084
  thermostat: ClimateDevice,
@@ -166284,16 +166316,58 @@ init_nodejs();
166284
166316
 
166285
166317
  // src/matter/patches/patch-level-control-tlv.ts
166286
166318
  var logger233 = Logger.get("PatchLevelControlTlv");
166319
+ var optionalFieldModels = /* @__PURE__ */ new WeakSet();
166320
+ var fieldModelMandatoryGetterPatched = false;
166287
166321
  function patchLevelControlTlv() {
166288
166322
  let patched = 0;
166323
+ const patchErrors = [];
166324
+ const markOptional = (field2) => {
166325
+ if (!field2) {
166326
+ return false;
166327
+ }
166328
+ try {
166329
+ if (typeof field2.patch === "function") {
166330
+ field2.patch({ conformance: "O" });
166331
+ }
166332
+ } catch (error) {
166333
+ patchErrors.push(formatPatchError("patch", error));
166334
+ }
166335
+ try {
166336
+ field2.optional = true;
166337
+ } catch (error) {
166338
+ patchErrors.push(formatPatchError("optional", error));
166339
+ }
166340
+ try {
166341
+ Object.defineProperty(field2, "mandatory", {
166342
+ configurable: true,
166343
+ value: false,
166344
+ writable: true
166345
+ });
166346
+ } catch (error) {
166347
+ patchErrors.push(formatPatchError("mandatory", error));
166348
+ }
166349
+ return field2.mandatory === false || forceOptionalViaPrototype(field2);
166350
+ };
166289
166351
  const moveToLevelFields = LevelControl3.MoveToLevelRequest.fieldDefinitions;
166290
- if (moveToLevelFields?.transitionTime) {
166291
- moveToLevelFields.transitionTime.optional = true;
166352
+ if (markOptional(moveToLevelFields?.transitionTime)) {
166292
166353
  patched++;
166293
166354
  }
166294
166355
  const stepFields = LevelControl3.StepRequest.fieldDefinitions;
166295
- if (stepFields?.transitionTime) {
166296
- stepFields.transitionTime.optional = true;
166356
+ if (markOptional(stepFields?.transitionTime)) {
166357
+ patched++;
166358
+ }
166359
+ const moveToLevelSchemaField = findTransitionTimeField(
166360
+ LevelControl3.commands.moveToLevel.schema.children,
166361
+ 1
166362
+ );
166363
+ if (markOptional(moveToLevelSchemaField)) {
166364
+ patched++;
166365
+ }
166366
+ const stepSchemaField = findTransitionTimeField(
166367
+ LevelControl3.commands.step.schema.children,
166368
+ 2
166369
+ );
166370
+ if (markOptional(stepSchemaField)) {
166297
166371
  patched++;
166298
166372
  }
166299
166373
  if (patched > 0) {
@@ -166302,10 +166376,62 @@ function patchLevelControlTlv() {
166302
166376
  );
166303
166377
  } else {
166304
166378
  logger233.warn(
166305
- "Failed to patch LevelControl TLV schemas, field definitions not found. Google Home brightness adjustment may not work."
166379
+ "Failed to patch LevelControl TLV schemas, field definitions not found. Google Home brightness adjustment may not work.",
166380
+ {
166381
+ moveToLevel: describeFields(
166382
+ LevelControl3.commands.moveToLevel.schema.children
166383
+ ),
166384
+ patchErrors,
166385
+ step: describeFields(
166386
+ LevelControl3.commands.step.schema.children
166387
+ )
166388
+ }
166306
166389
  );
166307
166390
  }
166308
166391
  }
166392
+ function findTransitionTimeField(fields, fallbackIndex) {
166393
+ return fields?.find(
166394
+ (field2) => field2.name === "TransitionTime" || field2.propertyName === "transitionTime"
166395
+ ) ?? fields?.[fallbackIndex];
166396
+ }
166397
+ function forceOptionalViaPrototype(field2) {
166398
+ optionalFieldModels.add(field2);
166399
+ if (!fieldModelMandatoryGetterPatched) {
166400
+ let proto = Object.getPrototypeOf(field2);
166401
+ while (proto) {
166402
+ const descriptor = Object.getOwnPropertyDescriptor(proto, "mandatory");
166403
+ if (descriptor?.get && descriptor.configurable) {
166404
+ const original = descriptor.get;
166405
+ Object.defineProperty(proto, "mandatory", {
166406
+ configurable: true,
166407
+ get() {
166408
+ if (optionalFieldModels.has(this)) {
166409
+ return false;
166410
+ }
166411
+ return original.call(this);
166412
+ }
166413
+ });
166414
+ fieldModelMandatoryGetterPatched = true;
166415
+ break;
166416
+ }
166417
+ proto = Object.getPrototypeOf(proto);
166418
+ }
166419
+ }
166420
+ return field2.mandatory === false;
166421
+ }
166422
+ function describeFields(fields) {
166423
+ return fields?.map((field2, index) => ({
166424
+ hasPatch: typeof field2.patch === "function",
166425
+ index,
166426
+ mandatory: field2.mandatory,
166427
+ name: field2.name,
166428
+ optional: field2.optional,
166429
+ propertyName: field2.propertyName
166430
+ }));
166431
+ }
166432
+ function formatPatchError(action, error) {
166433
+ return `${action}:${error instanceof Error ? error.message : String(error)}`;
166434
+ }
166309
166435
 
166310
166436
  // src/commands/start/start-handler.ts
166311
166437
  function extractErrorMessage(error) {