@riddix/hamh 2.1.0-alpha.748 → 2.1.0-alpha.750

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.
@@ -127010,6 +127010,7 @@ function entityMappingApi(mappingStorage) {
127010
127010
  coverSwapOpenClose: body.coverSwapOpenClose,
127011
127011
  coverExposeAsDimmableLight: body.coverExposeAsDimmableLight,
127012
127012
  coverSliderDebounceMs: body.coverSliderDebounceMs,
127013
+ updateThrottleMs: body.updateThrottleMs,
127013
127014
  disableClimateOnOff: body.disableClimateOnOff,
127014
127015
  disableClimateFanControl: body.disableClimateFanControl,
127015
127016
  climateKeepModeOnIdle: body.climateKeepModeOnIdle,
@@ -131643,6 +131644,7 @@ var EntityMappingStorage = class extends Service {
131643
131644
  coverSwapOpenClose: request.coverSwapOpenClose || void 0,
131644
131645
  coverExposeAsDimmableLight: request.coverExposeAsDimmableLight || void 0,
131645
131646
  coverSliderDebounceMs: sanitizeDebounceMs(request.coverSliderDebounceMs),
131647
+ updateThrottleMs: sanitizeThrottleMs(request.updateThrottleMs),
131646
131648
  disableClimateOnOff: request.disableClimateOnOff || void 0,
131647
131649
  disableClimateFanControl: request.disableClimateFanControl || void 0,
131648
131650
  climateKeepModeOnIdle: request.climateKeepModeOnIdle || void 0,
@@ -131650,7 +131652,7 @@ var EntityMappingStorage = class extends Service {
131650
131652
  climateAutoMode: request.climateAutoMode || void 0,
131651
131653
  composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
131652
131654
  };
131653
- 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.coverExposeAsDimmableLight && !config11.coverSliderDebounceMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
131655
+ 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.coverExposeAsDimmableLight && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
131654
131656
  bridgeMap.delete(request.entityId);
131655
131657
  } else {
131656
131658
  bridgeMap.set(request.entityId, config11);
@@ -131690,6 +131692,16 @@ function sanitizeDebounceMs(value) {
131690
131692
  }
131691
131693
  return Math.min(5e3, Math.round(n));
131692
131694
  }
131695
+ function sanitizeThrottleMs(value) {
131696
+ if (value === void 0 || value === null || value === "") {
131697
+ return void 0;
131698
+ }
131699
+ const n = typeof value === "string" ? Number(value) : value;
131700
+ if (typeof n !== "number" || !Number.isFinite(n) || n <= 0) {
131701
+ return void 0;
131702
+ }
131703
+ return Math.min(6e4, Math.round(n));
131704
+ }
131693
131705
 
131694
131706
  // src/services/storage/lock-credential-storage.ts
131695
131707
  init_service();
@@ -149079,10 +149091,54 @@ var AggregatorEndpoint2 = class extends Endpoint {
149079
149091
  // src/matter/endpoints/legacy/legacy-endpoint.ts
149080
149092
  init_dist();
149081
149093
  init_esm();
149082
- init_home_assistant_entity_behavior();
149083
149094
  import debounce6 from "debounce";
149084
149095
  import { isEqual } from "lodash-es";
149085
149096
 
149097
+ // src/utils/throttle-latest.ts
149098
+ function throttleLatest(fn, intervalMs) {
149099
+ let lastRun = Number.NEGATIVE_INFINITY;
149100
+ let timer;
149101
+ let pending;
149102
+ const run = (args) => {
149103
+ lastRun = Date.now();
149104
+ fn(...args);
149105
+ };
149106
+ const throttled = ((...args) => {
149107
+ const elapsed = Date.now() - lastRun;
149108
+ if (elapsed >= intervalMs) {
149109
+ if (timer) {
149110
+ clearTimeout(timer);
149111
+ timer = void 0;
149112
+ }
149113
+ pending = void 0;
149114
+ run(args);
149115
+ return;
149116
+ }
149117
+ pending = args;
149118
+ if (!timer) {
149119
+ timer = setTimeout(() => {
149120
+ timer = void 0;
149121
+ if (pending) {
149122
+ const next = pending;
149123
+ pending = void 0;
149124
+ run(next);
149125
+ }
149126
+ }, intervalMs - elapsed);
149127
+ }
149128
+ });
149129
+ throttled.clear = () => {
149130
+ if (timer) {
149131
+ clearTimeout(timer);
149132
+ timer = void 0;
149133
+ }
149134
+ pending = void 0;
149135
+ };
149136
+ return throttled;
149137
+ }
149138
+
149139
+ // src/matter/endpoints/legacy/legacy-endpoint.ts
149140
+ init_home_assistant_entity_behavior();
149141
+
149086
149142
  // src/matter/endpoints/entity-endpoint.ts
149087
149143
  init_esm7();
149088
149144
  var EntityEndpoint = class extends Endpoint {
@@ -160183,29 +160239,26 @@ var VacuumOnOffServer = OnOffServer2({
160183
160239
 
160184
160240
  // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-power-source-server.ts
160185
160241
  init_dist();
160242
+
160243
+ // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-battery.ts
160186
160244
  init_home_assistant_entity_behavior();
160245
+ function getVacuumBatteryPercent(entity, agent) {
160246
+ const mapped = agent.get(HomeAssistantEntityBehavior).state.mapping?.batteryEntity;
160247
+ if (mapped) {
160248
+ const battery = agent.env.get(EntityStateProvider).getBatteryPercent(mapped);
160249
+ if (battery != null) return Math.max(0, Math.min(100, battery));
160250
+ }
160251
+ const attrs = entity.attributes;
160252
+ const raw = attrs.battery_level ?? attrs.battery;
160253
+ if (raw == null) return null;
160254
+ if (typeof raw === "number") return raw;
160255
+ const parsed = Number.parseFloat(String(raw));
160256
+ return Number.isNaN(parsed) ? null : parsed;
160257
+ }
160258
+
160259
+ // src/matter/endpoints/legacy/vacuum/behaviors/vacuum-power-source-server.ts
160187
160260
  var VacuumPowerSourceServer = PowerSourceServer2({
160188
- getBatteryPercent(entity, agent) {
160189
- const homeAssistant = agent.get(HomeAssistantEntityBehavior);
160190
- const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
160191
- if (batteryEntity) {
160192
- const stateProvider = agent.env.get(EntityStateProvider);
160193
- const battery = stateProvider.getBatteryPercent(batteryEntity);
160194
- if (battery != null) {
160195
- return Math.max(0, Math.min(100, battery));
160196
- }
160197
- }
160198
- const attributes9 = entity.attributes;
160199
- const batteryLevel = attributes9.battery_level ?? attributes9.battery;
160200
- if (batteryLevel == null) {
160201
- return null;
160202
- }
160203
- if (typeof batteryLevel === "number") {
160204
- return batteryLevel;
160205
- }
160206
- const parsed = Number.parseFloat(String(batteryLevel));
160207
- return Number.isNaN(parsed) ? null : parsed;
160208
- },
160261
+ getBatteryPercent: getVacuumBatteryPercent,
160209
160262
  isCharging(entity) {
160210
160263
  const state = entity.state;
160211
160264
  return state === VacuumState.docked;
@@ -160934,19 +160987,31 @@ init_dist();
160934
160987
  init_esm();
160935
160988
  init_home_assistant_entity_behavior();
160936
160989
  var logger225 = Logger.get("VacuumRvcOperationalStateServer");
160990
+ function batteryFromAttributes(attrs) {
160991
+ const raw = attrs.battery_level ?? attrs.battery;
160992
+ if (raw == null) return null;
160993
+ const n = typeof raw === "number" ? raw : Number.parseFloat(String(raw));
160994
+ return Number.isFinite(n) ? n : null;
160995
+ }
160937
160996
  function isCharging(entity) {
160938
160997
  const attrs = entity.attributes;
160939
160998
  if (attrs.is_charging === true || attrs.charging === true) return true;
160940
160999
  if (attrs.is_charging === false || attrs.charging === false) return false;
160941
- const raw = attrs.battery_level ?? attrs.battery;
160942
- const level = typeof raw === "number" ? raw : Number.parseFloat(String(raw ?? ""));
160943
- if (Number.isFinite(level) && level >= 100) return false;
161000
+ const level = batteryFromAttributes(entity.attributes);
161001
+ if (level != null && level >= 100) return false;
160944
161002
  if (attrs.battery_icon?.includes("charging")) return true;
160945
161003
  if (typeof attrs.status === "string" && attrs.status.toLowerCase().includes("charg"))
160946
161004
  return true;
160947
161005
  return false;
160948
161006
  }
160949
- function mapVacuumOperationalState(entity) {
161007
+ function isDockedCharging(entity, batteryPercent) {
161008
+ const attrs = entity.attributes;
161009
+ if (attrs.is_charging === true || attrs.charging === true) return true;
161010
+ if (attrs.is_charging === false || attrs.charging === false) return false;
161011
+ if (batteryPercent != null) return batteryPercent < 100;
161012
+ return isCharging(entity);
161013
+ }
161014
+ function mapVacuumOperationalState(entity, batteryPercent = batteryFromAttributes(entity.attributes)) {
160950
161015
  const state = entity.state;
160951
161016
  const cleaningStates = [
160952
161017
  VacuumState.cleaning,
@@ -160957,7 +161022,7 @@ function mapVacuumOperationalState(entity) {
160957
161022
  ];
160958
161023
  let operationalState;
160959
161024
  if (state === VacuumState.docked) {
160960
- if (isCharging(entity)) {
161025
+ if (isDockedCharging(entity, batteryPercent)) {
160961
161026
  operationalState = RvcOperationalState4.OperationalState.Charging;
160962
161027
  } else {
160963
161028
  operationalState = RvcOperationalState4.OperationalState.Docked;
@@ -160993,8 +161058,11 @@ function mapVacuumOperationalState(entity) {
160993
161058
  return operationalState;
160994
161059
  }
160995
161060
  var VacuumRvcOperationalStateServer = RvcOperationalStateServer2({
160996
- getOperationalState(entity) {
160997
- return mapVacuumOperationalState(entity);
161061
+ getOperationalState(entity, agent) {
161062
+ return mapVacuumOperationalState(
161063
+ entity,
161064
+ getVacuumBatteryPercent(entity, agent)
161065
+ );
160998
161066
  },
160999
161067
  pause: (_, agent) => {
161000
161068
  const supportedFeatures = agent.get(HomeAssistantEntityBehavior).entity.state.attributes.supported_features ?? 0;
@@ -162034,11 +162102,17 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
162034
162102
  }
162035
162103
  const customName = effectiveMapping?.customName;
162036
162104
  const mappedIds = getMappedEntityIds(effectiveMapping);
162037
- return new _LegacyEndpoint(type, entityId, customName, mappedIds);
162105
+ return new _LegacyEndpoint(
162106
+ type,
162107
+ entityId,
162108
+ customName,
162109
+ mappedIds,
162110
+ effectiveMapping?.updateThrottleMs
162111
+ );
162038
162112
  }
162039
- constructor(type, entityId, customName, mappedEntityIds) {
162113
+ constructor(type, entityId, customName, mappedEntityIds, throttleMs) {
162040
162114
  super(type, entityId, customName, mappedEntityIds);
162041
- this.flushUpdate = debounce6(this.flushPendingUpdate.bind(this), 50);
162115
+ this.flushUpdate = throttleMs && throttleMs > 50 ? throttleLatest(this.flushPendingUpdate.bind(this), throttleMs) : debounce6(this.flushPendingUpdate.bind(this), 50);
162042
162116
  }
162043
162117
  lastState;
162044
162118
  pendingMappedChange = false;