@riddix/hamh 2.1.0-alpha.489 → 2.1.0-alpha.490

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.
@@ -146411,6 +146411,7 @@ var init_vacuum = __esm({
146411
146411
  VacuumDeviceFeature2[VacuumDeviceFeature2["MAP"] = 2048] = "MAP";
146412
146412
  VacuumDeviceFeature2[VacuumDeviceFeature2["STATE"] = 4096] = "STATE";
146413
146413
  VacuumDeviceFeature2[VacuumDeviceFeature2["START"] = 8192] = "START";
146414
+ VacuumDeviceFeature2[VacuumDeviceFeature2["CLEAN_AREA"] = 16384] = "CLEAN_AREA";
146414
146415
  })(VacuumDeviceFeature || (VacuumDeviceFeature = {}));
146415
146416
  (function(VacuumFanSpeed2) {
146416
146417
  VacuumFanSpeed2["off"] = "off";
@@ -175703,6 +175704,28 @@ function createCustomServiceAreaServer(customAreas) {
175703
175704
  currentArea: null
175704
175705
  });
175705
175706
  }
175707
+ function createCleanAreaServiceAreaServer(cleanAreaRooms) {
175708
+ const supportedAreas = cleanAreaRooms.map((room) => ({
175709
+ areaId: room.areaId,
175710
+ mapId: null,
175711
+ areaInfo: {
175712
+ locationInfo: {
175713
+ locationName: room.name,
175714
+ floorNumber: null,
175715
+ areaType: null
175716
+ },
175717
+ landmarkInfo: null
175718
+ }
175719
+ }));
175720
+ logger190.info(
175721
+ `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA: ${cleanAreaRooms.map((r) => r.name).join(", ")}`
175722
+ );
175723
+ return ServiceAreaServer2({
175724
+ supportedAreas,
175725
+ selectedAreas: [],
175726
+ currentArea: null
175727
+ });
175728
+ }
175706
175729
 
175707
175730
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-rvc-run-mode-server.ts
175708
175731
  var logger191 = Logger.get("VacuumRvcRunModeServer");
@@ -175774,6 +175797,16 @@ function handleCustomServiceAreas(selectedAreas, customAreas, homeAssistant, ser
175774
175797
  data: first.data
175775
175798
  };
175776
175799
  }
175800
+ function resolveCleanAreaIds(selectedAreas, cleanAreaRooms) {
175801
+ const haAreaIds = [];
175802
+ for (const areaId of selectedAreas) {
175803
+ const room = cleanAreaRooms.find((r) => r.areaId === areaId);
175804
+ if (room) {
175805
+ haAreaIds.push(room.haAreaId);
175806
+ }
175807
+ }
175808
+ return haAreaIds;
175809
+ }
175777
175810
  var vacuumRvcRunModeConfig = {
175778
175811
  getCurrentMode: (entity) => {
175779
175812
  const state = entity.state;
@@ -175812,6 +175845,20 @@ var vacuumRvcRunModeConfig = {
175812
175845
  serviceArea
175813
175846
  );
175814
175847
  }
175848
+ const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
175849
+ if (cleanAreaRooms && cleanAreaRooms.length > 0) {
175850
+ const haAreaIds = resolveCleanAreaIds(selectedAreas, cleanAreaRooms);
175851
+ serviceArea.state.selectedAreas = [];
175852
+ if (haAreaIds.length > 0) {
175853
+ logger191.info(
175854
+ `CLEAN_AREA: cleaning HA areas: ${haAreaIds.join(", ")}`
175855
+ );
175856
+ return {
175857
+ action: "vacuum.clean_area",
175858
+ data: { cleaning_area_id: haAreaIds }
175859
+ };
175860
+ }
175861
+ }
175815
175862
  const roomEntities = homeAssistant.state.mapping?.roomEntities;
175816
175863
  if (roomEntities && roomEntities.length > 0) {
175817
175864
  const buttonEntityIds = [];
@@ -175945,6 +175992,23 @@ var vacuumRvcRunModeConfig = {
175945
175992
  const entity = homeAssistant.entity;
175946
175993
  const attributes7 = entity.state.attributes;
175947
175994
  logger191.info(`cleanRoom called: roomMode=${roomMode}`);
175995
+ const cleanAreaRooms = homeAssistant.state.mapping?.cleanAreaRooms;
175996
+ if (cleanAreaRooms && cleanAreaRooms.length > 0) {
175997
+ const sorted = [...cleanAreaRooms].sort(
175998
+ (a, b) => a.name.localeCompare(b.name)
175999
+ );
176000
+ const areaIndex = roomMode - ROOM_MODE_BASE2 - 1;
176001
+ if (areaIndex >= 0 && areaIndex < sorted.length) {
176002
+ const area = sorted[areaIndex];
176003
+ logger191.info(
176004
+ `cleanRoom: CLEAN_AREA "${area.name}" \u2192 vacuum.clean_area(${area.haAreaId})`
176005
+ );
176006
+ return {
176007
+ action: "vacuum.clean_area",
176008
+ data: { cleaning_area_id: [area.haAreaId] }
176009
+ };
176010
+ }
176011
+ }
175948
176012
  const customAreas = homeAssistant.state.mapping?.customServiceAreas;
175949
176013
  if (customAreas && customAreas.length > 0) {
175950
176014
  const sorted = [...customAreas].sort(
@@ -176080,6 +176144,39 @@ function createVacuumRvcRunModeServer(attributes7, includeUnnamedRooms = false,
176080
176144
  currentMode: 0 /* Idle */
176081
176145
  });
176082
176146
  }
176147
+ function createCleanAreaRvcRunModeServer(cleanAreaRooms) {
176148
+ const modes = [
176149
+ {
176150
+ label: "Idle",
176151
+ mode: 0 /* Idle */,
176152
+ modeTags: [{ value: RvcRunMode3.ModeTag.Idle }]
176153
+ },
176154
+ {
176155
+ label: "Cleaning",
176156
+ mode: 1 /* Cleaning */,
176157
+ modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
176158
+ }
176159
+ ];
176160
+ const sorted = [...cleanAreaRooms].sort(
176161
+ (a, b) => a.name.localeCompare(b.name)
176162
+ );
176163
+ for (let i = 0; i < sorted.length; i++) {
176164
+ const modeValue = ROOM_MODE_BASE2 + i + 1;
176165
+ if (modeValue > 255) continue;
176166
+ modes.push({
176167
+ label: sorted[i].name,
176168
+ mode: modeValue,
176169
+ modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
176170
+ });
176171
+ }
176172
+ logger191.info(
176173
+ `Creating CLEAN_AREA RvcRunModeServer with ${cleanAreaRooms.length} HA areas, ${modes.length} total modes`
176174
+ );
176175
+ return RvcRunModeServer2(vacuumRvcRunModeConfig, {
176176
+ supportedModes: modes,
176177
+ currentMode: 0 /* Idle */
176178
+ });
176179
+ }
176083
176180
  var VacuumRvcRunModeServer = RvcRunModeServer2(vacuumRvcRunModeConfig);
176084
176181
 
176085
176182
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-on-off-server.ts
@@ -177077,8 +177174,9 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
177077
177174
  logger196.info(
177078
177175
  `Creating vacuum endpoint for ${entityId}, mapping: ${JSON.stringify(homeAssistantEntity.mapping ?? "none")}`
177079
177176
  );
177177
+ const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
177080
177178
  let device = VacuumEndpointType.with(
177081
- createVacuumRvcRunModeServer(
177179
+ cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
177082
177180
  attributes7,
177083
177181
  false,
177084
177182
  customAreas && customAreas.length > 0 ? customAreas : void 0
@@ -177092,9 +177190,14 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
177092
177190
  const roomEntities = homeAssistantEntity.mapping?.roomEntities;
177093
177191
  const rooms = parseVacuumRooms(attributes7);
177094
177192
  logger196.info(
177095
- `${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}`
177193
+ `${entityId}: customAreas=${customAreas?.length ?? 0}, roomEntities=${JSON.stringify(roomEntities ?? [])}, parsedRooms=${rooms.length}, cleanAreaRooms=${cleanAreaRooms?.length ?? 0}`
177096
177194
  );
177097
- if (customAreas && customAreas.length > 0) {
177195
+ if (cleanAreaRooms && cleanAreaRooms.length > 0) {
177196
+ logger196.info(
177197
+ `${entityId}: Adding ServiceArea (${cleanAreaRooms.length} HA areas via CLEAN_AREA)`
177198
+ );
177199
+ device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
177200
+ } else if (customAreas && customAreas.length > 0) {
177098
177201
  logger196.info(
177099
177202
  `${entityId}: Adding ServiceArea (${customAreas.length} custom areas)`
177100
177203
  );
@@ -177653,8 +177756,23 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
177653
177756
  `Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity} to ${entityId}`
177654
177757
  );
177655
177758
  }
177759
+ const supportedFeatures = state.attributes.supported_features ?? 0;
177760
+ const cleanAreaRooms = await registry2.resolveCleanAreaRooms(
177761
+ entityId,
177762
+ supportedFeatures
177763
+ );
177764
+ if (cleanAreaRooms.length > 0) {
177765
+ effectiveMapping = {
177766
+ ...effectiveMapping,
177767
+ entityId: effectiveMapping?.entityId ?? entityId,
177768
+ cleanAreaRooms
177769
+ };
177770
+ logger198.debug(
177771
+ `Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA for ${entityId}`
177772
+ );
177773
+ }
177656
177774
  const vacAttrs = state.attributes;
177657
- if (!vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
177775
+ if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
177658
177776
  const valetudoRooms = registry2.findValetudoMapSegments(
177659
177777
  entity.device_id
177660
177778
  );
@@ -178850,6 +178968,54 @@ var BridgeRegistry = class _BridgeRegistry {
178850
178968
  return [];
178851
178969
  }
178852
178970
  }
178971
+ static cleanAreaLogger = Logger.get("CleanAreaRooms");
178972
+ /**
178973
+ * Resolve HA areas mapped to vacuum segments via HA 2026.3 CLEAN_AREA.
178974
+ * Fetches the full entity registry entry (including options.vacuum.area_mapping)
178975
+ * and resolves HA area names from the area registry.
178976
+ * Returns CleanAreaRoom[] sorted alphabetically, or empty array if
178977
+ * CLEAN_AREA is not supported or no area_mapping is configured.
178978
+ */
178979
+ async resolveCleanAreaRooms(entityId, supportedFeatures) {
178980
+ if (!this.client) return [];
178981
+ if (!(supportedFeatures & VacuumDeviceFeature.CLEAN_AREA)) return [];
178982
+ try {
178983
+ const entry = await this.client.connection.sendMessagePromise({
178984
+ type: "config/entity_registry/get",
178985
+ entity_id: entityId
178986
+ });
178987
+ const vacuumOptions = entry?.options?.vacuum;
178988
+ const areaMapping = vacuumOptions?.area_mapping;
178989
+ if (!areaMapping || Object.keys(areaMapping).length === 0) {
178990
+ _BridgeRegistry.cleanAreaLogger.debug(
178991
+ `${entityId}: CLEAN_AREA supported but no area_mapping configured`
178992
+ );
178993
+ return [];
178994
+ }
178995
+ const rooms = [];
178996
+ for (const haAreaId of Object.keys(areaMapping)) {
178997
+ const areaName = this.registry.areas.get(haAreaId) ?? haAreaId;
178998
+ rooms.push({
178999
+ areaId: hashAreaId(haAreaId),
179000
+ haAreaId,
179001
+ name: areaName
179002
+ });
179003
+ }
179004
+ rooms.sort((a, b) => a.name.localeCompare(b.name));
179005
+ if (rooms.length > 0) {
179006
+ _BridgeRegistry.cleanAreaLogger.info(
179007
+ `${entityId}: Resolved ${rooms.length} HA areas via CLEAN_AREA mapping`
179008
+ );
179009
+ }
179010
+ return rooms;
179011
+ } catch (error) {
179012
+ const msg = error instanceof Error ? error.message : typeof error === "object" && error !== null ? JSON.stringify(error) : String(error);
179013
+ _BridgeRegistry.cleanAreaLogger.warn(
179014
+ `${entityId}: Failed to resolve CLEAN_AREA mapping: ${msg}`
179015
+ );
179016
+ return [];
179017
+ }
179018
+ }
178853
179019
  /**
178854
179020
  * Find a pressure sensor entity that belongs to the same HA device.
178855
179021
  * Returns the entity_id of the pressure sensor, or undefined if none found.
@@ -179080,6 +179246,15 @@ var BridgeRegistry = class _BridgeRegistry {
179080
179246
  return true;
179081
179247
  }
179082
179248
  };
179249
+ function hashAreaId(areaId) {
179250
+ let hash2 = 0;
179251
+ for (let i = 0; i < areaId.length; i++) {
179252
+ const char = areaId.charCodeAt(i);
179253
+ hash2 = (hash2 << 5) - hash2 + char;
179254
+ hash2 |= 0;
179255
+ }
179256
+ return Math.abs(hash2);
179257
+ }
179083
179258
 
179084
179259
  // src/services/bridges/server-mode-bridge.ts
179085
179260
  init_dist();
@@ -179455,17 +179630,24 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
179455
179630
  return void 0;
179456
179631
  }
179457
179632
  const attributes7 = homeAssistantEntity.entity.state.attributes;
179633
+ const cleanAreaRooms = homeAssistantEntity.mapping?.cleanAreaRooms;
179634
+ const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
179458
179635
  let device = ServerModeVacuumEndpointType.with(
179459
- createVacuumRvcRunModeServer(attributes7)
179636
+ cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
179637
+ attributes7,
179638
+ false,
179639
+ customAreas && customAreas.length > 0 ? customAreas : void 0
179640
+ )
179460
179641
  ).set({ homeAssistantEntity });
179461
179642
  if (includeOnOff) {
179462
179643
  device = device.with(VacuumOnOffServer);
179463
179644
  }
179464
179645
  device = device.with(VacuumPowerSourceServer);
179465
- const customAreas = homeAssistantEntity.mapping?.customServiceAreas;
179466
179646
  const roomEntities = homeAssistantEntity.mapping?.roomEntities;
179467
179647
  const rooms = parseVacuumRooms(attributes7);
179468
- if (customAreas && customAreas.length > 0) {
179648
+ if (cleanAreaRooms && cleanAreaRooms.length > 0) {
179649
+ device = device.with(createCleanAreaServiceAreaServer(cleanAreaRooms));
179650
+ } else if (customAreas && customAreas.length > 0) {
179469
179651
  device = device.with(createCustomServiceAreaServer(customAreas));
179470
179652
  } else if (rooms.length > 0 || roomEntities && roomEntities.length > 0) {
179471
179653
  device = device.with(
@@ -179563,8 +179745,23 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
179563
179745
  `${entityId}: Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity}`
179564
179746
  );
179565
179747
  }
179748
+ const supportedFeatures = state.attributes.supported_features ?? 0;
179749
+ const cleanAreaRooms = await registry2.resolveCleanAreaRooms(
179750
+ entityId,
179751
+ supportedFeatures
179752
+ );
179753
+ if (cleanAreaRooms.length > 0) {
179754
+ effectiveMapping = {
179755
+ ...effectiveMapping,
179756
+ entityId: effectiveMapping?.entityId ?? entityId,
179757
+ cleanAreaRooms
179758
+ };
179759
+ logger201.info(
179760
+ `${entityId}: Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA`
179761
+ );
179762
+ }
179566
179763
  const vacAttrs = state.attributes;
179567
- if (!vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
179764
+ if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
179568
179765
  const valetudoRooms = registry2.findValetudoMapSegments(
179569
179766
  entity.device_id
179570
179767
  );