@riddix/hamh 2.1.0-alpha.734 → 2.1.0-alpha.736

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.
@@ -124663,8 +124663,8 @@ var init_bridge_config_schema = __esm({
124663
124663
  default: false
124664
124664
  },
124665
124665
  serverMode: {
124666
- title: "Server Mode (for Robot Vacuums)",
124667
- description: "Expose the device as a standalone Matter device instead of a bridged device. This is required for Apple Home to properly support Siri voice commands for Robot Vacuums. IMPORTANT: Only ONE device should be in this bridge when server mode is enabled.",
124666
+ title: "Server Mode (standalone device)",
124667
+ description: "Expose the entity as a standalone Matter device instead of a bridged device. Works for any supported device type, e.g. robot vacuums need it for Apple Home Siri voice commands. IMPORTANT: Only ONE device should be in this bridge when server mode is enabled.",
124668
124668
  type: "boolean",
124669
124669
  default: false
124670
124670
  },
@@ -124822,7 +124822,10 @@ var init_create_bridge_request_schema = __esm({
124822
124822
  "../common/dist/schemas/create-bridge-request-schema.js"() {
124823
124823
  "use strict";
124824
124824
  init_bridge_config_schema();
124825
- createBridgeRequestSchema = bridgeConfigSchema;
124825
+ createBridgeRequestSchema = {
124826
+ ...bridgeConfigSchema,
124827
+ required: ["name", "filter"]
124828
+ };
124826
124829
  }
124827
124830
  });
124828
124831
 
@@ -126800,6 +126803,7 @@ function entityMappingApi(mappingStorage) {
126800
126803
  customFanSpeedTags: body.customFanSpeedTags,
126801
126804
  currentRoomEntity: body.currentRoomEntity,
126802
126805
  cleanedAreaEntity: body.cleanedAreaEntity,
126806
+ disableCustomAreaRoomModes: body.disableCustomAreaRoomModes,
126803
126807
  valetudoIdentifier: body.valetudoIdentifier,
126804
126808
  coverSwapOpenClose: body.coverSwapOpenClose,
126805
126809
  coverSliderDebounceMs: body.coverSliderDebounceMs,
@@ -130501,11 +130505,13 @@ var BridgeService = class extends Service {
130501
130505
  return this.bridges.find((bridge) => bridge.id === id);
130502
130506
  }
130503
130507
  async create(request) {
130504
- if (this.portUsed(request.port)) {
130505
- throw new Error(`Port already in use: ${request.port}`);
130508
+ const port = request.port ?? this.getNextAvailablePort();
130509
+ if (this.portUsed(port)) {
130510
+ throw new Error(`Port already in use: ${port}`);
130506
130511
  }
130507
130512
  const bridge = await this.addBridge({
130508
130513
  ...request,
130514
+ port,
130509
130515
  id: crypto3.randomUUID().replace(/-/g, ""),
130510
130516
  basicInformation: this.props.basicInformation
130511
130517
  });
@@ -131420,6 +131426,7 @@ var EntityMappingStorage = class extends Service {
131420
131426
  customFanSpeedTags: request.customFanSpeedTags && Object.keys(request.customFanSpeedTags).length > 0 ? request.customFanSpeedTags : void 0,
131421
131427
  currentRoomEntity: request.currentRoomEntity?.trim() || void 0,
131422
131428
  cleanedAreaEntity: request.cleanedAreaEntity?.trim() || void 0,
131429
+ disableCustomAreaRoomModes: request.disableCustomAreaRoomModes || void 0,
131423
131430
  valetudoIdentifier: request.valetudoIdentifier?.trim() || void 0,
131424
131431
  coverSwapOpenClose: request.coverSwapOpenClose || void 0,
131425
131432
  coverSliderDebounceMs: sanitizeDebounceMs(request.coverSliderDebounceMs),
@@ -131430,7 +131437,7 @@ var EntityMappingStorage = class extends Service {
131430
131437
  climateAutoMode: request.climateAutoMode || void 0,
131431
131438
  composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
131432
131439
  };
131433
- if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.roomEntities && !config11.disableLockPin && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverSliderDebounceMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
131440
+ if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.roomEntities && !config11.disableLockPin && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverSliderDebounceMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
131434
131441
  bridgeMap.delete(request.entityId);
131435
131442
  } else {
131436
131443
  bridgeMap.set(request.entityId, config11);
@@ -159128,7 +159135,7 @@ function buildValetudoSegmentAction(vacuumEntityId, segmentIds, valetudoIdentifi
159128
159135
  }
159129
159136
  };
159130
159137
  }
159131
- function buildSupportedModes2(attributes8, includeUnnamedRooms = false, customAreas) {
159138
+ function buildSupportedModes2(attributes8, includeUnnamedRooms = false, customAreas, disableRoomModes = false) {
159132
159139
  const modes = [
159133
159140
  {
159134
159141
  label: "Idle",
@@ -159142,17 +159149,19 @@ function buildSupportedModes2(attributes8, includeUnnamedRooms = false, customAr
159142
159149
  }
159143
159150
  ];
159144
159151
  if (customAreas && customAreas.length > 0) {
159145
- const sorted = [...customAreas].sort(
159146
- (a, b) => a.name.localeCompare(b.name)
159147
- );
159148
- for (let i = 0; i < sorted.length; i++) {
159149
- const modeValue = ROOM_MODE_BASE2 + i + 1;
159150
- if (modeValue > 255) continue;
159151
- modes.push({
159152
- label: sorted[i].name,
159153
- mode: modeValue,
159154
- modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
159155
- });
159152
+ if (!disableRoomModes) {
159153
+ const sorted = [...customAreas].sort(
159154
+ (a, b) => a.name.localeCompare(b.name)
159155
+ );
159156
+ for (let i = 0; i < sorted.length; i++) {
159157
+ const modeValue = ROOM_MODE_BASE2 + i + 1;
159158
+ if (modeValue > 255) continue;
159159
+ modes.push({
159160
+ label: sorted[i].name,
159161
+ mode: modeValue,
159162
+ modeTags: [{ value: RvcRunMode3.ModeTag.Cleaning }]
159163
+ });
159164
+ }
159156
159165
  }
159157
159166
  } else {
159158
159167
  const rooms = parseVacuumRooms(attributes8, includeUnnamedRooms);
@@ -159285,11 +159294,13 @@ var vacuumRvcRunModeConfig = {
159285
159294
  },
159286
159295
  getSupportedModes: (entity, agent) => {
159287
159296
  const attributes8 = entity.attributes;
159288
- const customAreas = agent.get(HomeAssistantEntityBehavior).state.mapping?.customServiceAreas;
159297
+ const mapping = agent.get(HomeAssistantEntityBehavior).state.mapping;
159298
+ const customAreas = mapping?.customServiceAreas;
159289
159299
  return buildSupportedModes2(
159290
159300
  attributes8,
159291
159301
  false,
159292
- customAreas && customAreas.length > 0 ? customAreas : void 0
159302
+ customAreas && customAreas.length > 0 ? customAreas : void 0,
159303
+ mapping?.disableCustomAreaRoomModes
159293
159304
  );
159294
159305
  },
159295
159306
  // biome-ignore lint/suspicious/noConfusingVoidType: Required by ValueSetter<void> interface
@@ -159546,14 +159557,15 @@ var vacuumRvcRunModeConfig = {
159546
159557
  return { action: "vacuum.start" };
159547
159558
  }
159548
159559
  };
159549
- function createVacuumRvcRunModeServer(attributes8, includeUnnamedRooms = false, customAreas) {
159560
+ function createVacuumRvcRunModeServer(attributes8, includeUnnamedRooms = false, customAreas, disableRoomModes = false) {
159550
159561
  const allRooms = parseVacuumRooms(attributes8, true);
159551
159562
  const rooms = includeUnnamedRooms ? allRooms : parseVacuumRooms(attributes8, false);
159552
159563
  const filteredCount = allRooms.length - rooms.length;
159553
159564
  const supportedModes = buildSupportedModes2(
159554
159565
  attributes8,
159555
159566
  includeUnnamedRooms,
159556
- customAreas
159567
+ customAreas,
159568
+ disableRoomModes
159557
159569
  );
159558
159570
  logger220.info(
159559
159571
  `Creating VacuumRvcRunModeServer with ${rooms.length} rooms, ${supportedModes.length} total modes`
@@ -160606,7 +160618,8 @@ function VacuumDevice(homeAssistantEntity, includeOnOff = false, cleaningModeOpt
160606
160618
  cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
160607
160619
  attributes8,
160608
160620
  false,
160609
- customAreas && customAreas.length > 0 ? customAreas : void 0
160621
+ customAreas && customAreas.length > 0 ? customAreas : void 0,
160622
+ homeAssistantEntity.mapping?.disableCustomAreaRoomModes
160610
160623
  )
160611
160624
  ).set({ homeAssistantEntity });
160612
160625
  if (includeOnOff) {
@@ -163799,7 +163812,8 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
163799
163812
  cleanAreaRooms && cleanAreaRooms.length > 0 ? createCleanAreaRvcRunModeServer(cleanAreaRooms) : createVacuumRvcRunModeServer(
163800
163813
  attributes8,
163801
163814
  false,
163802
- customAreas && customAreas.length > 0 ? customAreas : void 0
163815
+ customAreas && customAreas.length > 0 ? customAreas : void 0,
163816
+ homeAssistantEntity.mapping?.disableCustomAreaRoomModes
163803
163817
  )
163804
163818
  ).set({ homeAssistantEntity });
163805
163819
  if (includeOnOff) {
@@ -164096,20 +164110,20 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
164096
164110
 
164097
164111
  // src/services/bridges/server-mode-endpoint-manager.ts
164098
164112
  var ServerModeEndpointManager = class extends Service {
164099
- constructor(serverNode, client, registry2, mappingStorage, bridgeId, log) {
164113
+ constructor(serverNode, client, registry2, mappingStorage, dataProvider, log) {
164100
164114
  super("ServerModeEndpointManager");
164101
164115
  this.serverNode = serverNode;
164102
164116
  this.client = client;
164103
164117
  this.registry = registry2;
164104
164118
  this.mappingStorage = mappingStorage;
164105
- this.bridgeId = bridgeId;
164119
+ this.dataProvider = dataProvider;
164106
164120
  this.log = log;
164107
164121
  }
164108
164122
  serverNode;
164109
164123
  client;
164110
164124
  registry;
164111
164125
  mappingStorage;
164112
- bridgeId;
164126
+ dataProvider;
164113
164127
  log;
164114
164128
  entityIds = [];
164115
164129
  unsubscribe;
@@ -164126,7 +164140,7 @@ var ServerModeEndpointManager = class extends Service {
164126
164140
  return this.deviceEndpoint;
164127
164141
  }
164128
164142
  getEntityMapping(entityId) {
164129
- return this.mappingStorage.getMapping(this.bridgeId, entityId);
164143
+ return this.mappingStorage.getMapping(this.dataProvider.id, entityId);
164130
164144
  }
164131
164145
  computeMappingFingerprint(mapping) {
164132
164146
  if (!mapping) return "";
@@ -164177,6 +164191,10 @@ var ServerModeEndpointManager = class extends Service {
164177
164191
  this.entityIds = this.registry.entityIds;
164178
164192
  if (this.entityIds.length === 0) {
164179
164193
  this.log.warn("Server mode bridge has no entities configured");
164194
+ this._failedEntities.push({
164195
+ entityId: this.dataProvider.filter?.include?.[0]?.value ?? "(no entity configured)",
164196
+ reason: "No Home Assistant entity matched this bridge's filter. Check for typos or renamed/removed entities."
164197
+ });
164180
164198
  return;
164181
164199
  }
164182
164200
  if (this.entityIds.length > 1) {
@@ -164197,6 +164215,10 @@ var ServerModeEndpointManager = class extends Service {
164197
164215
  this.log.warn(
164198
164216
  `The only entity in server mode bridge is disabled: ${entityId}`
164199
164217
  );
164218
+ this._failedEntities.push({
164219
+ entityId,
164220
+ reason: "The configured entity is disabled for this bridge."
164221
+ });
164200
164222
  return;
164201
164223
  }
164202
164224
  const currentFp = this.computeMappingFingerprint(mapping);
@@ -164277,9 +164299,10 @@ var ServerModeEndpointManager = class extends Service {
164277
164299
  const reason = e instanceof Error ? e.message : String(e);
164278
164300
  this.log.error(`Failed to create server mode device ${entityId}:`, e);
164279
164301
  this._failedEntities.push({ entityId, reason });
164280
- }
164281
- if (this.unsubscribe) {
164282
- this.startObserving();
164302
+ } finally {
164303
+ if (this.unsubscribe) {
164304
+ this.startObserving();
164305
+ }
164283
164306
  }
164284
164307
  }
164285
164308
  async updateStates(states) {
@@ -164473,7 +164496,7 @@ var BridgeEnvironmentFactory = class extends BridgeFactory {
164473
164496
  await env.load(HomeAssistantClient),
164474
164497
  env.get(BridgeRegistry),
164475
164498
  await env.load(EntityMappingStorage),
164476
- dataProvider.id,
164499
+ dataProvider,
164477
164500
  loggerService.get("ServerModeEndpointManager")
164478
164501
  );
164479
164502
  class ServerModeBridgeWithEnvironment extends ServerModeBridge {