@riddix/hamh 2.0.41 → 2.0.42

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
@@ -37,7 +37,7 @@ of port forwarding etc.
37
37
 
38
38
  | Channel | Branch | Current Version | Description |
39
39
  |---------|--------|-----------------|-------------|
40
- | **Stable** | `main` | v2.0.41 | Production-ready, recommended for most users |
40
+ | **Stable** | `main` | v2.0.42 | Production-ready, recommended for most users |
41
41
  | **Alpha** | `alpha` | v2.1.0-alpha.x | Pre-release with new features, for early adopters |
42
42
  | **Testing** | `testing` | v4.1.0-testing.x | ⚠️ **Highly unstable!** Experimental features, may break |
43
43
 
@@ -52,9 +52,16 @@ of port forwarding etc.
52
52
  ## 🎉 What's New
53
53
 
54
54
  <details>
55
- <summary><strong>📦 Stable Features (v2.0.41)</strong> - Click to expand</summary>
55
+ <summary><strong>📦 Stable Features (v2.0.42)</strong> - Click to expand</summary>
56
56
 
57
- **New in v2.0.41:**
57
+ **New in v2.0.42 (hotfix release):**
58
+
59
+ - 🇯🇵 Aqara bridge registration no longer stalls — root `softwareVersionString` now matches the numeric `softwareVersion` ([#316](https://github.com/RiDDiX/home-assistant-matter-hub/issues/316))
60
+ - ❄️ Climate `auto` mode is clamped to `heat`/`cool` on devices without an `AutoMode` base ([#319](https://github.com/RiDDiX/home-assistant-matter-hub/issues/319))
61
+ - 🌀 Per-entity `disableClimateFanControl` mapping flag — falls back to `ThermostatDevice` when controllers like Aqara don't recognise `RoomAirConditioner` (`0x0072`) ([#318](https://github.com/RiDDiX/home-assistant-matter-hub/issues/318))
62
+ - 🗺️ Vacuum service area `selectedAreas` is kept after dispatch instead of being cleared
63
+
64
+ **Previously in v2.0.41:**
58
65
 
59
66
  | Feature | Description |
60
67
  |---------|-------------|
@@ -127,7 +134,7 @@ of port forwarding etc.
127
134
  <details>
128
135
  <summary><strong>🧪 Alpha Features (v2.1.0-alpha.x)</strong> - Click to expand</summary>
129
136
 
130
- **Alpha is currently level with Stable (v2.0.41).** All alpha work from the v2.1.0-alpha.601 line through v2.1.0-alpha.626 has been promoted into v2.0.41. New alpha work continues from `v2.1.0-alpha.627` onward and will appear here as development progresses.
137
+ **Alpha is currently level with Stable (v2.0.42).** All alpha work through `v2.1.0-alpha.633` has been promoted into v2.0.42. New alpha work continues from `v2.1.0-alpha.634` onward and will appear here as development progresses.
131
138
 
132
139
  </details>
133
140
 
@@ -147874,6 +147874,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
147874
147874
  valetudoIdentifier: config10.valetudoIdentifier,
147875
147875
  coverSwapOpenClose: config10.coverSwapOpenClose,
147876
147876
  disableClimateOnOff: config10.disableClimateOnOff,
147877
+ disableClimateFanControl: config10.disableClimateFanControl,
147877
147878
  customServiceAreas: config10.customServiceAreas,
147878
147879
  customFanSpeedTags: config10.customFanSpeedTags,
147879
147880
  composedEntities: config10.composedEntities
@@ -148020,6 +148021,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
148020
148021
  valetudoIdentifier: config10.valetudoIdentifier,
148021
148022
  coverSwapOpenClose: config10.coverSwapOpenClose,
148022
148023
  disableClimateOnOff: config10.disableClimateOnOff,
148024
+ disableClimateFanControl: config10.disableClimateFanControl,
148023
148025
  customServiceAreas: config10.customServiceAreas,
148024
148026
  customFanSpeedTags: config10.customFanSpeedTags,
148025
148027
  composedEntities: config10.composedEntities
@@ -148840,6 +148842,7 @@ function entityMappingApi(mappingStorage) {
148840
148842
  valetudoIdentifier: body.valetudoIdentifier,
148841
148843
  coverSwapOpenClose: body.coverSwapOpenClose,
148842
148844
  disableClimateOnOff: body.disableClimateOnOff,
148845
+ disableClimateFanControl: body.disableClimateFanControl,
148843
148846
  composedEntities: body.composedEntities
148844
148847
  };
148845
148848
  const config10 = await mappingStorage.setMapping(request);
@@ -149303,7 +149306,8 @@ function configToProfileEntry(config10) {
149303
149306
  customFanSpeedTags: config10.customFanSpeedTags,
149304
149307
  valetudoIdentifier: config10.valetudoIdentifier,
149305
149308
  coverSwapOpenClose: config10.coverSwapOpenClose,
149306
- disableClimateOnOff: config10.disableClimateOnOff
149309
+ disableClimateOnOff: config10.disableClimateOnOff,
149310
+ disableClimateFanControl: config10.disableClimateFanControl
149307
149311
  };
149308
149312
  }
149309
149313
  function mappingProfileApi(mappingStorage) {
@@ -149425,7 +149429,8 @@ function mappingProfileApi(mappingStorage) {
149425
149429
  customFanSpeedTags: entry.customFanSpeedTags,
149426
149430
  valetudoIdentifier: entry.valetudoIdentifier,
149427
149431
  coverSwapOpenClose: entry.coverSwapOpenClose,
149428
- disableClimateOnOff: entry.disableClimateOnOff
149432
+ disableClimateOnOff: entry.disableClimateOnOff,
149433
+ disableClimateFanControl: entry.disableClimateFanControl
149429
149434
  });
149430
149435
  applied++;
149431
149436
  } catch (e) {
@@ -153295,9 +153300,10 @@ var EntityMappingStorage = class extends Service {
153295
153300
  valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0,
153296
153301
  coverSwapOpenClose: request.coverSwapOpenClose || void 0,
153297
153302
  disableClimateOnOff: request.disableClimateOnOff || void 0,
153303
+ disableClimateFanControl: request.disableClimateFanControl || void 0,
153298
153304
  composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
153299
153305
  };
153300
- if (!config10.matterDeviceType && !config10.customName && !config10.customProductName && !config10.customVendorName && !config10.customSerialNumber && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.temperatureEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0) && !config10.currentRoomEntity && !config10.valetudoIdentifier && !config10.coverSwapOpenClose && !config10.disableClimateOnOff && (!config10.composedEntities || config10.composedEntities.length === 0)) {
153306
+ if (!config10.matterDeviceType && !config10.customName && !config10.customProductName && !config10.customVendorName && !config10.customSerialNumber && config10.disabled !== true && !config10.filterLifeEntity && !config10.cleaningModeEntity && !config10.temperatureEntity && !config10.humidityEntity && !config10.batteryEntity && !config10.roomEntities && !config10.disableLockPin && !config10.powerEntity && !config10.energyEntity && !config10.pressureEntity && !config10.suctionLevelEntity && !config10.mopIntensityEntity && (!config10.customServiceAreas || config10.customServiceAreas.length === 0) && (!config10.customFanSpeedTags || Object.keys(config10.customFanSpeedTags).length === 0) && !config10.currentRoomEntity && !config10.valetudoIdentifier && !config10.coverSwapOpenClose && !config10.disableClimateOnOff && !config10.disableClimateFanControl && (!config10.composedEntities || config10.composedEntities.length === 0)) {
153301
153307
  bridgeMap.delete(request.entityId);
153302
153308
  } else {
153303
153309
  bridgeMap.set(request.entityId, config10);
@@ -167516,7 +167522,9 @@ function createBridgeServerConfig(data) {
167516
167522
  hardwareVersion: data.basicInformation.hardwareVersion,
167517
167523
  softwareVersion: data.basicInformation.softwareVersion,
167518
167524
  hardwareVersionString: data.basicInformation.hardwareVersionString,
167519
- softwareVersionString: data.basicInformation.softwareVersionString ?? String(data.basicInformation.softwareVersion),
167525
+ // Keep the root string aligned with the numeric softwareVersion. Aqara
167526
+ // stalls bridge registration when the two diverge (#316).
167527
+ softwareVersionString: String(data.basicInformation.softwareVersion),
167520
167528
  ...data.countryCode ? { location: data.countryCode } : {}
167521
167529
  },
167522
167530
  subscriptions: {
@@ -171745,7 +171753,9 @@ var config4 = {
171745
171753
  const direction = getHeatCoolOnlyDirection(entity, agent);
171746
171754
  return direction === "cooling" ? Thermostat3.SystemMode.Cool : Thermostat3.SystemMode.Heat;
171747
171755
  }
171748
- const hasMatterAuto = modes.includes(ClimateHvacMode.heat_cool) || modes.includes(ClimateHvacMode.auto);
171756
+ const hasCoolCapability = modes.includes(ClimateHvacMode.cool) || modes.includes(ClimateHvacMode.heat_cool);
171757
+ const hasHeatCapability = modes.includes(ClimateHvacMode.heat) || modes.includes(ClimateHvacMode.heat_cool);
171758
+ const hasMatterAuto = (modes.includes(ClimateHvacMode.heat_cool) || modes.includes(ClimateHvacMode.auto)) && hasCoolCapability && hasHeatCapability;
171749
171759
  if (hasMatterAuto) {
171750
171760
  return systemMode;
171751
171761
  }
@@ -171917,10 +171927,7 @@ function ClimateDevice(homeAssistantEntity) {
171917
171927
  }
171918
171928
  const supportsHumidity = attributes7.current_humidity != null || testBit(supportedFeatures, ClimateDeviceFeature.TARGET_HUMIDITY);
171919
171929
  const supportsOnOff = testBit(supportedFeatures, ClimateDeviceFeature.TURN_ON) && testBit(supportedFeatures, ClimateDeviceFeature.TURN_OFF) && homeAssistantEntity.mapping?.disableClimateOnOff !== true;
171920
- const supportsFanMode = testBit(
171921
- supportedFeatures,
171922
- ClimateDeviceFeature.FAN_MODE
171923
- );
171930
+ const supportsFanMode = testBit(supportedFeatures, ClimateDeviceFeature.FAN_MODE) && homeAssistantEntity.mapping?.disableClimateFanControl !== true;
171924
171931
  const initialState = {
171925
171932
  // Pass actual current_temperature for initial state.
171926
171933
  // If unavailable (null/undefined), update() will fall back to the
@@ -177608,9 +177615,8 @@ function buildSupportedModes2(attributes7, includeUnnamedRooms = false, customAr
177608
177615
  }
177609
177616
  return modes;
177610
177617
  }
177611
- function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant, serviceArea) {
177618
+ function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant) {
177612
177619
  const matched = selectedAreas.map((areaId) => customAreas[areaId - 1]).filter(Boolean);
177613
- serviceArea.state.selectedAreas = [];
177614
177620
  if (matched.length === 0) {
177615
177621
  logger194.warn(
177616
177622
  `Custom service areas: no match for selected IDs ${selectedAreas.join(", ")}`
@@ -177680,14 +177686,12 @@ var vacuumRvcRunModeConfig = {
177680
177686
  return handleCustomServiceAreas(
177681
177687
  selectedAreas,
177682
177688
  customAreas,
177683
- homeAssistant,
177684
- serviceArea
177689
+ homeAssistant
177685
177690
  );
177686
177691
  }
177687
177692
  const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
177688
177693
  if (cleanAreaRooms && cleanAreaRooms.length > 0) {
177689
177694
  const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
177690
- serviceArea.state.selectedAreas = [];
177691
177695
  if (haAreaIds.length > 0) {
177692
177696
  logger194.info(
177693
177697
  `CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`
@@ -177713,7 +177717,6 @@ var vacuumRvcRunModeConfig = {
177713
177717
  logger194.info(
177714
177718
  `Roborock: Pressing button entities for selected rooms: ${buttonEntityIds.join(", ")}`
177715
177719
  );
177716
- serviceArea.state.selectedAreas = [];
177717
177720
  for (let i = 1; i < buttonEntityIds.length; i++) {
177718
177721
  homeAssistant.callAction({
177719
177722
  action: "button.press",
@@ -177728,7 +177731,6 @@ var vacuumRvcRunModeConfig = {
177728
177731
  }
177729
177732
  const vacuumEntityId = homeAssistant.entityId;
177730
177733
  if (vacuumEntityId.startsWith("vacuum.valetudo_")) {
177731
- serviceArea.state.selectedAreas = [];
177732
177734
  return buildValetudoSegmentAction(
177733
177735
  vacuumEntityId,
177734
177736
  selectedAreas,
@@ -177751,7 +177753,6 @@ var vacuumRvcRunModeConfig = {
177751
177753
  logger194.info(
177752
177754
  `Starting cleaning with selected areas: ${roomIds.join(", ")}`
177753
177755
  );
177754
- serviceArea.state.selectedAreas = [];
177755
177756
  if (isDreameVacuum(attributes7)) {
177756
177757
  if (targetMapName) {
177757
177758
  const vacName = vacuumEntityId.replace("vacuum.", "");