@riddix/hamh 2.1.0-alpha.767 → 2.1.0-alpha.769

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.
@@ -126316,6 +126316,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
126316
126316
  climateAutoMode: config11.climateAutoMode,
126317
126317
  customServiceAreas: config11.customServiceAreas,
126318
126318
  customFanSpeedTags: config11.customFanSpeedTags,
126319
+ fanWindPresets: config11.fanWindPresets,
126319
126320
  composedEntities: config11.composedEntities
126320
126321
  });
126321
126322
  mappingsRestored++;
@@ -126466,6 +126467,7 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
126466
126467
  climateAutoMode: config11.climateAutoMode,
126467
126468
  customServiceAreas: config11.customServiceAreas,
126468
126469
  customFanSpeedTags: config11.customFanSpeedTags,
126470
+ fanWindPresets: config11.fanWindPresets,
126469
126471
  composedEntities: config11.composedEntities
126470
126472
  });
126471
126473
  mappingsRestored++;
@@ -127300,6 +127302,7 @@ function entityMappingApi(mappingStorage) {
127300
127302
  mopIntensityEntity: body.mopIntensityEntity,
127301
127303
  customServiceAreas: body.customServiceAreas,
127302
127304
  customFanSpeedTags: body.customFanSpeedTags,
127305
+ fanWindPresets: body.fanWindPresets,
127303
127306
  currentRoomEntity: body.currentRoomEntity,
127304
127307
  cleanedAreaEntity: body.cleanedAreaEntity,
127305
127308
  disableCustomAreaRoomModes: body.disableCustomAreaRoomModes,
@@ -127785,6 +127788,7 @@ function configToProfileEntry(config11) {
127785
127788
  mopIntensityEntity: config11.mopIntensityEntity,
127786
127789
  customServiceAreas: config11.customServiceAreas,
127787
127790
  customFanSpeedTags: config11.customFanSpeedTags,
127791
+ fanWindPresets: config11.fanWindPresets,
127788
127792
  valetudoIdentifier: config11.valetudoIdentifier,
127789
127793
  coverSwapOpenClose: config11.coverSwapOpenClose,
127790
127794
  coverSliderDebounceMs: config11.coverSliderDebounceMs,
@@ -127912,6 +127916,7 @@ function mappingProfileApi(mappingStorage) {
127912
127916
  mopIntensityEntity: entry.mopIntensityEntity,
127913
127917
  customServiceAreas: entry.customServiceAreas,
127914
127918
  customFanSpeedTags: entry.customFanSpeedTags,
127919
+ fanWindPresets: entry.fanWindPresets,
127915
127920
  valetudoIdentifier: entry.valetudoIdentifier,
127916
127921
  coverSwapOpenClose: entry.coverSwapOpenClose,
127917
127922
  coverSliderDebounceMs: entry.coverSliderDebounceMs,
@@ -131425,6 +131430,12 @@ var HomeAssistantClient = class extends Service {
131425
131430
  get connection() {
131426
131431
  return this._connection;
131427
131432
  }
131433
+ get baseUrl() {
131434
+ return this.options.url;
131435
+ }
131436
+ get accessToken() {
131437
+ return this.options.accessToken;
131438
+ }
131428
131439
  async initialize() {
131429
131440
  this._connection = await this.createConnection(this.options);
131430
131441
  }
@@ -132068,6 +132079,7 @@ var EntityMappingStorage = class extends Service {
132068
132079
  (a) => a.name?.trim() && a.service?.trim()
132069
132080
  ) ?? void 0,
132070
132081
  customFanSpeedTags: request.customFanSpeedTags && Object.keys(request.customFanSpeedTags).length > 0 ? request.customFanSpeedTags : void 0,
132082
+ fanWindPresets: request.fanWindPresets && ((request.fanWindPresets.natural?.length ?? 0) > 0 || (request.fanWindPresets.sleep?.length ?? 0) > 0) ? request.fanWindPresets : void 0,
132071
132083
  currentRoomEntity: request.currentRoomEntity?.trim() || void 0,
132072
132084
  cleanedAreaEntity: request.cleanedAreaEntity?.trim() || void 0,
132073
132085
  disableCustomAreaRoomModes: request.disableCustomAreaRoomModes || void 0,
@@ -132083,7 +132095,7 @@ var EntityMappingStorage = class extends Service {
132083
132095
  climateAutoMode: request.climateAutoMode || void 0,
132084
132096
  composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
132085
132097
  };
132086
- 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.chargingStateEntity && !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.coverExposeAsDimmableLight && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
132098
+ 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.chargingStateEntity && !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.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
132087
132099
  bridgeMap.delete(request.entityId);
132088
132100
  } else {
132089
132101
  bridgeMap.set(request.entityId, config11);
@@ -148175,6 +148187,7 @@ var PluginManager = class {
148175
148187
  domainMappingOwners = /* @__PURE__ */ new Map();
148176
148188
  storageDir;
148177
148189
  bridgeId;
148190
+ homeAssistant;
148178
148191
  runner = new SafePluginRunner();
148179
148192
  registry;
148180
148193
  /** Callback invoked when a plugin registers a new device */
@@ -148183,9 +148196,10 @@ var PluginManager = class {
148183
148196
  onDeviceUnregistered;
148184
148197
  /** Callback invoked when a plugin updates device state */
148185
148198
  onDeviceStateUpdated;
148186
- constructor(bridgeId, storageDir) {
148199
+ constructor(bridgeId, storageDir, homeAssistant) {
148187
148200
  this.bridgeId = bridgeId;
148188
148201
  this.storageDir = storageDir;
148202
+ this.homeAssistant = homeAssistant;
148189
148203
  }
148190
148204
  setRegistry(registry2) {
148191
148205
  this.registry = registry2;
@@ -148271,6 +148285,7 @@ var PluginManager = class {
148271
148285
  bridgeId: this.bridgeId,
148272
148286
  storage: storage2,
148273
148287
  log: pluginLogger,
148288
+ homeAssistant: this.homeAssistant,
148274
148289
  registerDevice: async (device) => {
148275
148290
  const validationError = validatePluginDevice(device);
148276
148291
  if (validationError) {
@@ -151243,7 +151258,14 @@ function FanControlServer2(config11, defaults = {}) {
151243
151258
  }
151244
151259
 
151245
151260
  // src/matter/endpoints/legacy/fan/behaviors/fan-fan-control-server.ts
151261
+ init_home_assistant_entity_behavior();
151246
151262
  var attributes2 = (e) => e.attributes;
151263
+ var windPresets = (agent) => agent.get(HomeAssistantEntityBehavior).state.mapping?.fanWindPresets ?? {};
151264
+ var isEnglishNatural = (m) => {
151265
+ const lower = m.toLowerCase();
151266
+ return lower === "natural" || lower === "nature";
151267
+ };
151268
+ var isEnglishSleep = (m) => m.toLowerCase() === "sleep";
151247
151269
  var fanControlConfig = {
151248
151270
  getPercentage: (state) => state.state === "off" ? 0 : attributes2(state).percentage,
151249
151271
  getStepSize: (state) => attributes2(state).percentage_step,
@@ -151262,17 +151284,22 @@ var fanControlConfig = {
151262
151284
  attributes2(state).supported_features ?? 0,
151263
151285
  FanDeviceFeature.OSCILLATE
151264
151286
  ),
151265
- // Wind mode support - check if preset_modes contains natural/sleep
151266
- getWindMode: (state) => {
151267
- const mode = attributes2(state).preset_mode?.toLowerCase();
151268
- if (mode === "natural" || mode === "nature") return "natural";
151269
- if (mode === "sleep") return "sleep";
151287
+ // Wind mode support - localized presets via mapping, english as fallback
151288
+ getWindMode: (state, agent) => {
151289
+ const mode = attributes2(state).preset_mode;
151290
+ if (!mode) return void 0;
151291
+ const presets = windPresets(agent);
151292
+ if (presets.natural?.includes(mode)) return "natural";
151293
+ if (presets.sleep?.includes(mode)) return "sleep";
151294
+ if (isEnglishNatural(mode)) return "natural";
151295
+ if (isEnglishSleep(mode)) return "sleep";
151270
151296
  return void 0;
151271
151297
  },
151272
- supportsWind: (state) => {
151298
+ supportsWind: (state, agent) => {
151273
151299
  const modes = attributes2(state).preset_modes ?? [];
151300
+ const presets = windPresets(agent);
151274
151301
  return modes.some(
151275
- (m) => m.toLowerCase() === "natural" || m.toLowerCase() === "nature" || m.toLowerCase() === "sleep"
151302
+ (m) => isEnglishNatural(m) || isEnglishSleep(m) || !!presets.natural?.includes(m) || !!presets.sleep?.includes(m)
151276
151303
  );
151277
151304
  },
151278
151305
  turnOff: () => ({ action: "fan.turn_off" }),
@@ -151295,12 +151322,29 @@ var fanControlConfig = {
151295
151322
  action: "fan.oscillate",
151296
151323
  data: { oscillating }
151297
151324
  }),
151298
- setWindMode: (mode) => ({
151299
- action: "fan.set_preset_mode",
151300
- data: {
151301
- preset_mode: mode === "natural" ? "Natural" : mode === "sleep" ? "Sleep" : "Normal"
151325
+ setWindMode: (mode, agent) => {
151326
+ const presets = windPresets(agent);
151327
+ let presetMode;
151328
+ if (mode === "natural") {
151329
+ presetMode = presets.natural?.[0] ?? "Natural";
151330
+ } else if (mode === "sleep") {
151331
+ presetMode = presets.sleep?.[0] ?? "Sleep";
151332
+ } else {
151333
+ const wind = /* @__PURE__ */ new Set([
151334
+ ...presets.natural ?? [],
151335
+ ...presets.sleep ?? []
151336
+ ]);
151337
+ const entityState = agent.get(HomeAssistantEntityBehavior).state.entity.state;
151338
+ const modes = attributes2(entityState).preset_modes ?? [];
151339
+ presetMode = modes.find(
151340
+ (m) => !wind.has(m) && !isEnglishNatural(m) && !isEnglishSleep(m)
151341
+ ) ?? "Normal";
151302
151342
  }
151303
- })
151343
+ return {
151344
+ action: "fan.set_preset_mode",
151345
+ data: { preset_mode: presetMode }
151346
+ };
151347
+ }
151304
151348
  };
151305
151349
  var FanFanControlServer = FanControlServer2(fanControlConfig);
151306
151350
 
@@ -155164,8 +155208,9 @@ function FanDevice2(homeAssistantEntity) {
155164
155208
  if (testBit(supportedFeatures, FanDeviceFeature.OSCILLATE)) {
155165
155209
  features3.add("Rocking");
155166
155210
  }
155211
+ const windPresets2 = homeAssistantEntity.mapping?.fanWindPresets;
155167
155212
  const hasWindModes = presetModes.some(
155168
- (m) => m.toLowerCase() === "natural" || m.toLowerCase() === "nature" || m.toLowerCase() === "sleep"
155213
+ (m) => m.toLowerCase() === "natural" || m.toLowerCase() === "nature" || m.toLowerCase() === "sleep" || !!windPresets2?.natural?.includes(m) || !!windPresets2?.sleep?.includes(m)
155169
155214
  );
155170
155215
  if (hasWindModes) {
155171
155216
  features3.add("Wind");
@@ -163180,13 +163225,14 @@ var CameraPlugin = class {
163180
163225
  haUrl: {
163181
163226
  type: "string",
163182
163227
  title: "Home Assistant URL",
163183
- description: "e.g. http://homeassistant.local:8123",
163184
- required: true
163228
+ description: "e.g. http://homeassistant.local:8123. Leave empty to use the bridge's Home Assistant connection.",
163229
+ required: false
163185
163230
  },
163186
163231
  haToken: {
163187
163232
  type: "string",
163188
163233
  title: "Long-lived access token",
163189
- required: true
163234
+ description: "Leave empty to use the bridge's Home Assistant connection.",
163235
+ required: false
163190
163236
  },
163191
163237
  cameras: {
163192
163238
  type: "string",
@@ -163201,9 +163247,11 @@ var CameraPlugin = class {
163201
163247
  const context = this.context;
163202
163248
  if (!context) return;
163203
163249
  await this.teardown();
163204
- const { haUrl, haToken, cameras } = this.config;
163250
+ const haUrl = this.config.haUrl ?? context.homeAssistant?.url;
163251
+ const haToken = this.config.haToken ?? context.homeAssistant?.accessToken;
163252
+ const cameras = this.config.cameras;
163205
163253
  if (!haUrl || !haToken) {
163206
- this.log.info("haUrl and haToken not set, no cameras exposed");
163254
+ this.log.info("no Home Assistant connection, no cameras exposed");
163207
163255
  return;
163208
163256
  }
163209
163257
  const entityIds = (cameras ?? "").split(",").map((s) => s.trim()).filter(Boolean);
@@ -166125,7 +166173,10 @@ var BridgeEnvironment = class _BridgeEnvironment extends EnvironmentBase {
166125
166173
  let pluginRegistry;
166126
166174
  let pluginInstaller;
166127
166175
  if (this.storageLocation) {
166128
- pluginManager = new PluginManager(bridgeId, this.storageLocation);
166176
+ pluginManager = new PluginManager(bridgeId, this.storageLocation, {
166177
+ url: haClient.baseUrl,
166178
+ accessToken: haClient.accessToken
166179
+ });
166129
166180
  pluginRegistry = new PluginRegistry(this.storageLocation);
166130
166181
  pluginManager.setRegistry(pluginRegistry);
166131
166182
  pluginInstaller = new PluginInstaller(this.storageLocation);