@riddix/hamh 2.1.0-alpha.451 → 2.1.0-alpha.453
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/dist/backend/cli.js
CHANGED
|
@@ -146589,6 +146589,11 @@ var init_bridge_config_schema = __esm({
|
|
|
146589
146589
|
title: "platform",
|
|
146590
146590
|
description: "Match entities by their integration/platform. Example: 'hue', 'zwave', 'mqtt'."
|
|
146591
146591
|
},
|
|
146592
|
+
{
|
|
146593
|
+
const: "label",
|
|
146594
|
+
title: "label (deprecated)",
|
|
146595
|
+
description: "Deprecated: use entity_label or device_label instead. Behaves like entity_label."
|
|
146596
|
+
},
|
|
146592
146597
|
{
|
|
146593
146598
|
const: "entity_label",
|
|
146594
146599
|
title: "entity_label",
|
|
@@ -165874,10 +165879,254 @@ function transactionIsOffline(context) {
|
|
|
165874
165879
|
|
|
165875
165880
|
// src/matter/behaviors/fan-control-server.ts
|
|
165876
165881
|
init_home_assistant_entity_behavior();
|
|
165882
|
+
|
|
165883
|
+
// src/matter/behaviors/on-off-server.ts
|
|
165884
|
+
init_esm();
|
|
165885
|
+
init_home_assistant_entity_behavior();
|
|
165886
|
+
|
|
165887
|
+
// src/matter/behaviors/level-control-server.ts
|
|
165888
|
+
init_esm();
|
|
165889
|
+
init_home_assistant_entity_behavior();
|
|
165890
|
+
var lastTurnOnTimestamps = /* @__PURE__ */ new Map();
|
|
165891
|
+
var optimisticLevelState = /* @__PURE__ */ new Map();
|
|
165892
|
+
var OPTIMISTIC_TIMEOUT_MS = 3e3;
|
|
165893
|
+
var OPTIMISTIC_TOLERANCE = 5;
|
|
165894
|
+
function notifyLightTurnedOn(entityId) {
|
|
165895
|
+
lastTurnOnTimestamps.set(entityId, Date.now());
|
|
165896
|
+
}
|
|
165897
|
+
var logger158 = Logger.get("LevelControlServer");
|
|
165898
|
+
var FeaturedBase3 = LevelControlServer.with("OnOff", "Lighting");
|
|
165899
|
+
var LevelControlServerBase = class extends FeaturedBase3 {
|
|
165900
|
+
pendingTransitionTime;
|
|
165901
|
+
async initialize() {
|
|
165902
|
+
if (this.state.currentLevel == null) {
|
|
165903
|
+
this.state.currentLevel = 1;
|
|
165904
|
+
}
|
|
165905
|
+
if (this.state.minLevel == null) {
|
|
165906
|
+
this.state.minLevel = 1;
|
|
165907
|
+
}
|
|
165908
|
+
if (this.state.maxLevel == null) {
|
|
165909
|
+
this.state.maxLevel = 254;
|
|
165910
|
+
}
|
|
165911
|
+
this.state.onLevel = null;
|
|
165912
|
+
logger158.debug(`initialize: calling super.initialize()`);
|
|
165913
|
+
try {
|
|
165914
|
+
await super.initialize();
|
|
165915
|
+
logger158.debug(`initialize: super.initialize() completed successfully`);
|
|
165916
|
+
} catch (error) {
|
|
165917
|
+
logger158.error(`initialize: super.initialize() FAILED:`, error);
|
|
165918
|
+
throw error;
|
|
165919
|
+
}
|
|
165920
|
+
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
165921
|
+
this.update(homeAssistant.entity);
|
|
165922
|
+
this.reactTo(homeAssistant.onChange, this.update);
|
|
165923
|
+
}
|
|
165924
|
+
update(entity) {
|
|
165925
|
+
if (!entity.state) {
|
|
165926
|
+
return;
|
|
165927
|
+
}
|
|
165928
|
+
const { state } = entity;
|
|
165929
|
+
const config10 = this.state.config;
|
|
165930
|
+
const minLevel = 1;
|
|
165931
|
+
const maxLevel = 254;
|
|
165932
|
+
const levelRange = maxLevel - minLevel;
|
|
165933
|
+
const currentLevelPercent = config10.getValuePercent(state, this.agent);
|
|
165934
|
+
let currentLevel = currentLevelPercent != null ? Math.round(currentLevelPercent * levelRange + minLevel) : null;
|
|
165935
|
+
if (currentLevel != null) {
|
|
165936
|
+
currentLevel = Math.min(Math.max(minLevel, currentLevel), maxLevel);
|
|
165937
|
+
}
|
|
165938
|
+
const optimistic = optimisticLevelState.get(entity.entity_id);
|
|
165939
|
+
if (optimistic != null && currentLevel != null) {
|
|
165940
|
+
if (Date.now() - optimistic.timestamp > OPTIMISTIC_TIMEOUT_MS) {
|
|
165941
|
+
optimisticLevelState.delete(entity.entity_id);
|
|
165942
|
+
} else if (Math.abs(currentLevel - optimistic.expectedLevel) <= OPTIMISTIC_TOLERANCE) {
|
|
165943
|
+
optimisticLevelState.delete(entity.entity_id);
|
|
165944
|
+
} else {
|
|
165945
|
+
currentLevel = null;
|
|
165946
|
+
}
|
|
165947
|
+
}
|
|
165948
|
+
applyPatchState(this.state, {
|
|
165949
|
+
minLevel,
|
|
165950
|
+
maxLevel,
|
|
165951
|
+
...currentLevel != null ? { currentLevel } : {}
|
|
165952
|
+
});
|
|
165953
|
+
}
|
|
165954
|
+
// Fix for Google Home (#41): it sends moveToLevel/moveToLevelWithOnOff/step commands
|
|
165955
|
+
// with transitionTime as null or completely omitted. The TLV schema is patched at startup
|
|
165956
|
+
// (see patch-level-control-tlv.ts) to accept omitted fields. Here we default to 0 (instant).
|
|
165957
|
+
async moveToLevel(request) {
|
|
165958
|
+
if (request.transitionTime == null) {
|
|
165959
|
+
request.transitionTime = 0;
|
|
165960
|
+
}
|
|
165961
|
+
this.pendingTransitionTime = request.transitionTime;
|
|
165962
|
+
return super.moveToLevel(request);
|
|
165963
|
+
}
|
|
165964
|
+
async moveToLevelWithOnOff(request) {
|
|
165965
|
+
if (request.transitionTime == null) {
|
|
165966
|
+
request.transitionTime = 0;
|
|
165967
|
+
}
|
|
165968
|
+
this.pendingTransitionTime = request.transitionTime;
|
|
165969
|
+
return super.moveToLevelWithOnOff(request);
|
|
165970
|
+
}
|
|
165971
|
+
step(request) {
|
|
165972
|
+
if (request.transitionTime == null) {
|
|
165973
|
+
request.transitionTime = 0;
|
|
165974
|
+
}
|
|
165975
|
+
return super.step(request);
|
|
165976
|
+
}
|
|
165977
|
+
stepWithOnOff(request) {
|
|
165978
|
+
if (request.transitionTime == null) {
|
|
165979
|
+
request.transitionTime = 0;
|
|
165980
|
+
}
|
|
165981
|
+
return super.stepWithOnOff(request);
|
|
165982
|
+
}
|
|
165983
|
+
moveToLevelLogic(level) {
|
|
165984
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
165985
|
+
const config10 = this.state.config;
|
|
165986
|
+
const entityId = homeAssistant.entity.entity_id;
|
|
165987
|
+
const levelRange = this.maxLevel - this.minLevel;
|
|
165988
|
+
const levelPercent = (level - this.minLevel) / levelRange;
|
|
165989
|
+
const lastTurnOn = lastTurnOnTimestamps.get(entityId);
|
|
165990
|
+
const timeSinceTurnOn = lastTurnOn ? Date.now() - lastTurnOn : Infinity;
|
|
165991
|
+
const isMaxBrightness = level >= this.maxLevel;
|
|
165992
|
+
if (isMaxBrightness && timeSinceTurnOn < 200) {
|
|
165993
|
+
logger158.debug(
|
|
165994
|
+
`[${entityId}] Ignoring moveToLevel(${level}) - Alexa brightness reset detected (${timeSinceTurnOn}ms after turn-on)`
|
|
165995
|
+
);
|
|
165996
|
+
return;
|
|
165997
|
+
}
|
|
165998
|
+
const current = config10.getValuePercent(
|
|
165999
|
+
homeAssistant.entity.state,
|
|
166000
|
+
this.agent
|
|
166001
|
+
);
|
|
166002
|
+
if (levelPercent === current) {
|
|
166003
|
+
return;
|
|
166004
|
+
}
|
|
166005
|
+
const action = config10.moveToLevelPercent(levelPercent, this.agent);
|
|
166006
|
+
const transitionTimeTenths = this.pendingTransitionTime;
|
|
166007
|
+
this.pendingTransitionTime = void 0;
|
|
166008
|
+
if (transitionTimeTenths && transitionTimeTenths > 0) {
|
|
166009
|
+
action.data = {
|
|
166010
|
+
...action.data,
|
|
166011
|
+
transition: transitionTimeTenths / 10
|
|
166012
|
+
};
|
|
166013
|
+
}
|
|
166014
|
+
this.state.currentLevel = level;
|
|
166015
|
+
optimisticLevelState.set(entityId, {
|
|
166016
|
+
expectedLevel: level,
|
|
166017
|
+
timestamp: Date.now()
|
|
166018
|
+
});
|
|
166019
|
+
homeAssistant.callAction(action);
|
|
166020
|
+
}
|
|
166021
|
+
};
|
|
166022
|
+
((LevelControlServerBase2) => {
|
|
166023
|
+
class State extends FeaturedBase3.State {
|
|
166024
|
+
config;
|
|
166025
|
+
}
|
|
166026
|
+
LevelControlServerBase2.State = State;
|
|
166027
|
+
})(LevelControlServerBase || (LevelControlServerBase = {}));
|
|
166028
|
+
function LevelControlServer2(config10) {
|
|
166029
|
+
return LevelControlServerBase.set({
|
|
166030
|
+
options: { executeIfOff: true },
|
|
166031
|
+
config: config10
|
|
166032
|
+
});
|
|
166033
|
+
}
|
|
166034
|
+
|
|
166035
|
+
// src/matter/behaviors/on-off-server.ts
|
|
166036
|
+
var logger159 = Logger.get("OnOffServer");
|
|
166037
|
+
var optimisticOnOffState = /* @__PURE__ */ new Map();
|
|
166038
|
+
var OPTIMISTIC_TIMEOUT_MS2 = 3e3;
|
|
166039
|
+
var OnOffServerBase = class extends OnOffServer {
|
|
166040
|
+
async initialize() {
|
|
166041
|
+
await super.initialize();
|
|
166042
|
+
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
166043
|
+
this.update(homeAssistant.entity);
|
|
166044
|
+
this.reactTo(homeAssistant.onChange, this.update);
|
|
166045
|
+
}
|
|
166046
|
+
update({ state }) {
|
|
166047
|
+
const onOff = this.isOn(state);
|
|
166048
|
+
const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
|
|
166049
|
+
const optimistic = optimisticOnOffState.get(entityId);
|
|
166050
|
+
if (optimistic != null) {
|
|
166051
|
+
if (Date.now() - optimistic.timestamp > OPTIMISTIC_TIMEOUT_MS2) {
|
|
166052
|
+
optimisticOnOffState.delete(entityId);
|
|
166053
|
+
} else if (onOff === optimistic.expectedOnOff) {
|
|
166054
|
+
optimisticOnOffState.delete(entityId);
|
|
166055
|
+
} else {
|
|
166056
|
+
return;
|
|
166057
|
+
}
|
|
166058
|
+
}
|
|
166059
|
+
applyPatchState(this.state, { onOff });
|
|
166060
|
+
}
|
|
166061
|
+
isOn(entity) {
|
|
166062
|
+
return this.state.config?.isOn?.(entity, this.agent) ?? (this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state !== "off");
|
|
166063
|
+
}
|
|
166064
|
+
on() {
|
|
166065
|
+
const { turnOn, turnOff } = this.state.config;
|
|
166066
|
+
if (turnOn === null) {
|
|
166067
|
+
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166068
|
+
return;
|
|
166069
|
+
}
|
|
166070
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166071
|
+
const action = turnOn?.(void 0, this.agent) ?? {
|
|
166072
|
+
action: "homeassistant.turn_on"
|
|
166073
|
+
};
|
|
166074
|
+
logger159.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
|
|
166075
|
+
notifyLightTurnedOn(homeAssistant.entityId);
|
|
166076
|
+
applyPatchState(this.state, { onOff: true });
|
|
166077
|
+
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
166078
|
+
expectedOnOff: true,
|
|
166079
|
+
timestamp: Date.now()
|
|
166080
|
+
});
|
|
166081
|
+
homeAssistant.callAction(action);
|
|
166082
|
+
if (turnOff === null) {
|
|
166083
|
+
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166084
|
+
}
|
|
166085
|
+
}
|
|
166086
|
+
off() {
|
|
166087
|
+
const { turnOff } = this.state.config;
|
|
166088
|
+
if (turnOff === null) {
|
|
166089
|
+
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166090
|
+
return;
|
|
166091
|
+
}
|
|
166092
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166093
|
+
const action = turnOff?.(void 0, this.agent) ?? {
|
|
166094
|
+
action: "homeassistant.turn_off"
|
|
166095
|
+
};
|
|
166096
|
+
logger159.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
|
|
166097
|
+
applyPatchState(this.state, { onOff: false });
|
|
166098
|
+
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
166099
|
+
expectedOnOff: false,
|
|
166100
|
+
timestamp: Date.now()
|
|
166101
|
+
});
|
|
166102
|
+
homeAssistant.callAction(action);
|
|
166103
|
+
}
|
|
166104
|
+
autoReset() {
|
|
166105
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166106
|
+
this.update(homeAssistant.entity);
|
|
166107
|
+
}
|
|
166108
|
+
};
|
|
166109
|
+
((OnOffServerBase2) => {
|
|
166110
|
+
class State extends OnOffServer.State {
|
|
166111
|
+
config;
|
|
166112
|
+
}
|
|
166113
|
+
OnOffServerBase2.State = State;
|
|
166114
|
+
})(OnOffServerBase || (OnOffServerBase = {}));
|
|
166115
|
+
function OnOffServer2(config10 = {}) {
|
|
166116
|
+
return OnOffServerBase.set({ config: config10 });
|
|
166117
|
+
}
|
|
166118
|
+
function setOptimisticOnOff(entityId, expectedOnOff) {
|
|
166119
|
+
optimisticOnOffState.set(entityId, {
|
|
166120
|
+
expectedOnOff,
|
|
166121
|
+
timestamp: Date.now()
|
|
166122
|
+
});
|
|
166123
|
+
}
|
|
166124
|
+
|
|
166125
|
+
// src/matter/behaviors/fan-control-server.ts
|
|
165877
166126
|
var defaultStepSize = 33.33;
|
|
165878
166127
|
var minSpeedMax = 3;
|
|
165879
166128
|
var maxSpeedMax = 100;
|
|
165880
|
-
var
|
|
166129
|
+
var FeaturedBase4 = FanControlServer.with(
|
|
165881
166130
|
"Step",
|
|
165882
166131
|
"MultiSpeed",
|
|
165883
166132
|
"AirflowDirection",
|
|
@@ -165891,7 +166140,7 @@ var FeaturedBase3 = FanControlServer.with(
|
|
|
165891
166140
|
rockSupport: { rockUpDown: true },
|
|
165892
166141
|
windSupport: { naturalWind: true, sleepWind: true }
|
|
165893
166142
|
});
|
|
165894
|
-
var FanControlServerBase = class extends
|
|
166143
|
+
var FanControlServerBase = class extends FeaturedBase4 {
|
|
165895
166144
|
async initialize() {
|
|
165896
166145
|
if (this.features.multiSpeed) {
|
|
165897
166146
|
if (this.state.speedMax == null || this.state.speedMax < minSpeedMax) {
|
|
@@ -166024,6 +166273,7 @@ var FanControlServerBase = class extends FeaturedBase3 {
|
|
|
166024
166273
|
if (!homeAssistant.isAvailable) {
|
|
166025
166274
|
return;
|
|
166026
166275
|
}
|
|
166276
|
+
this.syncOnOff(percentSetting !== 0);
|
|
166027
166277
|
if (percentSetting === 0) {
|
|
166028
166278
|
homeAssistant.callAction(this.state.config.turnOff(void 0, this.agent));
|
|
166029
166279
|
} else {
|
|
@@ -166064,6 +166314,7 @@ var FanControlServerBase = class extends FeaturedBase3 {
|
|
|
166064
166314
|
}
|
|
166065
166315
|
const targetFanMode = FanMode.create(fanMode, this.state.fanModeSequence);
|
|
166066
166316
|
if (targetFanMode.mode === FanControl3.FanMode.Auto) {
|
|
166317
|
+
this.syncOnOff(true);
|
|
166067
166318
|
homeAssistant.callAction(
|
|
166068
166319
|
this.state.config.setAutoMode(void 0, this.agent)
|
|
166069
166320
|
);
|
|
@@ -166093,6 +166344,7 @@ var FanControlServerBase = class extends FeaturedBase3 {
|
|
|
166093
166344
|
homeAssistant.entity.state,
|
|
166094
166345
|
this.agent
|
|
166095
166346
|
);
|
|
166347
|
+
this.syncOnOff(percentage !== 0);
|
|
166096
166348
|
if (percentage === 0) {
|
|
166097
166349
|
homeAssistant.callAction(config10.turnOff(void 0, this.agent));
|
|
166098
166350
|
} else if (supportsPercentage) {
|
|
@@ -166177,6 +166429,18 @@ var FanControlServerBase = class extends FeaturedBase3 {
|
|
|
166177
166429
|
homeAssistant.callAction(this.state.config.setWindMode(mode, this.agent));
|
|
166178
166430
|
});
|
|
166179
166431
|
}
|
|
166432
|
+
// Cross-cluster sync: keep OnOff in sync with FanControl per Matter spec
|
|
166433
|
+
// §4.4.6.6.1. matter.js does not implement this automatically.
|
|
166434
|
+
syncOnOff(on) {
|
|
166435
|
+
try {
|
|
166436
|
+
if (!this.agent.has(OnOffBehavior)) return;
|
|
166437
|
+
const onOffState = this.agent.get(OnOffBehavior).state;
|
|
166438
|
+
applyPatchState(onOffState, { onOff: on });
|
|
166439
|
+
const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
|
|
166440
|
+
setOptimisticOnOff(entityId, on);
|
|
166441
|
+
} catch {
|
|
166442
|
+
}
|
|
166443
|
+
}
|
|
166180
166444
|
mapWindModeToSetting(mode) {
|
|
166181
166445
|
return {
|
|
166182
166446
|
naturalWind: mode === "natural",
|
|
@@ -166185,7 +166449,7 @@ var FanControlServerBase = class extends FeaturedBase3 {
|
|
|
166185
166449
|
}
|
|
166186
166450
|
};
|
|
166187
166451
|
((FanControlServerBase2) => {
|
|
166188
|
-
class State extends
|
|
166452
|
+
class State extends FeaturedBase4.State {
|
|
166189
166453
|
config;
|
|
166190
166454
|
}
|
|
166191
166455
|
FanControlServerBase2.State = State;
|
|
@@ -166253,242 +166517,6 @@ var fanControlConfig = {
|
|
|
166253
166517
|
};
|
|
166254
166518
|
var FanFanControlServer = FanControlServer2(fanControlConfig);
|
|
166255
166519
|
|
|
166256
|
-
// src/matter/behaviors/on-off-server.ts
|
|
166257
|
-
init_esm();
|
|
166258
|
-
init_home_assistant_entity_behavior();
|
|
166259
|
-
|
|
166260
|
-
// src/matter/behaviors/level-control-server.ts
|
|
166261
|
-
init_esm();
|
|
166262
|
-
init_home_assistant_entity_behavior();
|
|
166263
|
-
var lastTurnOnTimestamps = /* @__PURE__ */ new Map();
|
|
166264
|
-
var optimisticLevelState = /* @__PURE__ */ new Map();
|
|
166265
|
-
var OPTIMISTIC_TIMEOUT_MS = 3e3;
|
|
166266
|
-
var OPTIMISTIC_TOLERANCE = 5;
|
|
166267
|
-
function notifyLightTurnedOn(entityId) {
|
|
166268
|
-
lastTurnOnTimestamps.set(entityId, Date.now());
|
|
166269
|
-
}
|
|
166270
|
-
var logger158 = Logger.get("LevelControlServer");
|
|
166271
|
-
var FeaturedBase4 = LevelControlServer.with("OnOff", "Lighting");
|
|
166272
|
-
var LevelControlServerBase = class extends FeaturedBase4 {
|
|
166273
|
-
pendingTransitionTime;
|
|
166274
|
-
async initialize() {
|
|
166275
|
-
if (this.state.currentLevel == null) {
|
|
166276
|
-
this.state.currentLevel = 1;
|
|
166277
|
-
}
|
|
166278
|
-
if (this.state.minLevel == null) {
|
|
166279
|
-
this.state.minLevel = 1;
|
|
166280
|
-
}
|
|
166281
|
-
if (this.state.maxLevel == null) {
|
|
166282
|
-
this.state.maxLevel = 254;
|
|
166283
|
-
}
|
|
166284
|
-
this.state.onLevel = null;
|
|
166285
|
-
logger158.debug(`initialize: calling super.initialize()`);
|
|
166286
|
-
try {
|
|
166287
|
-
await super.initialize();
|
|
166288
|
-
logger158.debug(`initialize: super.initialize() completed successfully`);
|
|
166289
|
-
} catch (error) {
|
|
166290
|
-
logger158.error(`initialize: super.initialize() FAILED:`, error);
|
|
166291
|
-
throw error;
|
|
166292
|
-
}
|
|
166293
|
-
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
166294
|
-
this.update(homeAssistant.entity);
|
|
166295
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
166296
|
-
}
|
|
166297
|
-
update(entity) {
|
|
166298
|
-
if (!entity.state) {
|
|
166299
|
-
return;
|
|
166300
|
-
}
|
|
166301
|
-
const { state } = entity;
|
|
166302
|
-
const config10 = this.state.config;
|
|
166303
|
-
const minLevel = 1;
|
|
166304
|
-
const maxLevel = 254;
|
|
166305
|
-
const levelRange = maxLevel - minLevel;
|
|
166306
|
-
const currentLevelPercent = config10.getValuePercent(state, this.agent);
|
|
166307
|
-
let currentLevel = currentLevelPercent != null ? Math.round(currentLevelPercent * levelRange + minLevel) : null;
|
|
166308
|
-
if (currentLevel != null) {
|
|
166309
|
-
currentLevel = Math.min(Math.max(minLevel, currentLevel), maxLevel);
|
|
166310
|
-
}
|
|
166311
|
-
const optimistic = optimisticLevelState.get(entity.entity_id);
|
|
166312
|
-
if (optimistic != null && currentLevel != null) {
|
|
166313
|
-
if (Date.now() - optimistic.timestamp > OPTIMISTIC_TIMEOUT_MS) {
|
|
166314
|
-
optimisticLevelState.delete(entity.entity_id);
|
|
166315
|
-
} else if (Math.abs(currentLevel - optimistic.expectedLevel) <= OPTIMISTIC_TOLERANCE) {
|
|
166316
|
-
optimisticLevelState.delete(entity.entity_id);
|
|
166317
|
-
} else {
|
|
166318
|
-
currentLevel = null;
|
|
166319
|
-
}
|
|
166320
|
-
}
|
|
166321
|
-
applyPatchState(this.state, {
|
|
166322
|
-
minLevel,
|
|
166323
|
-
maxLevel,
|
|
166324
|
-
...currentLevel != null ? { currentLevel } : {}
|
|
166325
|
-
});
|
|
166326
|
-
}
|
|
166327
|
-
// Fix for Google Home (#41): it sends moveToLevel/moveToLevelWithOnOff/step commands
|
|
166328
|
-
// with transitionTime as null or completely omitted. The TLV schema is patched at startup
|
|
166329
|
-
// (see patch-level-control-tlv.ts) to accept omitted fields. Here we default to 0 (instant).
|
|
166330
|
-
async moveToLevel(request) {
|
|
166331
|
-
if (request.transitionTime == null) {
|
|
166332
|
-
request.transitionTime = 0;
|
|
166333
|
-
}
|
|
166334
|
-
this.pendingTransitionTime = request.transitionTime;
|
|
166335
|
-
return super.moveToLevel(request);
|
|
166336
|
-
}
|
|
166337
|
-
async moveToLevelWithOnOff(request) {
|
|
166338
|
-
if (request.transitionTime == null) {
|
|
166339
|
-
request.transitionTime = 0;
|
|
166340
|
-
}
|
|
166341
|
-
this.pendingTransitionTime = request.transitionTime;
|
|
166342
|
-
return super.moveToLevelWithOnOff(request);
|
|
166343
|
-
}
|
|
166344
|
-
step(request) {
|
|
166345
|
-
if (request.transitionTime == null) {
|
|
166346
|
-
request.transitionTime = 0;
|
|
166347
|
-
}
|
|
166348
|
-
return super.step(request);
|
|
166349
|
-
}
|
|
166350
|
-
stepWithOnOff(request) {
|
|
166351
|
-
if (request.transitionTime == null) {
|
|
166352
|
-
request.transitionTime = 0;
|
|
166353
|
-
}
|
|
166354
|
-
return super.stepWithOnOff(request);
|
|
166355
|
-
}
|
|
166356
|
-
moveToLevelLogic(level) {
|
|
166357
|
-
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166358
|
-
const config10 = this.state.config;
|
|
166359
|
-
const entityId = homeAssistant.entity.entity_id;
|
|
166360
|
-
const levelRange = this.maxLevel - this.minLevel;
|
|
166361
|
-
const levelPercent = (level - this.minLevel) / levelRange;
|
|
166362
|
-
const lastTurnOn = lastTurnOnTimestamps.get(entityId);
|
|
166363
|
-
const timeSinceTurnOn = lastTurnOn ? Date.now() - lastTurnOn : Infinity;
|
|
166364
|
-
const isMaxBrightness = level >= this.maxLevel;
|
|
166365
|
-
if (isMaxBrightness && timeSinceTurnOn < 200) {
|
|
166366
|
-
logger158.debug(
|
|
166367
|
-
`[${entityId}] Ignoring moveToLevel(${level}) - Alexa brightness reset detected (${timeSinceTurnOn}ms after turn-on)`
|
|
166368
|
-
);
|
|
166369
|
-
return;
|
|
166370
|
-
}
|
|
166371
|
-
const current = config10.getValuePercent(
|
|
166372
|
-
homeAssistant.entity.state,
|
|
166373
|
-
this.agent
|
|
166374
|
-
);
|
|
166375
|
-
if (levelPercent === current) {
|
|
166376
|
-
return;
|
|
166377
|
-
}
|
|
166378
|
-
const action = config10.moveToLevelPercent(levelPercent, this.agent);
|
|
166379
|
-
const transitionTimeTenths = this.pendingTransitionTime;
|
|
166380
|
-
this.pendingTransitionTime = void 0;
|
|
166381
|
-
if (transitionTimeTenths && transitionTimeTenths > 0) {
|
|
166382
|
-
action.data = {
|
|
166383
|
-
...action.data,
|
|
166384
|
-
transition: transitionTimeTenths / 10
|
|
166385
|
-
};
|
|
166386
|
-
}
|
|
166387
|
-
this.state.currentLevel = level;
|
|
166388
|
-
optimisticLevelState.set(entityId, {
|
|
166389
|
-
expectedLevel: level,
|
|
166390
|
-
timestamp: Date.now()
|
|
166391
|
-
});
|
|
166392
|
-
homeAssistant.callAction(action);
|
|
166393
|
-
}
|
|
166394
|
-
};
|
|
166395
|
-
((LevelControlServerBase2) => {
|
|
166396
|
-
class State extends FeaturedBase4.State {
|
|
166397
|
-
config;
|
|
166398
|
-
}
|
|
166399
|
-
LevelControlServerBase2.State = State;
|
|
166400
|
-
})(LevelControlServerBase || (LevelControlServerBase = {}));
|
|
166401
|
-
function LevelControlServer2(config10) {
|
|
166402
|
-
return LevelControlServerBase.set({
|
|
166403
|
-
options: { executeIfOff: true },
|
|
166404
|
-
config: config10
|
|
166405
|
-
});
|
|
166406
|
-
}
|
|
166407
|
-
|
|
166408
|
-
// src/matter/behaviors/on-off-server.ts
|
|
166409
|
-
var logger159 = Logger.get("OnOffServer");
|
|
166410
|
-
var optimisticOnOffState = /* @__PURE__ */ new Map();
|
|
166411
|
-
var OPTIMISTIC_TIMEOUT_MS2 = 3e3;
|
|
166412
|
-
var OnOffServerBase = class extends OnOffServer {
|
|
166413
|
-
async initialize() {
|
|
166414
|
-
await super.initialize();
|
|
166415
|
-
const homeAssistant = await this.agent.load(HomeAssistantEntityBehavior);
|
|
166416
|
-
this.update(homeAssistant.entity);
|
|
166417
|
-
this.reactTo(homeAssistant.onChange, this.update);
|
|
166418
|
-
}
|
|
166419
|
-
update({ state }) {
|
|
166420
|
-
const onOff = this.isOn(state);
|
|
166421
|
-
const entityId = this.agent.get(HomeAssistantEntityBehavior).entity.entity_id;
|
|
166422
|
-
const optimistic = optimisticOnOffState.get(entityId);
|
|
166423
|
-
if (optimistic != null) {
|
|
166424
|
-
if (Date.now() - optimistic.timestamp > OPTIMISTIC_TIMEOUT_MS2) {
|
|
166425
|
-
optimisticOnOffState.delete(entityId);
|
|
166426
|
-
} else if (onOff === optimistic.expectedOnOff) {
|
|
166427
|
-
optimisticOnOffState.delete(entityId);
|
|
166428
|
-
} else {
|
|
166429
|
-
return;
|
|
166430
|
-
}
|
|
166431
|
-
}
|
|
166432
|
-
applyPatchState(this.state, { onOff });
|
|
166433
|
-
}
|
|
166434
|
-
isOn(entity) {
|
|
166435
|
-
return this.state.config?.isOn?.(entity, this.agent) ?? (this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state !== "off");
|
|
166436
|
-
}
|
|
166437
|
-
on() {
|
|
166438
|
-
const { turnOn, turnOff } = this.state.config;
|
|
166439
|
-
if (turnOn === null) {
|
|
166440
|
-
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166441
|
-
return;
|
|
166442
|
-
}
|
|
166443
|
-
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166444
|
-
const action = turnOn?.(void 0, this.agent) ?? {
|
|
166445
|
-
action: "homeassistant.turn_on"
|
|
166446
|
-
};
|
|
166447
|
-
logger159.info(`[${homeAssistant.entityId}] Turning ON -> ${action.action}`);
|
|
166448
|
-
notifyLightTurnedOn(homeAssistant.entityId);
|
|
166449
|
-
applyPatchState(this.state, { onOff: true });
|
|
166450
|
-
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
166451
|
-
expectedOnOff: true,
|
|
166452
|
-
timestamp: Date.now()
|
|
166453
|
-
});
|
|
166454
|
-
homeAssistant.callAction(action);
|
|
166455
|
-
if (turnOff === null) {
|
|
166456
|
-
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166457
|
-
}
|
|
166458
|
-
}
|
|
166459
|
-
off() {
|
|
166460
|
-
const { turnOff } = this.state.config;
|
|
166461
|
-
if (turnOff === null) {
|
|
166462
|
-
setTimeout(this.callback(this.autoReset), 1e3);
|
|
166463
|
-
return;
|
|
166464
|
-
}
|
|
166465
|
-
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166466
|
-
const action = turnOff?.(void 0, this.agent) ?? {
|
|
166467
|
-
action: "homeassistant.turn_off"
|
|
166468
|
-
};
|
|
166469
|
-
logger159.info(`[${homeAssistant.entityId}] Turning OFF -> ${action.action}`);
|
|
166470
|
-
applyPatchState(this.state, { onOff: false });
|
|
166471
|
-
optimisticOnOffState.set(homeAssistant.entityId, {
|
|
166472
|
-
expectedOnOff: false,
|
|
166473
|
-
timestamp: Date.now()
|
|
166474
|
-
});
|
|
166475
|
-
homeAssistant.callAction(action);
|
|
166476
|
-
}
|
|
166477
|
-
autoReset() {
|
|
166478
|
-
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
166479
|
-
this.update(homeAssistant.entity);
|
|
166480
|
-
}
|
|
166481
|
-
};
|
|
166482
|
-
((OnOffServerBase2) => {
|
|
166483
|
-
class State extends OnOffServer.State {
|
|
166484
|
-
config;
|
|
166485
|
-
}
|
|
166486
|
-
OnOffServerBase2.State = State;
|
|
166487
|
-
})(OnOffServerBase || (OnOffServerBase = {}));
|
|
166488
|
-
function OnOffServer2(config10 = {}) {
|
|
166489
|
-
return OnOffServerBase.set({ config: config10 });
|
|
166490
|
-
}
|
|
166491
|
-
|
|
166492
166520
|
// src/matter/endpoints/legacy/fan/behaviors/fan-on-off-server.ts
|
|
166493
166521
|
var FanOnOffServer = OnOffServer2({
|
|
166494
166522
|
turnOn: () => ({ action: "fan.turn_on" }),
|