@riddix/hamh 2.1.0-alpha.840 → 2.1.0-alpha.842
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
|
@@ -1767,8 +1767,8 @@ var init_Cancelable = __esm({
|
|
|
1767
1767
|
};
|
|
1768
1768
|
return result;
|
|
1769
1769
|
}
|
|
1770
|
-
static set logger(
|
|
1771
|
-
this.#logger =
|
|
1770
|
+
static set logger(logger251) {
|
|
1771
|
+
this.#logger = logger251;
|
|
1772
1772
|
}
|
|
1773
1773
|
static get logger() {
|
|
1774
1774
|
return this.#logger;
|
|
@@ -3475,13 +3475,13 @@ var init_Logger = __esm({
|
|
|
3475
3475
|
*
|
|
3476
3476
|
* @deprecated use {@link destinations}
|
|
3477
3477
|
*/
|
|
3478
|
-
static addLogger(identifier,
|
|
3478
|
+
static addLogger(identifier, logger251, options) {
|
|
3479
3479
|
if (identifier in this.destinations) {
|
|
3480
3480
|
throw new ImplementationError(`Logger "${identifier}" already exists`);
|
|
3481
3481
|
}
|
|
3482
3482
|
const dest = LogDestination({ name: identifier });
|
|
3483
3483
|
const legacy = adaptDestinationToLegacy(dest);
|
|
3484
|
-
legacy.log =
|
|
3484
|
+
legacy.log = logger251;
|
|
3485
3485
|
if (options?.defaultLogLevel !== void 0) {
|
|
3486
3486
|
legacy.defaultLogLevel = options.defaultLogLevel;
|
|
3487
3487
|
}
|
|
@@ -5687,8 +5687,8 @@ var init_Construction = __esm({
|
|
|
5687
5687
|
}
|
|
5688
5688
|
}
|
|
5689
5689
|
#unhandledError(...args) {
|
|
5690
|
-
const
|
|
5691
|
-
|
|
5690
|
+
const logger251 = Logger.get(this.#subject.constructor.name);
|
|
5691
|
+
logger251.error(...args);
|
|
5692
5692
|
}
|
|
5693
5693
|
#createErrorHandler(name) {
|
|
5694
5694
|
return (e) => {
|
|
@@ -11712,18 +11712,18 @@ var init_FileHandleTracker = __esm({
|
|
|
11712
11712
|
logger12 = Logger.get("FileHandleTracker");
|
|
11713
11713
|
((FileHandleTracker2) => {
|
|
11714
11714
|
const openHandles = /* @__PURE__ */ new Set();
|
|
11715
|
-
const
|
|
11715
|
+
const registry3 = new FinalizationRegistry((info) => {
|
|
11716
11716
|
logger12.warn(`File handle GC'd without close: "${info.purpose}" for ${info.path}`);
|
|
11717
11717
|
});
|
|
11718
11718
|
function register(handle) {
|
|
11719
11719
|
const info = { purpose: handle.purpose, path: handle.path };
|
|
11720
|
-
|
|
11720
|
+
registry3.register(handle, info, handle);
|
|
11721
11721
|
const ref = new WeakRef(handle);
|
|
11722
11722
|
openHandles.add(ref);
|
|
11723
11723
|
}
|
|
11724
11724
|
FileHandleTracker2.register = register;
|
|
11725
11725
|
function unregister(handle) {
|
|
11726
|
-
|
|
11726
|
+
registry3.unregister(handle);
|
|
11727
11727
|
for (const ref of openHandles) {
|
|
11728
11728
|
if (ref.deref() === handle) {
|
|
11729
11729
|
openHandles.delete(ref);
|
|
@@ -64070,8 +64070,8 @@ var init_NodeSession = __esm({
|
|
|
64070
64070
|
return session?.type === SessionType.Unicast;
|
|
64071
64071
|
}
|
|
64072
64072
|
NodeSession2.is = is;
|
|
64073
|
-
function logNew(
|
|
64074
|
-
|
|
64073
|
+
function logNew(logger251, operation, session, messenger, fabric, peerNodeId) {
|
|
64074
|
+
logger251.info(
|
|
64075
64075
|
session.via,
|
|
64076
64076
|
`${operation} session with`,
|
|
64077
64077
|
Diagnostic.strong(PeerAddress({ fabricIndex: fabric.fabricIndex, nodeId: peerNodeId }).toString()),
|
|
@@ -117714,11 +117714,11 @@ var init_Api = __esm({
|
|
|
117714
117714
|
}
|
|
117715
117715
|
Api2.resourceFor = resourceFor;
|
|
117716
117716
|
function log(level, facility, id, ...message) {
|
|
117717
|
-
let
|
|
117718
|
-
if (!
|
|
117719
|
-
loggers.set(facility,
|
|
117717
|
+
let logger251 = loggers.get(facility);
|
|
117718
|
+
if (!logger251) {
|
|
117719
|
+
loggers.set(facility, logger251 = Logger.get(facility));
|
|
117720
117720
|
}
|
|
117721
|
-
|
|
117721
|
+
logger251[level](Diagnostic.via(id || "(anon)"), message);
|
|
117722
117722
|
}
|
|
117723
117723
|
Api2.log = log;
|
|
117724
117724
|
function logRequest(facility, id, method, target) {
|
|
@@ -132631,10 +132631,10 @@ var init_home_assistant_actions = __esm({
|
|
|
132631
132631
|
circuitBreakerResetMs: 3e4
|
|
132632
132632
|
};
|
|
132633
132633
|
HomeAssistantActions = class extends Service {
|
|
132634
|
-
constructor(
|
|
132634
|
+
constructor(logger251, client, config11) {
|
|
132635
132635
|
super("HomeAssistantActions");
|
|
132636
132636
|
this.client = client;
|
|
132637
|
-
this.log =
|
|
132637
|
+
this.log = logger251.get(this);
|
|
132638
132638
|
this.config = { ...defaultConfig, ...config11 };
|
|
132639
132639
|
this.circuitBreaker = new CircuitBreaker(
|
|
132640
132640
|
this.config.circuitBreakerThreshold,
|
|
@@ -132980,10 +132980,10 @@ var DiagnosticService = class {
|
|
|
132980
132980
|
};
|
|
132981
132981
|
|
|
132982
132982
|
// src/api/access-log.ts
|
|
132983
|
-
function accessLogger(
|
|
132983
|
+
function accessLogger(logger251) {
|
|
132984
132984
|
return (req, res, next) => {
|
|
132985
132985
|
res.on("finish", () => {
|
|
132986
|
-
|
|
132986
|
+
logger251.debug(
|
|
132987
132987
|
`${req.method} ${decodeURI(req.originalUrl)} ${res.statusCode} ${res.statusMessage} from ${req.socket.remoteAddress}`
|
|
132988
132988
|
);
|
|
132989
132989
|
});
|
|
@@ -136617,7 +136617,7 @@ var BLOCKED_PREFIXES = [
|
|
|
136617
136617
|
function pluginApi(bridgeService, storageLocation) {
|
|
136618
136618
|
const router = express14.Router();
|
|
136619
136619
|
const installer = new PluginInstaller(storageLocation);
|
|
136620
|
-
const
|
|
136620
|
+
const registry3 = new PluginRegistry(storageLocation);
|
|
136621
136621
|
router.get("/", (_req, res) => {
|
|
136622
136622
|
const result = [];
|
|
136623
136623
|
for (const bridge of bridgeService.bridges) {
|
|
@@ -136702,7 +136702,7 @@ function pluginApi(bridgeService, storageLocation) {
|
|
|
136702
136702
|
res.json({ success: true, pluginName, reset: true });
|
|
136703
136703
|
});
|
|
136704
136704
|
router.get("/installed", (_req, res) => {
|
|
136705
|
-
const registered =
|
|
136705
|
+
const registered = registry3.getAll();
|
|
136706
136706
|
const npmInstalled = installer.listInstalled();
|
|
136707
136707
|
const result = registered.map((entry) => {
|
|
136708
136708
|
const npm = npmInstalled.find((p) => p.name === entry.packageName);
|
|
@@ -136732,7 +136732,7 @@ function pluginApi(bridgeService, storageLocation) {
|
|
|
136732
136732
|
});
|
|
136733
136733
|
return;
|
|
136734
136734
|
}
|
|
136735
|
-
|
|
136735
|
+
registry3.add(packageName, config11 ?? {});
|
|
136736
136736
|
res.json({
|
|
136737
136737
|
success: true,
|
|
136738
136738
|
packageName,
|
|
@@ -136760,7 +136760,7 @@ function pluginApi(bridgeService, storageLocation) {
|
|
|
136760
136760
|
});
|
|
136761
136761
|
return;
|
|
136762
136762
|
}
|
|
136763
|
-
|
|
136763
|
+
registry3.remove(packageName);
|
|
136764
136764
|
res.json({
|
|
136765
136765
|
success: true,
|
|
136766
136766
|
packageName,
|
|
@@ -136800,7 +136800,7 @@ function pluginApi(bridgeService, storageLocation) {
|
|
|
136800
136800
|
});
|
|
136801
136801
|
return;
|
|
136802
136802
|
}
|
|
136803
|
-
|
|
136803
|
+
registry3.add(result.packageName, {});
|
|
136804
136804
|
res.json({
|
|
136805
136805
|
success: true,
|
|
136806
136806
|
packageName: result.packageName,
|
|
@@ -136833,7 +136833,7 @@ function pluginApi(bridgeService, storageLocation) {
|
|
|
136833
136833
|
});
|
|
136834
136834
|
return;
|
|
136835
136835
|
}
|
|
136836
|
-
|
|
136836
|
+
registry3.add(result.packageName, {});
|
|
136837
136837
|
res.json({
|
|
136838
136838
|
success: true,
|
|
136839
136839
|
packageName: result.packageName,
|
|
@@ -137530,7 +137530,7 @@ var WebSocketApi = class {
|
|
|
137530
137530
|
|
|
137531
137531
|
// src/api/web-api.ts
|
|
137532
137532
|
var WebApi = class extends Service {
|
|
137533
|
-
constructor(
|
|
137533
|
+
constructor(logger251, bridgeService, haClient, haRegistry, bridgeStorage, mappingStorage, identityStorage, lockCredentialStorage, settingsStorage, backupService, props) {
|
|
137534
137534
|
super("WebApi");
|
|
137535
137535
|
this.bridgeService = bridgeService;
|
|
137536
137536
|
this.haClient = haClient;
|
|
@@ -137542,8 +137542,8 @@ var WebApi = class extends Service {
|
|
|
137542
137542
|
this.settingsStorage = settingsStorage;
|
|
137543
137543
|
this.backupService = backupService;
|
|
137544
137544
|
this.props = props;
|
|
137545
|
-
this.logger =
|
|
137546
|
-
this.log =
|
|
137545
|
+
this.logger = logger251;
|
|
137546
|
+
this.log = logger251.get(this);
|
|
137547
137547
|
this.accessLogger = accessLogger(this.log.createChild("Access Log"));
|
|
137548
137548
|
this.startTime = Date.now();
|
|
137549
137549
|
this.wsApi = new WebSocketApi(
|
|
@@ -138734,10 +138734,10 @@ function isTransientConnectError(reason) {
|
|
|
138734
138734
|
return msg.includes("socket hang up") || msg.includes("tls") || msg.includes("TLS");
|
|
138735
138735
|
}
|
|
138736
138736
|
var HomeAssistantClient = class extends Service {
|
|
138737
|
-
constructor(
|
|
138737
|
+
constructor(logger251, options) {
|
|
138738
138738
|
super("HomeAssistantClient");
|
|
138739
138739
|
this.options = options;
|
|
138740
|
-
this.log =
|
|
138740
|
+
this.log = logger251.get(this);
|
|
138741
138741
|
}
|
|
138742
138742
|
options;
|
|
138743
138743
|
static Options = /* @__PURE__ */ Symbol.for("HomeAssistantClientProps");
|
|
@@ -156524,8 +156524,8 @@ var PluginManager = class {
|
|
|
156524
156524
|
this.storageDir = storageDir;
|
|
156525
156525
|
this.homeAssistant = homeAssistant;
|
|
156526
156526
|
}
|
|
156527
|
-
setRegistry(
|
|
156528
|
-
this.registry =
|
|
156527
|
+
setRegistry(registry3) {
|
|
156528
|
+
this.registry = registry3;
|
|
156529
156529
|
}
|
|
156530
156530
|
/**
|
|
156531
156531
|
* Load and register a built-in plugin instance.
|
|
@@ -157335,11 +157335,11 @@ var AUTO_FORCE_SYNC_INTERVAL_MS = 9e4;
|
|
|
157335
157335
|
var SHUTDOWN_SESSION_CLOSE_TIMEOUT_MS = 2500;
|
|
157336
157336
|
var MDNS_ADDRESS_CHECK_INTERVAL_MS = 6e4;
|
|
157337
157337
|
var Bridge = class {
|
|
157338
|
-
constructor(env,
|
|
157338
|
+
constructor(env, logger251, dataProvider, endpointManager, serverOptions) {
|
|
157339
157339
|
this.dataProvider = dataProvider;
|
|
157340
157340
|
this.endpointManager = endpointManager;
|
|
157341
157341
|
this.serverOptions = serverOptions;
|
|
157342
|
-
this.log =
|
|
157342
|
+
this.log = logger251.get(`Bridge / ${dataProvider.id}`);
|
|
157343
157343
|
this.server = new BridgeServerNode(
|
|
157344
157344
|
env,
|
|
157345
157345
|
this.dataProvider,
|
|
@@ -158471,9 +158471,9 @@ function resolveBatteryPercent(state) {
|
|
|
158471
158471
|
return BATTERY_ENUM_PERCENT[state.toLowerCase()] ?? null;
|
|
158472
158472
|
}
|
|
158473
158473
|
var EntityStateProvider = class extends Service {
|
|
158474
|
-
constructor(
|
|
158474
|
+
constructor(registry3) {
|
|
158475
158475
|
super("EntityStateProvider");
|
|
158476
|
-
this.registry =
|
|
158476
|
+
this.registry = registry3;
|
|
158477
158477
|
}
|
|
158478
158478
|
registry;
|
|
158479
158479
|
/**
|
|
@@ -160391,11 +160391,11 @@ function createEndpointId2(entityId, customName) {
|
|
|
160391
160391
|
const baseName = customName || entityId;
|
|
160392
160392
|
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
160393
160393
|
}
|
|
160394
|
-
function buildEntityPayload(
|
|
160395
|
-
const state =
|
|
160394
|
+
function buildEntityPayload(registry3, entityId) {
|
|
160395
|
+
const state = registry3.initialState(entityId);
|
|
160396
160396
|
if (!state) return void 0;
|
|
160397
|
-
const entity =
|
|
160398
|
-
const deviceRegistry =
|
|
160397
|
+
const entity = registry3.entity(entityId);
|
|
160398
|
+
const deviceRegistry = registry3.deviceOf(entityId);
|
|
160399
160399
|
return {
|
|
160400
160400
|
entity_id: entityId,
|
|
160401
160401
|
state,
|
|
@@ -160410,8 +160410,8 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
160410
160410
|
lastStates = /* @__PURE__ */ new Map();
|
|
160411
160411
|
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
160412
160412
|
static async create(config11) {
|
|
160413
|
-
const { registry:
|
|
160414
|
-
const primaryPayload = buildEntityPayload(
|
|
160413
|
+
const { registry: registry3, primaryEntityId } = config11;
|
|
160414
|
+
const primaryPayload = buildEntityPayload(registry3, primaryEntityId);
|
|
160415
160415
|
if (!primaryPayload) return void 0;
|
|
160416
160416
|
const airPurifierAttributes = primaryPayload.state.attributes;
|
|
160417
160417
|
const supportedFeatures = airPurifierAttributes.supported_features ?? 0;
|
|
@@ -160499,7 +160499,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
160499
160499
|
let tempSub;
|
|
160500
160500
|
if (config11.temperatureEntityId) {
|
|
160501
160501
|
const tempPayload = buildEntityPayload(
|
|
160502
|
-
|
|
160502
|
+
registry3,
|
|
160503
160503
|
config11.temperatureEntityId
|
|
160504
160504
|
);
|
|
160505
160505
|
if (tempPayload) {
|
|
@@ -160514,7 +160514,7 @@ var ComposedAirPurifierEndpoint = class _ComposedAirPurifierEndpoint extends End
|
|
|
160514
160514
|
}
|
|
160515
160515
|
let humSub;
|
|
160516
160516
|
if (config11.humidityEntityId) {
|
|
160517
|
-
const humPayload = buildEntityPayload(
|
|
160517
|
+
const humPayload = buildEntityPayload(registry3, config11.humidityEntityId);
|
|
160518
160518
|
if (humPayload) {
|
|
160519
160519
|
humSub = new Endpoint(
|
|
160520
160520
|
HumiditySubType.set({
|
|
@@ -161968,14 +161968,14 @@ function createEndpointId3(entityId, customName) {
|
|
|
161968
161968
|
const baseName = customName || entityId;
|
|
161969
161969
|
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
161970
161970
|
}
|
|
161971
|
-
function buildEntityPayload2(
|
|
161972
|
-
const state =
|
|
161971
|
+
function buildEntityPayload2(registry3, entityId) {
|
|
161972
|
+
const state = registry3.initialState(entityId);
|
|
161973
161973
|
if (!state) return void 0;
|
|
161974
161974
|
return {
|
|
161975
161975
|
entity_id: entityId,
|
|
161976
161976
|
state,
|
|
161977
|
-
registry:
|
|
161978
|
-
deviceRegistry:
|
|
161977
|
+
registry: registry3.entity(entityId),
|
|
161978
|
+
deviceRegistry: registry3.deviceOf(entityId)
|
|
161979
161979
|
};
|
|
161980
161980
|
}
|
|
161981
161981
|
var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpoint {
|
|
@@ -161985,8 +161985,8 @@ var ComposedClimateFanEndpoint = class _ComposedClimateFanEndpoint extends Endpo
|
|
|
161985
161985
|
lastStates = /* @__PURE__ */ new Map();
|
|
161986
161986
|
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
161987
161987
|
static async create(config11) {
|
|
161988
|
-
const { registry:
|
|
161989
|
-
const payload = buildEntityPayload2(
|
|
161988
|
+
const { registry: registry3, primaryEntityId } = config11;
|
|
161989
|
+
const payload = buildEntityPayload2(registry3, primaryEntityId);
|
|
161990
161990
|
if (!payload) return void 0;
|
|
161991
161991
|
const endpointId = config11.endpointId ?? createEndpointId3(primaryEntityId, config11.customName);
|
|
161992
161992
|
const mapping = config11.mapping ?? {
|
|
@@ -162244,11 +162244,11 @@ function createEndpointId4(entityId, customName) {
|
|
|
162244
162244
|
const baseName = customName || entityId;
|
|
162245
162245
|
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
162246
162246
|
}
|
|
162247
|
-
function buildEntityPayload3(
|
|
162248
|
-
const state =
|
|
162247
|
+
function buildEntityPayload3(registry3, entityId) {
|
|
162248
|
+
const state = registry3.initialStateIncludingUnfiltered(entityId);
|
|
162249
162249
|
if (!state) return void 0;
|
|
162250
|
-
const entity =
|
|
162251
|
-
const deviceRegistry =
|
|
162250
|
+
const entity = registry3.entityIncludingUnfiltered(entityId);
|
|
162251
|
+
const deviceRegistry = registry3.deviceOfIncludingUnfiltered(entityId);
|
|
162252
162252
|
return {
|
|
162253
162253
|
entity_id: entityId,
|
|
162254
162254
|
state,
|
|
@@ -162263,8 +162263,8 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
162263
162263
|
lastStates = /* @__PURE__ */ new Map();
|
|
162264
162264
|
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
162265
162265
|
static async create(config11) {
|
|
162266
|
-
const { registry:
|
|
162267
|
-
const primaryPayload = buildEntityPayload3(
|
|
162266
|
+
const { registry: registry3, primaryEntityId } = config11;
|
|
162267
|
+
const primaryPayload = buildEntityPayload3(registry3, primaryEntityId);
|
|
162268
162268
|
if (!primaryPayload) return void 0;
|
|
162269
162269
|
let parentType = BridgedNodeEndpoint.with(
|
|
162270
162270
|
BasicInformationServer2,
|
|
@@ -162308,7 +162308,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
162308
162308
|
parts.push(tempSub);
|
|
162309
162309
|
let humSub;
|
|
162310
162310
|
if (config11.humidityEntityId) {
|
|
162311
|
-
const humPayload = buildEntityPayload3(
|
|
162311
|
+
const humPayload = buildEntityPayload3(registry3, config11.humidityEntityId);
|
|
162312
162312
|
if (humPayload) {
|
|
162313
162313
|
humSub = new Endpoint(
|
|
162314
162314
|
HumiditySubType2.set({
|
|
@@ -162322,7 +162322,7 @@ var ComposedSensorEndpoint = class _ComposedSensorEndpoint extends Endpoint {
|
|
|
162322
162322
|
let pressSub;
|
|
162323
162323
|
if (config11.pressureEntityId) {
|
|
162324
162324
|
const pressPayload = buildEntityPayload3(
|
|
162325
|
-
|
|
162325
|
+
registry3,
|
|
162326
162326
|
config11.pressureEntityId
|
|
162327
162327
|
);
|
|
162328
162328
|
if (pressPayload) {
|
|
@@ -163276,6 +163276,15 @@ function clearPendingTilt(st) {
|
|
|
163276
163276
|
st.pendingTilt = null;
|
|
163277
163277
|
}
|
|
163278
163278
|
var coverOptimistic = /* @__PURE__ */ new WeakMap();
|
|
163279
|
+
function haRestEnd(action) {
|
|
163280
|
+
if (action.action.includes("open_cover")) {
|
|
163281
|
+
return "open";
|
|
163282
|
+
}
|
|
163283
|
+
if (action.action.includes("close_cover")) {
|
|
163284
|
+
return "close";
|
|
163285
|
+
}
|
|
163286
|
+
return null;
|
|
163287
|
+
}
|
|
163279
163288
|
function getCoverOptimistic(endpoint) {
|
|
163280
163289
|
let st = coverOptimistic.get(endpoint);
|
|
163281
163290
|
if (!st) {
|
|
@@ -163390,7 +163399,10 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163390
163399
|
if (!entry) {
|
|
163391
163400
|
return MovementStatus.Stopped;
|
|
163392
163401
|
}
|
|
163393
|
-
const
|
|
163402
|
+
const getExpected = config11.getExpectedRestPosition;
|
|
163403
|
+
const expectedPercent = entry.expectedRestEnd != null && getExpected != null ? getExpected(entry.expectedRestEnd, this.agent) : null;
|
|
163404
|
+
const goal = expectedPercent != null ? expectedPercent * 100 : existingTarget;
|
|
163405
|
+
const reachedTarget = positionAware && current100ths != null && goal != null && Math.abs(current100ths - goal) < 100;
|
|
163394
163406
|
const expired = Date.now() - entry.startedAt >= optimisticMovementTimeoutMs;
|
|
163395
163407
|
if (reachedTarget || expired) {
|
|
163396
163408
|
clearOptimisticAxis(optimistic, axis);
|
|
@@ -163495,7 +163507,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163495
163507
|
}
|
|
163496
163508
|
// Record the optimistic direction and emit it now so a controller gets the
|
|
163497
163509
|
// moving->stopped edge even when HA never reports a transitional state (#429).
|
|
163498
|
-
startOptimisticMovement(axis, status3) {
|
|
163510
|
+
startOptimisticMovement(axis, status3, expectedRestEnd) {
|
|
163499
163511
|
const optimistic = getCoverOptimistic(this.endpoint);
|
|
163500
163512
|
clearOptimisticAxis(optimistic, axis);
|
|
163501
163513
|
const endpoint = this.endpoint;
|
|
@@ -163540,7 +163552,7 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163540
163552
|
})();
|
|
163541
163553
|
}, optimisticMovementTimeoutMs);
|
|
163542
163554
|
timer.unref?.();
|
|
163543
|
-
optimistic[axis] = { status: status3, startedAt, timer };
|
|
163555
|
+
optimistic[axis] = { status: status3, startedAt, timer, expectedRestEnd };
|
|
163544
163556
|
this.writeOperationalStatus({ [axis]: status3 });
|
|
163545
163557
|
}
|
|
163546
163558
|
async handleMovement(type, _, direction, targetPercent100ths) {
|
|
@@ -163599,17 +163611,25 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163599
163611
|
}
|
|
163600
163612
|
handleLiftOpen() {
|
|
163601
163613
|
clearPendingLift(getCoverDebounce(this.endpoint));
|
|
163602
|
-
this.startOptimisticMovement("lift", MovementStatus.Opening);
|
|
163603
163614
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163604
163615
|
const action = this.state.config.openCoverLift(void 0, this.agent);
|
|
163616
|
+
this.startOptimisticMovement(
|
|
163617
|
+
"lift",
|
|
163618
|
+
MovementStatus.Opening,
|
|
163619
|
+
haRestEnd(action)
|
|
163620
|
+
);
|
|
163605
163621
|
logger218.info(`handleLiftOpen: calling action=${action.action}`);
|
|
163606
163622
|
homeAssistant.callAction(action);
|
|
163607
163623
|
}
|
|
163608
163624
|
handleLiftClose() {
|
|
163609
163625
|
clearPendingLift(getCoverDebounce(this.endpoint));
|
|
163610
|
-
this.startOptimisticMovement("lift", MovementStatus.Closing);
|
|
163611
163626
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163612
163627
|
const action = this.state.config.closeCoverLift(void 0, this.agent);
|
|
163628
|
+
this.startOptimisticMovement(
|
|
163629
|
+
"lift",
|
|
163630
|
+
MovementStatus.Closing,
|
|
163631
|
+
haRestEnd(action)
|
|
163632
|
+
);
|
|
163613
163633
|
logger218.info(`handleLiftClose: calling action=${action.action}`);
|
|
163614
163634
|
homeAssistant.callAction(action);
|
|
163615
163635
|
}
|
|
@@ -163620,14 +163640,15 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163620
163640
|
return;
|
|
163621
163641
|
}
|
|
163622
163642
|
this.state.targetPositionLiftPercent100ths = targetPercent100ths;
|
|
163623
|
-
this.startOptimisticMovement(
|
|
163624
|
-
"lift",
|
|
163625
|
-
currentPositionMatter != null && targetPercent100ths < currentPositionMatter ? MovementStatus.Opening : MovementStatus.Closing
|
|
163626
|
-
);
|
|
163627
163643
|
const targetPosition = targetPercent100ths / 100;
|
|
163628
163644
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163629
163645
|
const action = config11.setLiftPosition(targetPosition, this.agent);
|
|
163630
163646
|
const entityId = homeAssistant.entityId;
|
|
163647
|
+
this.startOptimisticMovement(
|
|
163648
|
+
"lift",
|
|
163649
|
+
currentPositionMatter != null && targetPercent100ths < currentPositionMatter ? MovementStatus.Opening : MovementStatus.Closing,
|
|
163650
|
+
haRestEnd(action)
|
|
163651
|
+
);
|
|
163631
163652
|
const actions = this.env.get(HomeAssistantActions);
|
|
163632
163653
|
const st = getCoverDebounce(this.endpoint);
|
|
163633
163654
|
st.pendingLift = { action, entityId, actions };
|
|
@@ -163660,21 +163681,27 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163660
163681
|
const st = getCoverDebounce(this.endpoint);
|
|
163661
163682
|
clearPendingTilt(st);
|
|
163662
163683
|
if (st.pendingLift?.action.action.includes("tilt")) clearPendingLift(st);
|
|
163663
|
-
this.
|
|
163664
|
-
|
|
163665
|
-
|
|
163666
|
-
|
|
163684
|
+
const action = this.state.config.openCoverTilt(void 0, this.agent);
|
|
163685
|
+
this.startOptimisticMovement(
|
|
163686
|
+
"tilt",
|
|
163687
|
+
MovementStatus.Opening,
|
|
163688
|
+
haRestEnd(action)
|
|
163667
163689
|
);
|
|
163690
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163691
|
+
homeAssistant.callAction(action);
|
|
163668
163692
|
}
|
|
163669
163693
|
handleTiltClose() {
|
|
163670
163694
|
const st = getCoverDebounce(this.endpoint);
|
|
163671
163695
|
clearPendingTilt(st);
|
|
163672
163696
|
if (st.pendingLift?.action.action.includes("tilt")) clearPendingLift(st);
|
|
163673
|
-
this.
|
|
163674
|
-
|
|
163675
|
-
|
|
163676
|
-
|
|
163697
|
+
const action = this.state.config.closeCoverTilt(void 0, this.agent);
|
|
163698
|
+
this.startOptimisticMovement(
|
|
163699
|
+
"tilt",
|
|
163700
|
+
MovementStatus.Closing,
|
|
163701
|
+
haRestEnd(action)
|
|
163677
163702
|
);
|
|
163703
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163704
|
+
homeAssistant.callAction(action);
|
|
163678
163705
|
}
|
|
163679
163706
|
handleGoToTiltPosition(targetPercent100ths) {
|
|
163680
163707
|
const config11 = this.state.config;
|
|
@@ -163683,14 +163710,15 @@ var WindowCoveringServerBase = class _WindowCoveringServerBase extends FeaturedB
|
|
|
163683
163710
|
return;
|
|
163684
163711
|
}
|
|
163685
163712
|
this.state.targetPositionTiltPercent100ths = targetPercent100ths;
|
|
163686
|
-
this.startOptimisticMovement(
|
|
163687
|
-
"tilt",
|
|
163688
|
-
currentPositionMatter != null && targetPercent100ths < currentPositionMatter ? MovementStatus.Opening : MovementStatus.Closing
|
|
163689
|
-
);
|
|
163690
163713
|
const targetPosition = targetPercent100ths / 100;
|
|
163691
163714
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
163692
163715
|
const action = config11.setTiltPosition(targetPosition, this.agent);
|
|
163693
163716
|
const entityId = homeAssistant.entityId;
|
|
163717
|
+
this.startOptimisticMovement(
|
|
163718
|
+
"tilt",
|
|
163719
|
+
currentPositionMatter != null && targetPercent100ths < currentPositionMatter ? MovementStatus.Opening : MovementStatus.Closing,
|
|
163720
|
+
haRestEnd(action)
|
|
163721
|
+
);
|
|
163694
163722
|
const actions = this.env.get(HomeAssistantActions);
|
|
163695
163723
|
const st = getCoverDebounce(this.endpoint);
|
|
163696
163724
|
st.pendingTilt = { action, entityId, actions };
|
|
@@ -163832,6 +163860,7 @@ var adjustPositionForWriting2 = (position, agent) => {
|
|
|
163832
163860
|
const matterSem = usesMatterSemantics(agent);
|
|
163833
163861
|
return adjustPositionForWriting(position, featureFlags, matterSem);
|
|
163834
163862
|
};
|
|
163863
|
+
var expectedRestPosition = (end, agent) => adjustPositionForReading2(end === "open" ? 100 : 0, agent);
|
|
163835
163864
|
var shouldSwapOpenClose = (agent) => {
|
|
163836
163865
|
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
163837
163866
|
const entitySwap = homeAssistant.state.mapping?.coverSwapOpenClose;
|
|
@@ -163919,11 +163948,11 @@ var config6 = {
|
|
|
163919
163948
|
}
|
|
163920
163949
|
return position == null ? null : adjustPositionForReading2(position, agent);
|
|
163921
163950
|
},
|
|
163951
|
+
getExpectedRestPosition: expectedRestPosition,
|
|
163922
163952
|
getCoverType: (entity) => deviceClassMapping(entity)?.type,
|
|
163923
163953
|
getEndProductType: (entity) => deviceClassMapping(entity)?.endProductType,
|
|
163924
163954
|
getMovementStatus: (entity, agent) => {
|
|
163925
|
-
const
|
|
163926
|
-
const swapped = featureFlags?.coverSwapOpenClose === true;
|
|
163955
|
+
const swapped = shouldSwapOpenClose(agent);
|
|
163927
163956
|
const coverState = entity.state;
|
|
163928
163957
|
if (coverState === CoverDeviceState.opening) {
|
|
163929
163958
|
return swapped ? WindowCovering3.MovementStatus.Closing : WindowCovering3.MovementStatus.Opening;
|
|
@@ -169774,8 +169803,8 @@ var VacuumIdentifyServer = class extends IdentifyServer2 {
|
|
|
169774
169803
|
#findIdentifyButton(homeAssistant) {
|
|
169775
169804
|
const deviceId = homeAssistant.entity.registry?.device_id;
|
|
169776
169805
|
if (!deviceId) return void 0;
|
|
169777
|
-
const
|
|
169778
|
-
for (const entity of Object.values(
|
|
169806
|
+
const registry3 = this.env.get(HomeAssistantRegistry);
|
|
169807
|
+
for (const entity of Object.values(registry3.entities)) {
|
|
169779
169808
|
if (entity.device_id !== deviceId) continue;
|
|
169780
169809
|
if (!entity.entity_id.startsWith("button.")) continue;
|
|
169781
169810
|
const uniqueId = entity.unique_id ?? "";
|
|
@@ -172178,11 +172207,11 @@ function createEndpointId5(entityId, customName) {
|
|
|
172178
172207
|
const baseName = customName || entityId;
|
|
172179
172208
|
return baseName.replace(/\./g, "_").replace(/\s+/g, "_");
|
|
172180
172209
|
}
|
|
172181
|
-
function buildEntityPayload4(
|
|
172182
|
-
const state =
|
|
172210
|
+
function buildEntityPayload4(registry3, entityId) {
|
|
172211
|
+
const state = registry3.initialStateIncludingUnfiltered(entityId);
|
|
172183
172212
|
if (!state) return void 0;
|
|
172184
|
-
const entity =
|
|
172185
|
-
const deviceRegistry =
|
|
172213
|
+
const entity = registry3.entityIncludingUnfiltered(entityId);
|
|
172214
|
+
const deviceRegistry = registry3.deviceOfIncludingUnfiltered(entityId);
|
|
172186
172215
|
return {
|
|
172187
172216
|
entity_id: entityId,
|
|
172188
172217
|
state,
|
|
@@ -172198,8 +172227,8 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
|
172198
172227
|
lastMappedStates = /* @__PURE__ */ new Map();
|
|
172199
172228
|
debouncedUpdates = /* @__PURE__ */ new Map();
|
|
172200
172229
|
static async create(config11) {
|
|
172201
|
-
const { registry:
|
|
172202
|
-
const primaryPayload = buildEntityPayload4(
|
|
172230
|
+
const { registry: registry3, primaryEntityId, composedEntities } = config11;
|
|
172231
|
+
const primaryPayload = buildEntityPayload4(registry3, primaryEntityId);
|
|
172203
172232
|
if (!primaryPayload) return void 0;
|
|
172204
172233
|
let parentType = BridgedNodeEndpoint.with(
|
|
172205
172234
|
BasicInformationServer2,
|
|
@@ -172241,7 +172270,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
|
172241
172270
|
primarySubPayload,
|
|
172242
172271
|
primaryMapping,
|
|
172243
172272
|
config11.areaName,
|
|
172244
|
-
{ vacuumOnOff:
|
|
172273
|
+
{ vacuumOnOff: registry3.isVacuumOnOffEnabled() }
|
|
172245
172274
|
);
|
|
172246
172275
|
if (!primaryType) {
|
|
172247
172276
|
logger242.warn(
|
|
@@ -172257,7 +172286,7 @@ var UserComposedEndpoint = class _UserComposedEndpoint extends Endpoint {
|
|
|
172257
172286
|
for (let i = 0; i < composedEntities.length; i++) {
|
|
172258
172287
|
const sub = composedEntities[i];
|
|
172259
172288
|
if (!sub.entityId) continue;
|
|
172260
|
-
const subPayload = buildEntityPayload4(
|
|
172289
|
+
const subPayload = buildEntityPayload4(registry3, sub.entityId);
|
|
172261
172290
|
if (!subPayload) {
|
|
172262
172291
|
logger242.warn(
|
|
172263
172292
|
`Cannot find state for composed sub-entity ${sub.entityId}, it does not exist in Home Assistant (removed or renamed?)`
|
|
@@ -172419,32 +172448,32 @@ function asStandaloneEndpointType(type) {
|
|
|
172419
172448
|
// src/matter/endpoints/legacy/legacy-endpoint.ts
|
|
172420
172449
|
var logger243 = Logger.get("LegacyEndpoint");
|
|
172421
172450
|
var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
172422
|
-
static async create(
|
|
172423
|
-
const deviceRegistry =
|
|
172424
|
-
let state =
|
|
172425
|
-
const entity =
|
|
172451
|
+
static async create(registry3, entityId, mapping, pluginDomainMappings, standalone = false, endpointId, identityAnchor) {
|
|
172452
|
+
const deviceRegistry = registry3.deviceOf(entityId);
|
|
172453
|
+
let state = registry3.initialState(entityId);
|
|
172454
|
+
const entity = registry3.entity(entityId);
|
|
172426
172455
|
if (!state) {
|
|
172427
172456
|
return;
|
|
172428
172457
|
}
|
|
172429
|
-
if (
|
|
172458
|
+
if (registry3.isAutoBatteryMappingEnabled() && registry3.isBatteryEntityUsed(entityId)) {
|
|
172430
172459
|
logger243.debug(
|
|
172431
172460
|
`Skipping ${entityId} - already auto-assigned as battery to another device`
|
|
172432
172461
|
);
|
|
172433
172462
|
return;
|
|
172434
172463
|
}
|
|
172435
|
-
if (
|
|
172464
|
+
if (registry3.isAutoHumidityMappingEnabled() && registry3.isHumidityEntityUsed(entityId)) {
|
|
172436
172465
|
logger243.debug(
|
|
172437
172466
|
`Skipping ${entityId} - already auto-assigned as humidity to a temperature sensor`
|
|
172438
172467
|
);
|
|
172439
172468
|
return;
|
|
172440
172469
|
}
|
|
172441
|
-
if (
|
|
172470
|
+
if (registry3.isAutoPressureMappingEnabled() && registry3.isPressureEntityUsed(entityId)) {
|
|
172442
172471
|
logger243.debug(
|
|
172443
172472
|
`Skipping ${entityId} - already auto-assigned as pressure to a temperature sensor`
|
|
172444
172473
|
);
|
|
172445
172474
|
return;
|
|
172446
172475
|
}
|
|
172447
|
-
if (
|
|
172476
|
+
if (registry3.isAutoComposedDevicesEnabled() && registry3.isComposedSubEntityUsed(entityId)) {
|
|
172448
172477
|
logger243.debug(
|
|
172449
172478
|
`Skipping ${entityId} - already consumed by a composed device`
|
|
172450
172479
|
);
|
|
@@ -172452,10 +172481,10 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172452
172481
|
}
|
|
172453
172482
|
let effectiveMapping = mapping;
|
|
172454
172483
|
if (entity.device_id) {
|
|
172455
|
-
if (
|
|
172484
|
+
if (registry3.isAutoHumidityMappingEnabled()) {
|
|
172456
172485
|
const attrs = state.attributes;
|
|
172457
172486
|
if (!mapping?.humidityEntity && entityId.startsWith("sensor.") && attrs.device_class === SensorDeviceClass.temperature) {
|
|
172458
|
-
const humidityEntityId =
|
|
172487
|
+
const humidityEntityId = registry3.findHumidityEntityForDevice(
|
|
172459
172488
|
entity.device_id
|
|
172460
172489
|
);
|
|
172461
172490
|
if (humidityEntityId && humidityEntityId !== entityId) {
|
|
@@ -172464,17 +172493,17 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172464
172493
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
172465
172494
|
humidityEntity: humidityEntityId
|
|
172466
172495
|
};
|
|
172467
|
-
|
|
172496
|
+
registry3.markHumidityEntityUsed(humidityEntityId);
|
|
172468
172497
|
logger243.debug(
|
|
172469
172498
|
`Auto-assigned humidity ${humidityEntityId} to ${entityId}`
|
|
172470
172499
|
);
|
|
172471
172500
|
}
|
|
172472
172501
|
}
|
|
172473
172502
|
}
|
|
172474
|
-
if (
|
|
172503
|
+
if (registry3.isAutoPressureMappingEnabled()) {
|
|
172475
172504
|
const attrs = state.attributes;
|
|
172476
172505
|
if (!mapping?.pressureEntity && entityId.startsWith("sensor.") && attrs.device_class === SensorDeviceClass.temperature) {
|
|
172477
|
-
const pressureEntityId =
|
|
172506
|
+
const pressureEntityId = registry3.findPressureEntityForDevice(
|
|
172478
172507
|
entity.device_id
|
|
172479
172508
|
);
|
|
172480
172509
|
if (pressureEntityId && pressureEntityId !== entityId) {
|
|
@@ -172483,7 +172512,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172483
172512
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
172484
172513
|
pressureEntity: pressureEntityId
|
|
172485
172514
|
};
|
|
172486
|
-
|
|
172515
|
+
registry3.markPressureEntityUsed(pressureEntityId);
|
|
172487
172516
|
logger243.debug(
|
|
172488
172517
|
`Auto-assigned pressure ${pressureEntityId} to ${entityId}`
|
|
172489
172518
|
);
|
|
@@ -172491,8 +172520,8 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172491
172520
|
}
|
|
172492
172521
|
}
|
|
172493
172522
|
const isVacuum = entityId.startsWith("vacuum.");
|
|
172494
|
-
if ((
|
|
172495
|
-
const batteryEntityId =
|
|
172523
|
+
if ((registry3.isAutoBatteryMappingEnabled() || isVacuum) && !mapping?.batteryEntity && !mapping?.disableBatteryMapping) {
|
|
172524
|
+
const batteryEntityId = registry3.findBatteryEntityForDevice(
|
|
172496
172525
|
entity.device_id
|
|
172497
172526
|
);
|
|
172498
172527
|
if (batteryEntityId && batteryEntityId !== entityId) {
|
|
@@ -172501,7 +172530,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172501
172530
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
172502
172531
|
batteryEntity: batteryEntityId
|
|
172503
172532
|
};
|
|
172504
|
-
|
|
172533
|
+
registry3.markBatteryEntityUsed(batteryEntityId);
|
|
172505
172534
|
logger243.debug(
|
|
172506
172535
|
`Auto-assigned battery ${batteryEntityId} to ${entityId}`
|
|
172507
172536
|
);
|
|
@@ -172509,8 +172538,8 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172509
172538
|
}
|
|
172510
172539
|
const alarmDeviceClass = state.attributes.device_class;
|
|
172511
172540
|
const isSmokeCoAlarm = mapping?.matterDeviceType === "smoke_co_alarm" || entityId.startsWith("binary_sensor.") && (alarmDeviceClass === "smoke" || alarmDeviceClass === "carbon_monoxide" || alarmDeviceClass === "gas");
|
|
172512
|
-
if (
|
|
172513
|
-
const faultEntityId =
|
|
172541
|
+
if (registry3.isAutoBatteryMappingEnabled() && !mapping?.faultEntity && isSmokeCoAlarm) {
|
|
172542
|
+
const faultEntityId = registry3.findProblemEntityForDevice(
|
|
172514
172543
|
entity.device_id
|
|
172515
172544
|
);
|
|
172516
172545
|
if (faultEntityId && faultEntityId !== entityId) {
|
|
@@ -172525,7 +172554,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172525
172554
|
if (!mapping?.powerEntity) {
|
|
172526
172555
|
const domain = entityId.split(".")[0];
|
|
172527
172556
|
if (domain === "switch") {
|
|
172528
|
-
const powerEntityId =
|
|
172557
|
+
const powerEntityId = registry3.findPowerEntityForDevice(
|
|
172529
172558
|
entity.device_id
|
|
172530
172559
|
);
|
|
172531
172560
|
if (powerEntityId && powerEntityId !== entityId) {
|
|
@@ -172534,7 +172563,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172534
172563
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
172535
172564
|
powerEntity: powerEntityId
|
|
172536
172565
|
};
|
|
172537
|
-
|
|
172566
|
+
registry3.markPowerEntityUsed(powerEntityId);
|
|
172538
172567
|
logger243.debug(`Auto-assigned power ${powerEntityId} to ${entityId}`);
|
|
172539
172568
|
}
|
|
172540
172569
|
}
|
|
@@ -172542,7 +172571,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172542
172571
|
if (!mapping?.energyEntity) {
|
|
172543
172572
|
const domain = entityId.split(".")[0];
|
|
172544
172573
|
if (domain === "switch") {
|
|
172545
|
-
const energyEntityId =
|
|
172574
|
+
const energyEntityId = registry3.findEnergyEntityForDevice(
|
|
172546
172575
|
entity.device_id
|
|
172547
172576
|
);
|
|
172548
172577
|
if (energyEntityId && energyEntityId !== entityId) {
|
|
@@ -172551,7 +172580,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172551
172580
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
172552
172581
|
energyEntity: energyEntityId
|
|
172553
172582
|
};
|
|
172554
|
-
|
|
172583
|
+
registry3.markEnergyEntityUsed(energyEntityId);
|
|
172555
172584
|
logger243.debug(
|
|
172556
172585
|
`Auto-assigned energy ${energyEntityId} to ${entityId}`
|
|
172557
172586
|
);
|
|
@@ -172559,7 +172588,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172559
172588
|
}
|
|
172560
172589
|
}
|
|
172561
172590
|
if (entityId.startsWith("vacuum.")) {
|
|
172562
|
-
const vacuumEntities =
|
|
172591
|
+
const vacuumEntities = registry3.findVacuumSelectEntities(
|
|
172563
172592
|
entity.device_id
|
|
172564
172593
|
);
|
|
172565
172594
|
if (!effectiveMapping?.cleaningModeEntity && vacuumEntities.cleaningModeEntity) {
|
|
@@ -172603,7 +172632,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172603
172632
|
);
|
|
172604
172633
|
}
|
|
172605
172634
|
const supportedFeatures = state.attributes.supported_features ?? 0;
|
|
172606
|
-
const cleanAreaRooms = await
|
|
172635
|
+
const cleanAreaRooms = await registry3.resolveCleanAreaRooms(
|
|
172607
172636
|
entityId,
|
|
172608
172637
|
supportedFeatures
|
|
172609
172638
|
);
|
|
@@ -172619,7 +172648,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172619
172648
|
}
|
|
172620
172649
|
const vacAttrs = state.attributes;
|
|
172621
172650
|
if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
172622
|
-
const valetudoRooms =
|
|
172651
|
+
const valetudoRooms = registry3.findValetudoMapSegments(
|
|
172623
172652
|
entity.device_id
|
|
172624
172653
|
);
|
|
172625
172654
|
if (valetudoRooms.length > 0) {
|
|
@@ -172638,7 +172667,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172638
172667
|
`Auto-detected ${valetudoRooms.length} Valetudo segments for ${entityId}`
|
|
172639
172668
|
);
|
|
172640
172669
|
} else {
|
|
172641
|
-
const roborockRooms = await
|
|
172670
|
+
const roborockRooms = await registry3.resolveRoborockRooms(entityId);
|
|
172642
172671
|
if (roborockRooms.length > 0) {
|
|
172643
172672
|
const roomsObj = {};
|
|
172644
172673
|
for (const r of roborockRooms) {
|
|
@@ -172664,10 +172693,10 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172664
172693
|
`Composed mappings are not supported in server mode, exposing ${entityId} as a flat standalone endpoint`
|
|
172665
172694
|
);
|
|
172666
172695
|
}
|
|
172667
|
-
if (!standalone &&
|
|
172668
|
-
const composedAreaName =
|
|
172696
|
+
if (!standalone && registry3.isAutoComposedDevicesEnabled() && effectiveMapping?.composedEntities && effectiveMapping.composedEntities.length > 0) {
|
|
172697
|
+
const composedAreaName = registry3.getAreaName(entityId);
|
|
172669
172698
|
const composed = await UserComposedEndpoint.create({
|
|
172670
|
-
registry:
|
|
172699
|
+
registry: registry3,
|
|
172671
172700
|
primaryEntityId: entityId,
|
|
172672
172701
|
mapping: effectiveMapping,
|
|
172673
172702
|
composedEntities: effectiveMapping.composedEntities,
|
|
@@ -172683,12 +172712,12 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172683
172712
|
`User composed device creation failed for ${entityId}, falling back to standalone`
|
|
172684
172713
|
);
|
|
172685
172714
|
}
|
|
172686
|
-
if (!standalone &&
|
|
172715
|
+
if (!standalone && registry3.isAutoComposedDevicesEnabled()) {
|
|
172687
172716
|
const attrs = state.attributes;
|
|
172688
172717
|
if (entityId.startsWith("sensor.") && attrs.device_class === SensorDeviceClass.temperature && (effectiveMapping?.humidityEntity || effectiveMapping?.pressureEntity)) {
|
|
172689
|
-
const composedAreaName =
|
|
172718
|
+
const composedAreaName = registry3.getAreaName(entityId);
|
|
172690
172719
|
const composed = await ComposedSensorEndpoint.create({
|
|
172691
|
-
registry:
|
|
172720
|
+
registry: registry3,
|
|
172692
172721
|
primaryEntityId: entityId,
|
|
172693
172722
|
humidityEntityId: effectiveMapping?.humidityEntity,
|
|
172694
172723
|
pressureEntityId: effectiveMapping?.pressureEntity,
|
|
@@ -172704,12 +172733,12 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172704
172733
|
}
|
|
172705
172734
|
const resolvedMatterType = mapping?.matterDeviceType ?? (entityId.startsWith("fan.") ? "fan" : void 0);
|
|
172706
172735
|
if (resolvedMatterType === "air_purifier") {
|
|
172707
|
-
const temperatureEntityId = effectiveMapping?.temperatureEntity || (entity.device_id ?
|
|
172708
|
-
const humidityEntityId = effectiveMapping?.humidityEntity || (entity.device_id ?
|
|
172736
|
+
const temperatureEntityId = effectiveMapping?.temperatureEntity || (entity.device_id ? registry3.findTemperatureEntityForDevice(entity.device_id) : void 0);
|
|
172737
|
+
const humidityEntityId = effectiveMapping?.humidityEntity || (entity.device_id ? registry3.findHumidityEntityForDevice(entity.device_id) : void 0);
|
|
172709
172738
|
if (temperatureEntityId || humidityEntityId) {
|
|
172710
|
-
const composedAreaName =
|
|
172739
|
+
const composedAreaName = registry3.getAreaName(entityId);
|
|
172711
172740
|
const composed = await ComposedAirPurifierEndpoint.create({
|
|
172712
|
-
registry:
|
|
172741
|
+
registry: registry3,
|
|
172713
172742
|
primaryEntityId: entityId,
|
|
172714
172743
|
temperatureEntityId,
|
|
172715
172744
|
humidityEntityId,
|
|
@@ -172731,9 +172760,9 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172731
172760
|
if (!standalone && entityId.startsWith("climate.") && effectiveMapping?.climateExposeFan === true) {
|
|
172732
172761
|
const climateFeatures = state.attributes.supported_features ?? 0;
|
|
172733
172762
|
if ((climateFeatures & ClimateDeviceFeature.FAN_MODE) !== 0) {
|
|
172734
|
-
const composedAreaName =
|
|
172763
|
+
const composedAreaName = registry3.getAreaName(entityId);
|
|
172735
172764
|
const composed = await ComposedClimateFanEndpoint.create({
|
|
172736
|
-
registry:
|
|
172765
|
+
registry: registry3,
|
|
172737
172766
|
primaryEntityId: entityId,
|
|
172738
172767
|
mapping: effectiveMapping,
|
|
172739
172768
|
customName: effectiveMapping?.customName,
|
|
@@ -172758,7 +172787,7 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172758
172787
|
let cleaningModeOptions;
|
|
172759
172788
|
if (entityId.startsWith("vacuum.")) {
|
|
172760
172789
|
if (effectiveMapping?.cleaningModeEntity) {
|
|
172761
|
-
const cmState =
|
|
172790
|
+
const cmState = registry3.initialState(
|
|
172762
172791
|
effectiveMapping.cleaningModeEntity
|
|
172763
172792
|
);
|
|
172764
172793
|
cleaningModeOptions = cmState?.attributes?.options;
|
|
@@ -172772,13 +172801,13 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
172772
172801
|
];
|
|
172773
172802
|
}
|
|
172774
172803
|
}
|
|
172775
|
-
const areaName =
|
|
172804
|
+
const areaName = registry3.getAreaName(entityId);
|
|
172776
172805
|
let type = createLegacyEndpointType(
|
|
172777
172806
|
payload,
|
|
172778
172807
|
effectiveMapping,
|
|
172779
172808
|
areaName,
|
|
172780
172809
|
{
|
|
172781
|
-
vacuumOnOff:
|
|
172810
|
+
vacuumOnOff: registry3.isVacuumOnOffEnabled(),
|
|
172782
172811
|
cleaningModeOptions,
|
|
172783
172812
|
pluginDomainMappings
|
|
172784
172813
|
},
|
|
@@ -172960,27 +172989,181 @@ var CameraAvStreamServer = class extends Base4 {
|
|
|
172960
172989
|
init_esm();
|
|
172961
172990
|
init_esm7();
|
|
172962
172991
|
init_esm3();
|
|
172963
|
-
|
|
172992
|
+
|
|
172993
|
+
// src/plugins/builtin/camera/requestor-client.ts
|
|
172994
|
+
init_esm();
|
|
172995
|
+
init_esm4();
|
|
172996
|
+
var logger244 = Logger.get("CameraWebRtcRequestor");
|
|
172997
|
+
var registry2 = /* @__PURE__ */ new Map();
|
|
172998
|
+
var pendingDeliveries = /* @__PURE__ */ new Map();
|
|
172999
|
+
var invokeTransport = defaultInvoke;
|
|
173000
|
+
function registerRequestor(sessionId, registration) {
|
|
173001
|
+
registry2.set(sessionId, registration);
|
|
173002
|
+
}
|
|
173003
|
+
function unregisterRequestor(sessionId) {
|
|
173004
|
+
registry2.delete(sessionId);
|
|
173005
|
+
const timer = pendingDeliveries.get(sessionId);
|
|
173006
|
+
if (timer) {
|
|
173007
|
+
clearTimeout(timer);
|
|
173008
|
+
pendingDeliveries.delete(sessionId);
|
|
173009
|
+
}
|
|
173010
|
+
}
|
|
173011
|
+
function unregisterAllRequestors() {
|
|
173012
|
+
for (const id of [...registry2.keys()]) unregisterRequestor(id);
|
|
173013
|
+
for (const timer of pendingDeliveries.values()) clearTimeout(timer);
|
|
173014
|
+
pendingDeliveries.clear();
|
|
173015
|
+
}
|
|
173016
|
+
function deliverAnswerDeferred(sessionId, sdp, onGiveUp) {
|
|
173017
|
+
const prior = pendingDeliveries.get(sessionId);
|
|
173018
|
+
if (prior) clearTimeout(prior);
|
|
173019
|
+
const owner = registry2.get(sessionId);
|
|
173020
|
+
const timer = setTimeout(() => {
|
|
173021
|
+
void (async () => {
|
|
173022
|
+
try {
|
|
173023
|
+
for (const delayMs of [0, 250, 500]) {
|
|
173024
|
+
if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
|
|
173025
|
+
if (registry2.get(sessionId) !== owner || pendingDeliveries.get(sessionId) !== timer) {
|
|
173026
|
+
return;
|
|
173027
|
+
}
|
|
173028
|
+
if (await sendAnswer(sessionId, sdp)) {
|
|
173029
|
+
logger244.info(`answer delivered for session ${sessionId}`);
|
|
173030
|
+
return;
|
|
173031
|
+
}
|
|
173032
|
+
}
|
|
173033
|
+
if (registry2.get(sessionId) !== owner || pendingDeliveries.get(sessionId) !== timer) {
|
|
173034
|
+
return;
|
|
173035
|
+
}
|
|
173036
|
+
logger244.info(
|
|
173037
|
+
`answer delivery failed for session ${sessionId}, giving up`
|
|
173038
|
+
);
|
|
173039
|
+
await onGiveUp();
|
|
173040
|
+
} catch (err) {
|
|
173041
|
+
logger244.info(
|
|
173042
|
+
`answer delivery for session ${sessionId} threw: ${errText(err)}`
|
|
173043
|
+
);
|
|
173044
|
+
} finally {
|
|
173045
|
+
if (pendingDeliveries.get(sessionId) === timer) {
|
|
173046
|
+
pendingDeliveries.delete(sessionId);
|
|
173047
|
+
}
|
|
173048
|
+
}
|
|
173049
|
+
})();
|
|
173050
|
+
}, 0);
|
|
173051
|
+
timer.unref?.();
|
|
173052
|
+
pendingDeliveries.set(sessionId, timer);
|
|
173053
|
+
}
|
|
173054
|
+
function hasRequestor(sessionId) {
|
|
173055
|
+
return registry2.has(sessionId);
|
|
173056
|
+
}
|
|
173057
|
+
function sendAnswer(sessionId, sdp) {
|
|
173058
|
+
return invokeRequestor(sessionId, "answer", {
|
|
173059
|
+
webRtcSessionId: sessionId,
|
|
173060
|
+
sdp
|
|
173061
|
+
});
|
|
173062
|
+
}
|
|
173063
|
+
async function invokeRequestor(sessionId, command, fields) {
|
|
173064
|
+
const registration = registry2.get(sessionId);
|
|
173065
|
+
if (!registration) {
|
|
173066
|
+
logger244.info(`requestor ${command}: no session ${sessionId} registered`);
|
|
173067
|
+
return false;
|
|
173068
|
+
}
|
|
173069
|
+
if (registration.session.isClosed) {
|
|
173070
|
+
logger244.info(`requestor ${command}: session ${sessionId} already closed`);
|
|
173071
|
+
return false;
|
|
173072
|
+
}
|
|
173073
|
+
const request = {
|
|
173074
|
+
endpoint: registration.requestorEndpoint,
|
|
173075
|
+
cluster: WebRtcTransportRequestor3.Cluster,
|
|
173076
|
+
command,
|
|
173077
|
+
fields
|
|
173078
|
+
};
|
|
173079
|
+
try {
|
|
173080
|
+
return await invokeTransport({ registration, request });
|
|
173081
|
+
} catch (err) {
|
|
173082
|
+
logger244.info(
|
|
173083
|
+
`requestor ${command} failed for session ${sessionId}: ${errText(err)}`
|
|
173084
|
+
);
|
|
173085
|
+
return false;
|
|
173086
|
+
}
|
|
173087
|
+
}
|
|
173088
|
+
async function defaultInvoke({
|
|
173089
|
+
registration,
|
|
173090
|
+
request
|
|
173091
|
+
}) {
|
|
173092
|
+
const { session, env } = registration;
|
|
173093
|
+
const exchangeManager = env.get(ExchangeManager);
|
|
173094
|
+
const exchangeProvider = new DedicatedChannelExchangeProvider(
|
|
173095
|
+
exchangeManager,
|
|
173096
|
+
session
|
|
173097
|
+
);
|
|
173098
|
+
const client = new ClientInteraction({ environment: env, exchangeProvider });
|
|
173099
|
+
try {
|
|
173100
|
+
const result = client.invoke(
|
|
173101
|
+
Invoke({
|
|
173102
|
+
commands: [
|
|
173103
|
+
{
|
|
173104
|
+
endpoint: request.endpoint,
|
|
173105
|
+
cluster: request.cluster,
|
|
173106
|
+
command: request.command,
|
|
173107
|
+
// biome-ignore lint/suspicious/noExplicitAny: fields typed per command by caller
|
|
173108
|
+
fields: request.fields
|
|
173109
|
+
}
|
|
173110
|
+
]
|
|
173111
|
+
})
|
|
173112
|
+
);
|
|
173113
|
+
for await (const chunk of result) {
|
|
173114
|
+
for (const entry of chunk) {
|
|
173115
|
+
if (entry.kind === "cmd-status") {
|
|
173116
|
+
if (entry.status !== Status2.Success) {
|
|
173117
|
+
logger244.info(
|
|
173118
|
+
`requestor ${request.command} status ${entry.status} for session ${String(request.fields.webRtcSessionId)}`
|
|
173119
|
+
);
|
|
173120
|
+
return false;
|
|
173121
|
+
}
|
|
173122
|
+
return true;
|
|
173123
|
+
}
|
|
173124
|
+
}
|
|
173125
|
+
}
|
|
173126
|
+
return true;
|
|
173127
|
+
} finally {
|
|
173128
|
+
await client.close().catch(() => {
|
|
173129
|
+
});
|
|
173130
|
+
}
|
|
173131
|
+
}
|
|
173132
|
+
function errText(err) {
|
|
173133
|
+
return err instanceof Error ? err.message : String(err);
|
|
173134
|
+
}
|
|
173135
|
+
|
|
173136
|
+
// src/plugins/builtin/camera/webrtc-provider-server.ts
|
|
173137
|
+
var logger245 = Logger.get("CameraWebRtc");
|
|
173138
|
+
var nextGlobalSessionId = 0;
|
|
173139
|
+
function mintSessionId() {
|
|
173140
|
+
for (let i = 0; i <= 65534; i++) {
|
|
173141
|
+
const id = nextGlobalSessionId;
|
|
173142
|
+
nextGlobalSessionId = nextGlobalSessionId >= 65534 ? 0 : nextGlobalSessionId + 1;
|
|
173143
|
+
if (!hasRequestor(id)) return id;
|
|
173144
|
+
}
|
|
173145
|
+
return nextGlobalSessionId;
|
|
173146
|
+
}
|
|
172964
173147
|
var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
172965
173148
|
solicitOffer(request) {
|
|
172966
|
-
const id =
|
|
173149
|
+
const id = mintSessionId();
|
|
172967
173150
|
this.trackSession(id, request.streamUsage, request.originatingEndpointId);
|
|
172968
|
-
|
|
173151
|
+
logger245.info(
|
|
172969
173152
|
`solicitOffer session=${id} (${this.state.entityId}), deferred offer`
|
|
172970
173153
|
);
|
|
172971
173154
|
void this.state.bridge.startSession(id, this.state.entityId, {
|
|
172972
173155
|
iceServers: request.iceServers,
|
|
172973
173156
|
iceTransportPolicy: request.iceTransportPolicy
|
|
172974
173157
|
}).catch(
|
|
172975
|
-
(err) =>
|
|
172976
|
-
`solicitOffer startSession failed for ${this.state.entityId}: ${
|
|
173158
|
+
(err) => logger245.info(
|
|
173159
|
+
`solicitOffer startSession failed for ${this.state.entityId}: ${errText2(err)}`
|
|
172977
173160
|
)
|
|
172978
173161
|
);
|
|
172979
173162
|
return { webRtcSessionId: id, deferredOffer: true };
|
|
172980
173163
|
}
|
|
172981
173164
|
async provideOffer(request) {
|
|
172982
|
-
const id = request.webRtcSessionId ??
|
|
172983
|
-
|
|
173165
|
+
const id = request.webRtcSessionId ?? mintSessionId();
|
|
173166
|
+
logger245.info(
|
|
172984
173167
|
`provideOffer entry: entityId=${this.state.entityId} session=${id} (sdp ${request.sdp.length} chars)`
|
|
172985
173168
|
);
|
|
172986
173169
|
if (request.webRtcSessionId == null) {
|
|
@@ -172990,6 +173173,15 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
172990
173173
|
request.originatingEndpointId ?? EndpointNumber(0)
|
|
172991
173174
|
);
|
|
172992
173175
|
}
|
|
173176
|
+
const requestorEndpoint = request.originatingEndpointId ?? EndpointNumber(0);
|
|
173177
|
+
const session = this.context.session;
|
|
173178
|
+
if (session) {
|
|
173179
|
+
registerRequestor(id, {
|
|
173180
|
+
session,
|
|
173181
|
+
requestorEndpoint,
|
|
173182
|
+
env: this.env
|
|
173183
|
+
});
|
|
173184
|
+
}
|
|
172993
173185
|
let answerSdp;
|
|
172994
173186
|
try {
|
|
172995
173187
|
answerSdp = await this.state.bridge.acceptControllerOffer(
|
|
@@ -173002,10 +173194,11 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
173002
173194
|
}
|
|
173003
173195
|
);
|
|
173004
173196
|
} catch (err) {
|
|
173005
|
-
const message =
|
|
173006
|
-
|
|
173197
|
+
const message = errText2(err);
|
|
173198
|
+
logger245.info(
|
|
173007
173199
|
`provideOffer failed for ${this.state.entityId} session=${id}: ${message}`
|
|
173008
173200
|
);
|
|
173201
|
+
unregisterRequestor(id);
|
|
173009
173202
|
this.state.currentSessions = this.state.currentSessions.filter(
|
|
173010
173203
|
(s) => s.id !== id
|
|
173011
173204
|
);
|
|
@@ -173014,14 +173207,26 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
173014
173207
|
StatusCode.Failure
|
|
173015
173208
|
);
|
|
173016
173209
|
}
|
|
173017
|
-
|
|
173018
|
-
`provideOffer answer computed for ${this.state.entityId} session=${id} (${answerSdp.length} chars);
|
|
173210
|
+
logger245.info(
|
|
173211
|
+
`provideOffer answer computed for ${this.state.entityId} session=${id} (${answerSdp.length} chars); delivering via requestor`
|
|
173019
173212
|
);
|
|
173020
|
-
|
|
173213
|
+
const bridge = this.state.bridge;
|
|
173214
|
+
const state = this.state;
|
|
173215
|
+
deliverAnswerDeferred(id, answerSdp, async () => {
|
|
173216
|
+
await bridge.endSession(id).catch(() => {
|
|
173217
|
+
});
|
|
173218
|
+
unregisterRequestor(id);
|
|
173219
|
+
try {
|
|
173220
|
+
state.currentSessions = state.currentSessions.filter(
|
|
173221
|
+
(s) => s.id !== id
|
|
173222
|
+
);
|
|
173223
|
+
} catch {
|
|
173224
|
+
}
|
|
173225
|
+
});
|
|
173021
173226
|
return { webRtcSessionId: id };
|
|
173022
173227
|
}
|
|
173023
173228
|
provideAnswer(request) {
|
|
173024
|
-
|
|
173229
|
+
logger245.info(
|
|
173025
173230
|
`provideAnswer session=${request.webRtcSessionId} (sdp ${request.sdp.length} chars, ${this.state.entityId})`
|
|
173026
173231
|
);
|
|
173027
173232
|
return this.state.bridge.acceptControllerAnswer(
|
|
@@ -173030,7 +173235,7 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
173030
173235
|
);
|
|
173031
173236
|
}
|
|
173032
173237
|
async provideIceCandidates(request) {
|
|
173033
|
-
|
|
173238
|
+
logger245.info(
|
|
173034
173239
|
`provideIceCandidates session=${request.webRtcSessionId}: ${request.iceCandidates.length} candidate(s) (${this.state.entityId})`
|
|
173035
173240
|
);
|
|
173036
173241
|
for (const c of request.iceCandidates) {
|
|
@@ -173043,16 +173248,21 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
173043
173248
|
}
|
|
173044
173249
|
}
|
|
173045
173250
|
async endSession(request) {
|
|
173046
|
-
|
|
173251
|
+
logger245.info(
|
|
173047
173252
|
`endSession session=${request.webRtcSessionId} (${this.state.entityId})`
|
|
173048
173253
|
);
|
|
173049
173254
|
await this.state.bridge.endSession(request.webRtcSessionId);
|
|
173255
|
+
unregisterRequestor(request.webRtcSessionId);
|
|
173050
173256
|
this.state.currentSessions = this.state.currentSessions.filter(
|
|
173051
173257
|
(s) => s.id !== request.webRtcSessionId
|
|
173052
173258
|
);
|
|
173053
173259
|
}
|
|
173054
173260
|
trackSession(id, streamUsage, peerEndpointId) {
|
|
173055
173261
|
const session = this.context.session;
|
|
173262
|
+
const fabricIndex = session?.associatedFabric?.fabricIndex;
|
|
173263
|
+
if (fabricIndex == null) {
|
|
173264
|
+
return;
|
|
173265
|
+
}
|
|
173056
173266
|
this.state.currentSessions = [
|
|
173057
173267
|
...this.state.currentSessions,
|
|
173058
173268
|
{
|
|
@@ -173061,19 +173271,18 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
173061
173271
|
peerEndpointId,
|
|
173062
173272
|
streamUsage,
|
|
173063
173273
|
metadataEnabled: false,
|
|
173064
|
-
fabricIndex
|
|
173274
|
+
fabricIndex
|
|
173065
173275
|
}
|
|
173066
173276
|
];
|
|
173067
173277
|
}
|
|
173068
173278
|
};
|
|
173069
|
-
function
|
|
173279
|
+
function errText2(err) {
|
|
173070
173280
|
return err instanceof Error ? err.message : String(err);
|
|
173071
173281
|
}
|
|
173072
173282
|
((CameraWebRtcProviderServer2) => {
|
|
173073
173283
|
class State extends WebRtcTransportProviderServer.State {
|
|
173074
173284
|
bridge;
|
|
173075
173285
|
entityId;
|
|
173076
|
-
nextSessionId = 1;
|
|
173077
173286
|
}
|
|
173078
173287
|
CameraWebRtcProviderServer2.State = State;
|
|
173079
173288
|
})(CameraWebRtcProviderServer || (CameraWebRtcProviderServer = {}));
|
|
@@ -173092,8 +173301,7 @@ function createCameraEndpointType(bridge, entityId, sensor = defaultSensorParams
|
|
|
173092
173301
|
webRtcTransportProvider: {
|
|
173093
173302
|
bridge,
|
|
173094
173303
|
entityId,
|
|
173095
|
-
currentSessions: []
|
|
173096
|
-
nextSessionId: 1
|
|
173304
|
+
currentSessions: []
|
|
173097
173305
|
},
|
|
173098
173306
|
cameraAvStreamManagement: {
|
|
173099
173307
|
bridge,
|
|
@@ -173161,7 +173369,7 @@ import {
|
|
|
173161
173369
|
createLongLivedTokenAuth as createLongLivedTokenAuth2
|
|
173162
173370
|
} from "home-assistant-js-websocket";
|
|
173163
173371
|
import { RTCPeerConnection } from "werift";
|
|
173164
|
-
var
|
|
173372
|
+
var logger246 = Logger.get("CameraWebRtc");
|
|
173165
173373
|
var DEFAULT_HA_WEBRTC_TIMEOUT_MS = 15e3;
|
|
173166
173374
|
var haWebRtcTimeoutMs = DEFAULT_HA_WEBRTC_TIMEOUT_MS;
|
|
173167
173375
|
var WebRtcBridge = class {
|
|
@@ -173200,6 +173408,7 @@ var WebRtcBridge = class {
|
|
|
173200
173408
|
controllerPeer.addTransceiver("video", { direction: "sendonly" })
|
|
173201
173409
|
);
|
|
173202
173410
|
this.forwardHaTracks(haPeer, senders, entityId);
|
|
173411
|
+
await this.closeExistingPeers(matterSessionId);
|
|
173203
173412
|
this.sessions.set(matterSessionId, { entityId, haPeer, controllerPeer });
|
|
173204
173413
|
try {
|
|
173205
173414
|
haPeer.addTransceiver("video", { direction: "recvonly" });
|
|
@@ -173207,7 +173416,7 @@ var WebRtcBridge = class {
|
|
|
173207
173416
|
const haOffer = await haPeer.createOffer();
|
|
173208
173417
|
await haPeer.setLocalDescription(haOffer);
|
|
173209
173418
|
const haOfferSdp = this.localSdp(haPeer);
|
|
173210
|
-
|
|
173419
|
+
logger246.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
|
|
173211
173420
|
const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
|
|
173212
173421
|
entityId,
|
|
173213
173422
|
haOfferSdp,
|
|
@@ -173230,12 +173439,12 @@ var WebRtcBridge = class {
|
|
|
173230
173439
|
const controllerOffer = await controllerPeer.createOffer();
|
|
173231
173440
|
await controllerPeer.setLocalDescription(controllerOffer);
|
|
173232
173441
|
const sdp = this.localSdp(controllerPeer);
|
|
173233
|
-
|
|
173442
|
+
logger246.info(
|
|
173234
173443
|
`controller offer created for ${entityId} (${sdp.length} chars)`
|
|
173235
173444
|
);
|
|
173236
173445
|
return { sdp, iceCandidates };
|
|
173237
173446
|
} catch (err) {
|
|
173238
|
-
|
|
173447
|
+
logger246.info(`startSession failed for ${entityId}: ${errText3(err)}`);
|
|
173239
173448
|
await this.endSession(matterSessionId);
|
|
173240
173449
|
throw err;
|
|
173241
173450
|
}
|
|
@@ -173257,6 +173466,7 @@ var WebRtcBridge = class {
|
|
|
173257
173466
|
);
|
|
173258
173467
|
}
|
|
173259
173468
|
this.forwardHaTracks(haPeer, senders, entityId);
|
|
173469
|
+
await this.closeExistingPeers(matterSessionId);
|
|
173260
173470
|
this.sessions.set(matterSessionId, { entityId, haPeer, controllerPeer });
|
|
173261
173471
|
try {
|
|
173262
173472
|
haPeer.addTransceiver("video", { direction: "recvonly" });
|
|
@@ -173264,7 +173474,7 @@ var WebRtcBridge = class {
|
|
|
173264
173474
|
const haOffer = await haPeer.createOffer();
|
|
173265
173475
|
await haPeer.setLocalDescription(haOffer);
|
|
173266
173476
|
const haOfferSdp = this.localSdp(haPeer);
|
|
173267
|
-
|
|
173477
|
+
logger246.info(`HA offer sent for ${entityId} (${haOfferSdp.length} chars)`);
|
|
173268
173478
|
const { answer, sessionId, unsubscribe } = await this.requestHaWebRtc(
|
|
173269
173479
|
entityId,
|
|
173270
173480
|
haOfferSdp,
|
|
@@ -173283,13 +173493,13 @@ var WebRtcBridge = class {
|
|
|
173283
173493
|
const controllerAnswer = await controllerPeer.createAnswer();
|
|
173284
173494
|
await controllerPeer.setLocalDescription(controllerAnswer);
|
|
173285
173495
|
const answerSdp = this.localSdp(controllerPeer);
|
|
173286
|
-
|
|
173496
|
+
logger246.info(
|
|
173287
173497
|
`controller answer created for ${entityId} (${answerSdp.length} chars)`
|
|
173288
173498
|
);
|
|
173289
173499
|
return answerSdp;
|
|
173290
173500
|
} catch (err) {
|
|
173291
|
-
|
|
173292
|
-
`acceptControllerOffer failed for ${entityId}: ${
|
|
173501
|
+
logger246.info(
|
|
173502
|
+
`acceptControllerOffer failed for ${entityId}: ${errText3(err)}`
|
|
173293
173503
|
);
|
|
173294
173504
|
await this.endSession(matterSessionId);
|
|
173295
173505
|
throw err;
|
|
@@ -173299,14 +173509,14 @@ var WebRtcBridge = class {
|
|
|
173299
173509
|
async acceptControllerAnswer(matterSessionId, sdp) {
|
|
173300
173510
|
const session = this.sessions.get(matterSessionId);
|
|
173301
173511
|
if (!session) return;
|
|
173302
|
-
|
|
173512
|
+
logger246.debug(`controller answer applied for ${session.entityId}`);
|
|
173303
173513
|
await session.controllerPeer.setRemoteDescription({ type: "answer", sdp });
|
|
173304
173514
|
}
|
|
173305
173515
|
/** Add a remote ICE candidate from the Matter controller. */
|
|
173306
173516
|
async addControllerIceCandidate(matterSessionId, candidate, sdpMid, sdpMLineIndex) {
|
|
173307
173517
|
const session = this.sessions.get(matterSessionId);
|
|
173308
173518
|
if (!session) return;
|
|
173309
|
-
|
|
173519
|
+
logger246.debug(
|
|
173310
173520
|
`controller ICE candidate for ${session.entityId}: ${candidate}`
|
|
173311
173521
|
);
|
|
173312
173522
|
await session.controllerPeer.addIceCandidate({
|
|
@@ -173315,32 +173525,53 @@ var WebRtcBridge = class {
|
|
|
173315
173525
|
sdpMLineIndex: sdpMLineIndex ?? void 0
|
|
173316
173526
|
});
|
|
173317
173527
|
}
|
|
173528
|
+
// Close the peers of a session we are about to overwrite. Leaves no map
|
|
173529
|
+
// entry; the caller replaces it with fresh peers under the same id.
|
|
173530
|
+
async closeExistingPeers(matterSessionId) {
|
|
173531
|
+
const prior = this.sessions.get(matterSessionId);
|
|
173532
|
+
if (!prior) return;
|
|
173533
|
+
logger246.info(
|
|
173534
|
+
`replacing session ${matterSessionId} (${prior.entityId}), closing prior peers`
|
|
173535
|
+
);
|
|
173536
|
+
if (prior.haUnsubscribe) {
|
|
173537
|
+
await Promise.resolve(prior.haUnsubscribe()).catch(
|
|
173538
|
+
(err) => logger246.debug(`HA unsubscribe failed: ${errText3(err)}`)
|
|
173539
|
+
);
|
|
173540
|
+
}
|
|
173541
|
+
await prior.haPeer.close().catch(() => {
|
|
173542
|
+
});
|
|
173543
|
+
await prior.controllerPeer.close().catch(() => {
|
|
173544
|
+
});
|
|
173545
|
+
await this.stopHaStream(prior).catch(() => {
|
|
173546
|
+
});
|
|
173547
|
+
}
|
|
173318
173548
|
async endSession(matterSessionId) {
|
|
173319
173549
|
const session = this.sessions.get(matterSessionId);
|
|
173320
173550
|
if (!session) return;
|
|
173321
|
-
|
|
173551
|
+
logger246.info(`ending session ${matterSessionId} (${session.entityId})`);
|
|
173322
173552
|
this.sessions.delete(matterSessionId);
|
|
173323
173553
|
if (session.haUnsubscribe) {
|
|
173324
173554
|
await Promise.resolve(session.haUnsubscribe()).catch(
|
|
173325
|
-
(err) =>
|
|
173555
|
+
(err) => logger246.debug(`HA unsubscribe failed: ${errText3(err)}`)
|
|
173326
173556
|
);
|
|
173327
173557
|
}
|
|
173328
173558
|
await session.haPeer.close().catch(() => {
|
|
173329
173559
|
});
|
|
173330
173560
|
await session.controllerPeer.close().catch(() => {
|
|
173331
173561
|
});
|
|
173332
|
-
|
|
173333
|
-
|
|
173334
|
-
|
|
173335
|
-
|
|
173336
|
-
|
|
173337
|
-
|
|
173338
|
-
|
|
173339
|
-
|
|
173340
|
-
|
|
173341
|
-
|
|
173342
|
-
|
|
173343
|
-
|
|
173562
|
+
await this.stopHaStream(session).catch(() => {
|
|
173563
|
+
});
|
|
173564
|
+
}
|
|
173565
|
+
// Tell HA to stop the stream if we tracked an HA session id. Best effort.
|
|
173566
|
+
async stopHaStream(session) {
|
|
173567
|
+
if (!session.haSessionId) return;
|
|
173568
|
+
const conn = await this.ha();
|
|
173569
|
+
await conn.sendMessagePromise({
|
|
173570
|
+
type: "camera/webrtc/candidate",
|
|
173571
|
+
entity_id: session.entityId,
|
|
173572
|
+
session_id: session.haSessionId,
|
|
173573
|
+
candidate: { candidate: "" }
|
|
173574
|
+
});
|
|
173344
173575
|
}
|
|
173345
173576
|
// Grab a still JPEG via HA's camera proxy (for CaptureSnapshot).
|
|
173346
173577
|
async snapshot(entityId) {
|
|
@@ -173351,11 +173582,11 @@ var WebRtcBridge = class {
|
|
|
173351
173582
|
headers: { Authorization: `Bearer ${this.config.haToken}` }
|
|
173352
173583
|
});
|
|
173353
173584
|
} catch (err) {
|
|
173354
|
-
|
|
173585
|
+
logger246.info(`snapshot fetch failed for ${entityId}: ${errText3(err)}`);
|
|
173355
173586
|
throw err;
|
|
173356
173587
|
}
|
|
173357
173588
|
if (!res.ok) {
|
|
173358
|
-
|
|
173589
|
+
logger246.info(
|
|
173359
173590
|
`snapshot fetch failed for ${entityId}: camera_proxy ${res.status}`
|
|
173360
173591
|
);
|
|
173361
173592
|
throw new Error(`HA camera_proxy ${entityId}: ${res.status}`);
|
|
@@ -173372,10 +173603,10 @@ var WebRtcBridge = class {
|
|
|
173372
173603
|
// Forward every track HA sends into the matching pre-added controller sender.
|
|
173373
173604
|
forwardHaTracks(haPeer, senders, entityId) {
|
|
173374
173605
|
haPeer.onTrack.subscribe((track) => {
|
|
173375
|
-
|
|
173606
|
+
logger246.info(`onTrack ${track.kind} from HA (${entityId})`);
|
|
173376
173607
|
const transceiver = senders.get(track.kind);
|
|
173377
173608
|
if (!transceiver) {
|
|
173378
|
-
|
|
173609
|
+
logger246.info(
|
|
173379
173610
|
`no controller transceiver for ${track.kind} (${entityId})`
|
|
173380
173611
|
);
|
|
173381
173612
|
return;
|
|
@@ -173384,7 +173615,7 @@ var WebRtcBridge = class {
|
|
|
173384
173615
|
track.onReceiveRtp.subscribe((rtp) => {
|
|
173385
173616
|
if (!firstLogged) {
|
|
173386
173617
|
firstLogged = true;
|
|
173387
|
-
|
|
173618
|
+
logger246.info(`first RTP forwarded for ${track.kind} (${entityId})`);
|
|
173388
173619
|
}
|
|
173389
173620
|
transceiver.sender.sendRtp(rtp);
|
|
173390
173621
|
});
|
|
@@ -173393,10 +173624,10 @@ var WebRtcBridge = class {
|
|
|
173393
173624
|
// Log connection/ice state transitions (these events fire on change only).
|
|
173394
173625
|
wireStateLogging(peer, label, entityId) {
|
|
173395
173626
|
peer.connectionStateChange.subscribe(
|
|
173396
|
-
(s) =>
|
|
173627
|
+
(s) => logger246.info(`${label} connectionState=${s} (${entityId})`)
|
|
173397
173628
|
);
|
|
173398
173629
|
peer.iceConnectionStateChange.subscribe(
|
|
173399
|
-
(s) =>
|
|
173630
|
+
(s) => logger246.info(`${label} iceConnectionState=${s} (${entityId})`)
|
|
173400
173631
|
);
|
|
173401
173632
|
}
|
|
173402
173633
|
// Map the Matter ICE struct onto werift's config. Only the controller peer
|
|
@@ -173410,11 +173641,11 @@ var WebRtcBridge = class {
|
|
|
173410
173641
|
}))
|
|
173411
173642
|
);
|
|
173412
173643
|
if (iceServers.length === 0) {
|
|
173413
|
-
|
|
173644
|
+
logger246.info(`controller peer using default ICE servers (${entityId})`);
|
|
173414
173645
|
return void 0;
|
|
173415
173646
|
}
|
|
173416
173647
|
const policy = ice?.iceTransportPolicy === "relay" || ice?.iceTransportPolicy === "all" ? ice.iceTransportPolicy : void 0;
|
|
173417
|
-
|
|
173648
|
+
logger246.info(
|
|
173418
173649
|
`controller peer using ${iceServers.length} controller ICE server(s)${policy ? ` policy=${policy}` : ""} (${entityId})`
|
|
173419
173650
|
);
|
|
173420
173651
|
return policy ? { iceServers, iceTransportPolicy: policy } : { iceServers };
|
|
@@ -173428,14 +173659,14 @@ var WebRtcBridge = class {
|
|
|
173428
173659
|
feedHaCandidate(entityId, haPeer, candidate) {
|
|
173429
173660
|
const value = candidate?.candidate;
|
|
173430
173661
|
if (!value) return;
|
|
173431
|
-
|
|
173662
|
+
logger246.debug(`HA ICE candidate for ${entityId}: ${value}`);
|
|
173432
173663
|
void haPeer.addIceCandidate({
|
|
173433
173664
|
candidate: value,
|
|
173434
173665
|
sdpMid: candidate?.sdpMid ?? void 0,
|
|
173435
173666
|
sdpMLineIndex: candidate?.sdpMLineIndex ?? void 0
|
|
173436
173667
|
}).catch(
|
|
173437
|
-
(e) =>
|
|
173438
|
-
`HA addIceCandidate failed for ${entityId}: ${
|
|
173668
|
+
(e) => logger246.debug(
|
|
173669
|
+
`HA addIceCandidate failed for ${entityId}: ${errText3(e)}`
|
|
173439
173670
|
)
|
|
173440
173671
|
);
|
|
173441
173672
|
}
|
|
@@ -173463,7 +173694,7 @@ var WebRtcBridge = class {
|
|
|
173463
173694
|
reject(err);
|
|
173464
173695
|
});
|
|
173465
173696
|
timer = setTimeout(() => {
|
|
173466
|
-
|
|
173697
|
+
logger246.info(
|
|
173467
173698
|
`HA WebRTC timed out after ${haWebRtcTimeoutMs}ms for ${entityId}`
|
|
173468
173699
|
);
|
|
173469
173700
|
fail(
|
|
@@ -173481,7 +173712,7 @@ var WebRtcBridge = class {
|
|
|
173481
173712
|
if (msg.session_id) sessionId = msg.session_id;
|
|
173482
173713
|
const ans = msg.answer;
|
|
173483
173714
|
settle(() => {
|
|
173484
|
-
|
|
173715
|
+
logger246.info(
|
|
173485
173716
|
`HA answer received for ${entityId} (${ans.length} chars)`
|
|
173486
173717
|
);
|
|
173487
173718
|
resolve11(ans);
|
|
@@ -173490,7 +173721,7 @@ var WebRtcBridge = class {
|
|
|
173490
173721
|
break;
|
|
173491
173722
|
case "error": {
|
|
173492
173723
|
const detail = msg.message ?? msg.code ?? "unknown error";
|
|
173493
|
-
|
|
173724
|
+
logger246.info(`HA WebRTC error for ${entityId}: ${detail}`);
|
|
173494
173725
|
fail(new Error(`HA WebRTC error: ${detail}`));
|
|
173495
173726
|
break;
|
|
173496
173727
|
}
|
|
@@ -173517,7 +173748,7 @@ function offerKinds(sdp) {
|
|
|
173517
173748
|
}
|
|
173518
173749
|
return kinds;
|
|
173519
173750
|
}
|
|
173520
|
-
function
|
|
173751
|
+
function errText3(err) {
|
|
173521
173752
|
return err instanceof Error ? err.message : String(err);
|
|
173522
173753
|
}
|
|
173523
173754
|
|
|
@@ -173652,6 +173883,7 @@ var CameraPlugin = class {
|
|
|
173652
173883
|
await this.bridge?.close().catch(() => {
|
|
173653
173884
|
});
|
|
173654
173885
|
this.bridge = void 0;
|
|
173886
|
+
unregisterAllRequestors();
|
|
173655
173887
|
}
|
|
173656
173888
|
};
|
|
173657
173889
|
|
|
@@ -173665,7 +173897,7 @@ import {
|
|
|
173665
173897
|
getCollection
|
|
173666
173898
|
} from "home-assistant-js-websocket";
|
|
173667
173899
|
import { atLeastHaVersion } from "home-assistant-js-websocket/dist/util.js";
|
|
173668
|
-
var
|
|
173900
|
+
var logger247 = Logger.get("SubscribeEntities");
|
|
173669
173901
|
function processEvent(store, updates) {
|
|
173670
173902
|
const state = { ...store.state };
|
|
173671
173903
|
if (updates.a) {
|
|
@@ -173691,7 +173923,7 @@ function processEvent(store, updates) {
|
|
|
173691
173923
|
for (const entityId in updates.c) {
|
|
173692
173924
|
let entityState = state[entityId];
|
|
173693
173925
|
if (!entityState) {
|
|
173694
|
-
|
|
173926
|
+
logger247.warn("Received state update for unknown entity", entityId);
|
|
173695
173927
|
continue;
|
|
173696
173928
|
}
|
|
173697
173929
|
entityState = { ...entityState };
|
|
@@ -173780,7 +174012,7 @@ var subscribeEntities = (conn, onChange, entityIds) => {
|
|
|
173780
174012
|
// src/services/bridges/entity-isolation-service.ts
|
|
173781
174013
|
init_esm();
|
|
173782
174014
|
init_diagnostic_event_bus();
|
|
173783
|
-
var
|
|
174015
|
+
var logger248 = Logger.get("EntityIsolation");
|
|
173784
174016
|
var EntityIsolationServiceImpl = class {
|
|
173785
174017
|
isolatedEntities = /* @__PURE__ */ new Map();
|
|
173786
174018
|
isolationCallbacks = /* @__PURE__ */ new Map();
|
|
@@ -173845,13 +174077,13 @@ var EntityIsolationServiceImpl = class {
|
|
|
173845
174077
|
}
|
|
173846
174078
|
const parsed = this.parseEndpointPath(msg);
|
|
173847
174079
|
if (!parsed) {
|
|
173848
|
-
|
|
174080
|
+
logger248.warn("Could not parse entity from error:", msg);
|
|
173849
174081
|
return false;
|
|
173850
174082
|
}
|
|
173851
174083
|
const { bridgeId, entityName } = parsed;
|
|
173852
174084
|
const callback = this.isolationCallbacks.get(bridgeId);
|
|
173853
174085
|
if (!callback) {
|
|
173854
|
-
|
|
174086
|
+
logger248.warn(
|
|
173855
174087
|
`No isolation callback registered for bridge ${bridgeId}, entity: ${entityName}`
|
|
173856
174088
|
);
|
|
173857
174089
|
return false;
|
|
@@ -173866,7 +174098,7 @@ var EntityIsolationServiceImpl = class {
|
|
|
173866
174098
|
reason,
|
|
173867
174099
|
failedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
173868
174100
|
});
|
|
173869
|
-
|
|
174101
|
+
logger248.warn(
|
|
173870
174102
|
`Isolating entity "${entityName}" from bridge ${bridgeId} due to: ${reason}`
|
|
173871
174103
|
);
|
|
173872
174104
|
diagnosticEventBus.emit("entity_error", `Entity isolated: ${entityName}`, {
|
|
@@ -173878,7 +174110,7 @@ var EntityIsolationServiceImpl = class {
|
|
|
173878
174110
|
await callback(entityName);
|
|
173879
174111
|
return true;
|
|
173880
174112
|
} catch (e) {
|
|
173881
|
-
|
|
174113
|
+
logger248.error(`Failed to isolate entity ${entityName}:`, e);
|
|
173882
174114
|
return false;
|
|
173883
174115
|
}
|
|
173884
174116
|
}
|
|
@@ -173911,10 +174143,10 @@ var EntityIsolationService = new EntityIsolationServiceImpl();
|
|
|
173911
174143
|
var MAX_ENTITY_ID_LENGTH = 150;
|
|
173912
174144
|
var ENDPOINT_REMOVAL_GRACE_MS = 6e4;
|
|
173913
174145
|
var BridgeEndpointManager = class extends Service {
|
|
173914
|
-
constructor(client,
|
|
174146
|
+
constructor(client, registry3, mappingStorage, identityStorage, bridgeId, log, pluginManager, pluginRegistry, pluginInstaller) {
|
|
173915
174147
|
super("BridgeEndpointManager");
|
|
173916
174148
|
this.client = client;
|
|
173917
|
-
this.registry =
|
|
174149
|
+
this.registry = registry3;
|
|
173918
174150
|
this.mappingStorage = mappingStorage;
|
|
173919
174151
|
this.identityStorage = identityStorage;
|
|
173920
174152
|
this.bridgeId = bridgeId;
|
|
@@ -174625,8 +174857,8 @@ init_send_ha_message();
|
|
|
174625
174857
|
import { callService as callService2 } from "home-assistant-js-websocket";
|
|
174626
174858
|
import { keys as keys2, pickBy, values as values3 } from "lodash-es";
|
|
174627
174859
|
var BridgeRegistry = class _BridgeRegistry {
|
|
174628
|
-
constructor(
|
|
174629
|
-
this.registry =
|
|
174860
|
+
constructor(registry3, dataProvider, client) {
|
|
174861
|
+
this.registry = registry3;
|
|
174630
174862
|
this.dataProvider = dataProvider;
|
|
174631
174863
|
this.client = client;
|
|
174632
174864
|
this.refresh();
|
|
@@ -175396,11 +175628,11 @@ function makeWarmStartState(state, now = (/* @__PURE__ */ new Date()).toISOStrin
|
|
|
175396
175628
|
return { ...state, last_updated: now };
|
|
175397
175629
|
}
|
|
175398
175630
|
var ServerModeBridge = class {
|
|
175399
|
-
constructor(
|
|
175631
|
+
constructor(logger251, dataProvider, endpointManager, server) {
|
|
175400
175632
|
this.dataProvider = dataProvider;
|
|
175401
175633
|
this.endpointManager = endpointManager;
|
|
175402
175634
|
this.server = server;
|
|
175403
|
-
this.log =
|
|
175635
|
+
this.log = logger251.get(`ServerModeBridge / ${dataProvider.id}`);
|
|
175404
175636
|
}
|
|
175405
175637
|
dataProvider;
|
|
175406
175638
|
endpointManager;
|
|
@@ -176430,12 +176662,12 @@ function ServerModeVacuumDevice(homeAssistantEntity, includeOnOff = false, clean
|
|
|
176430
176662
|
}
|
|
176431
176663
|
|
|
176432
176664
|
// src/matter/endpoints/server-mode-vacuum-endpoint.ts
|
|
176433
|
-
var
|
|
176665
|
+
var logger249 = Logger.get("ServerModeVacuumEndpoint");
|
|
176434
176666
|
var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEndpoint {
|
|
176435
|
-
static async create(
|
|
176436
|
-
const deviceRegistry =
|
|
176437
|
-
let state =
|
|
176438
|
-
const entity =
|
|
176667
|
+
static async create(registry3, entityId, mapping, endpointId) {
|
|
176668
|
+
const deviceRegistry = registry3.deviceOf(entityId);
|
|
176669
|
+
let state = registry3.initialState(entityId);
|
|
176670
|
+
const entity = registry3.entity(entityId);
|
|
176439
176671
|
if (!state) {
|
|
176440
176672
|
return void 0;
|
|
176441
176673
|
}
|
|
@@ -176443,12 +176675,12 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176443
176675
|
if (mapping?.disableBatteryMapping && mapping.batteryEntity) {
|
|
176444
176676
|
effectiveMapping = { ...mapping, batteryEntity: void 0 };
|
|
176445
176677
|
}
|
|
176446
|
-
|
|
176678
|
+
logger249.info(
|
|
176447
176679
|
`${entityId}: device_id=${entity.device_id}, manualBattery=${mapping?.batteryEntity ?? "none"}`
|
|
176448
176680
|
);
|
|
176449
176681
|
if (entity.device_id) {
|
|
176450
176682
|
if (!mapping?.batteryEntity && !mapping?.disableBatteryMapping) {
|
|
176451
|
-
const batteryEntityId =
|
|
176683
|
+
const batteryEntityId = registry3.findBatteryEntityForDevice(
|
|
176452
176684
|
entity.device_id
|
|
176453
176685
|
);
|
|
176454
176686
|
if (batteryEntityId && batteryEntityId !== entityId) {
|
|
@@ -176457,22 +176689,22 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176457
176689
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176458
176690
|
batteryEntity: batteryEntityId
|
|
176459
176691
|
};
|
|
176460
|
-
|
|
176461
|
-
|
|
176692
|
+
registry3.markBatteryEntityUsed(batteryEntityId);
|
|
176693
|
+
logger249.info(`${entityId}: Auto-assigned battery ${batteryEntityId}`);
|
|
176462
176694
|
} else {
|
|
176463
176695
|
const attrs = state.attributes;
|
|
176464
176696
|
if (attrs.battery_level != null || attrs.battery != null) {
|
|
176465
|
-
|
|
176697
|
+
logger249.info(
|
|
176466
176698
|
`${entityId}: No battery entity found, using battery attribute from vacuum state`
|
|
176467
176699
|
);
|
|
176468
176700
|
} else {
|
|
176469
|
-
|
|
176701
|
+
logger249.warn(
|
|
176470
176702
|
`${entityId}: No battery entity found for device ${entity.device_id}`
|
|
176471
176703
|
);
|
|
176472
176704
|
}
|
|
176473
176705
|
}
|
|
176474
176706
|
}
|
|
176475
|
-
const vacuumEntities =
|
|
176707
|
+
const vacuumEntities = registry3.findVacuumSelectEntities(
|
|
176476
176708
|
entity.device_id
|
|
176477
176709
|
);
|
|
176478
176710
|
if (!effectiveMapping?.cleaningModeEntity && vacuumEntities.cleaningModeEntity) {
|
|
@@ -176481,7 +176713,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176481
176713
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176482
176714
|
cleaningModeEntity: vacuumEntities.cleaningModeEntity
|
|
176483
176715
|
};
|
|
176484
|
-
|
|
176716
|
+
logger249.info(
|
|
176485
176717
|
`${entityId}: Auto-assigned cleaningMode ${vacuumEntities.cleaningModeEntity}`
|
|
176486
176718
|
);
|
|
176487
176719
|
}
|
|
@@ -176491,7 +176723,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176491
176723
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176492
176724
|
suctionLevelEntity: vacuumEntities.suctionLevelEntity
|
|
176493
176725
|
};
|
|
176494
|
-
|
|
176726
|
+
logger249.info(
|
|
176495
176727
|
`${entityId}: Auto-assigned suctionLevel ${vacuumEntities.suctionLevelEntity}`
|
|
176496
176728
|
);
|
|
176497
176729
|
}
|
|
@@ -176501,7 +176733,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176501
176733
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176502
176734
|
mopIntensityEntity: vacuumEntities.mopIntensityEntity
|
|
176503
176735
|
};
|
|
176504
|
-
|
|
176736
|
+
logger249.info(
|
|
176505
176737
|
`${entityId}: Auto-assigned mopIntensity ${vacuumEntities.mopIntensityEntity}`
|
|
176506
176738
|
);
|
|
176507
176739
|
}
|
|
@@ -176511,12 +176743,12 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176511
176743
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176512
176744
|
currentRoomEntity: vacuumEntities.currentRoomEntity
|
|
176513
176745
|
};
|
|
176514
|
-
|
|
176746
|
+
logger249.info(
|
|
176515
176747
|
`${entityId}: Auto-assigned currentRoom ${vacuumEntities.currentRoomEntity}`
|
|
176516
176748
|
);
|
|
176517
176749
|
}
|
|
176518
176750
|
const supportedFeatures = state.attributes.supported_features ?? 0;
|
|
176519
|
-
const cleanAreaRooms = await
|
|
176751
|
+
const cleanAreaRooms = await registry3.resolveCleanAreaRooms(
|
|
176520
176752
|
entityId,
|
|
176521
176753
|
supportedFeatures
|
|
176522
176754
|
);
|
|
@@ -176526,13 +176758,13 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176526
176758
|
entityId: effectiveMapping?.entityId ?? entityId,
|
|
176527
176759
|
cleanAreaRooms
|
|
176528
176760
|
};
|
|
176529
|
-
|
|
176761
|
+
logger249.info(
|
|
176530
176762
|
`${entityId}: Using ${cleanAreaRooms.length} HA areas via CLEAN_AREA`
|
|
176531
176763
|
);
|
|
176532
176764
|
}
|
|
176533
176765
|
const vacAttrs = state.attributes;
|
|
176534
176766
|
if (cleanAreaRooms.length === 0 && !vacAttrs.rooms && !vacAttrs.segments && !vacAttrs.room_mapping) {
|
|
176535
|
-
const valetudoRooms =
|
|
176767
|
+
const valetudoRooms = registry3.findValetudoMapSegments(
|
|
176536
176768
|
entity.device_id
|
|
176537
176769
|
);
|
|
176538
176770
|
if (valetudoRooms.length > 0) {
|
|
@@ -176547,11 +176779,11 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176547
176779
|
rooms: roomsObj
|
|
176548
176780
|
}
|
|
176549
176781
|
};
|
|
176550
|
-
|
|
176782
|
+
logger249.info(
|
|
176551
176783
|
`${entityId}: Auto-detected ${valetudoRooms.length} Valetudo segments`
|
|
176552
176784
|
);
|
|
176553
176785
|
} else {
|
|
176554
|
-
const roborockRooms = await
|
|
176786
|
+
const roborockRooms = await registry3.resolveRoborockRooms(entityId);
|
|
176555
176787
|
if (roborockRooms.length > 0) {
|
|
176556
176788
|
const roomsObj = {};
|
|
176557
176789
|
for (const r of roborockRooms) {
|
|
@@ -176564,14 +176796,14 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176564
176796
|
rooms: roomsObj
|
|
176565
176797
|
}
|
|
176566
176798
|
};
|
|
176567
|
-
|
|
176799
|
+
logger249.info(
|
|
176568
176800
|
`${entityId}: Auto-detected ${roborockRooms.length} Roborock rooms`
|
|
176569
176801
|
);
|
|
176570
176802
|
}
|
|
176571
176803
|
}
|
|
176572
176804
|
}
|
|
176573
176805
|
} else {
|
|
176574
|
-
|
|
176806
|
+
logger249.warn(`${entityId}: No device_id, cannot auto-assign battery`);
|
|
176575
176807
|
}
|
|
176576
176808
|
const payload = {
|
|
176577
176809
|
entity_id: entityId,
|
|
@@ -176582,7 +176814,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176582
176814
|
const vacAttrsForClean = state.attributes;
|
|
176583
176815
|
let cleaningModeOptions;
|
|
176584
176816
|
if (effectiveMapping?.cleaningModeEntity) {
|
|
176585
|
-
const cmState =
|
|
176817
|
+
const cmState = registry3.initialState(
|
|
176586
176818
|
effectiveMapping.cleaningModeEntity
|
|
176587
176819
|
);
|
|
176588
176820
|
cleaningModeOptions = cmState?.attributes?.options;
|
|
@@ -176602,7 +176834,7 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176602
176834
|
customName,
|
|
176603
176835
|
mapping: effectiveMapping
|
|
176604
176836
|
},
|
|
176605
|
-
|
|
176837
|
+
registry3.isServerModeVacuumOnOffEnabled(),
|
|
176606
176838
|
cleaningModeOptions
|
|
176607
176839
|
);
|
|
176608
176840
|
if (!endpointType) {
|
|
@@ -176644,11 +176876,11 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176644
176876
|
}
|
|
176645
176877
|
if (mappedChanged) {
|
|
176646
176878
|
this.pendingMappedChange = true;
|
|
176647
|
-
|
|
176879
|
+
logger249.debug(
|
|
176648
176880
|
`Mapped entity change detected for ${this.entityId}, forcing update`
|
|
176649
176881
|
);
|
|
176650
176882
|
}
|
|
176651
|
-
|
|
176883
|
+
logger249.debug(
|
|
176652
176884
|
`State update received for ${this.entityId}: state=${state.state}`
|
|
176653
176885
|
);
|
|
176654
176886
|
this.lastState = state;
|
|
@@ -176688,11 +176920,11 @@ var ServerModeVacuumEndpoint = class _ServerModeVacuumEndpoint extends EntityEnd
|
|
|
176688
176920
|
// src/services/bridges/server-mode-endpoint-manager.ts
|
|
176689
176921
|
var MAX_SERVER_MODE_DEVICES = 10;
|
|
176690
176922
|
var ServerModeEndpointManager = class extends Service {
|
|
176691
|
-
constructor(serverNode, client,
|
|
176923
|
+
constructor(serverNode, client, registry3, mappingStorage, identityStorage, dataProvider, log) {
|
|
176692
176924
|
super("ServerModeEndpointManager");
|
|
176693
176925
|
this.serverNode = serverNode;
|
|
176694
176926
|
this.client = client;
|
|
176695
|
-
this.registry =
|
|
176927
|
+
this.registry = registry3;
|
|
176696
176928
|
this.mappingStorage = mappingStorage;
|
|
176697
176929
|
this.identityStorage = identityStorage;
|
|
176698
176930
|
this.dataProvider = dataProvider;
|
|
@@ -177226,10 +177458,10 @@ var BridgeEnvironmentFactory = class extends BridgeFactory {
|
|
|
177226
177458
|
// src/core/ioc/app-environment.ts
|
|
177227
177459
|
var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
177228
177460
|
constructor(rootEnv, options) {
|
|
177229
|
-
const
|
|
177461
|
+
const logger251 = rootEnv.get(LoggerService);
|
|
177230
177462
|
super({
|
|
177231
177463
|
id: "App",
|
|
177232
|
-
log:
|
|
177464
|
+
log: logger251.get("AppContainer"),
|
|
177233
177465
|
parent: rootEnv
|
|
177234
177466
|
});
|
|
177235
177467
|
this.options = options;
|
|
@@ -177243,8 +177475,8 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
177243
177475
|
}
|
|
177244
177476
|
construction;
|
|
177245
177477
|
async init() {
|
|
177246
|
-
const
|
|
177247
|
-
this.set(LoggerService,
|
|
177478
|
+
const logger251 = this.get(LoggerService);
|
|
177479
|
+
this.set(LoggerService, logger251);
|
|
177248
177480
|
this.set(AppStorage, new AppStorage(await this.load(StorageService)));
|
|
177249
177481
|
this.set(BridgeStorage, new BridgeStorage(await this.load(AppStorage)));
|
|
177250
177482
|
this.set(
|
|
@@ -177265,7 +177497,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
177265
177497
|
);
|
|
177266
177498
|
this.set(
|
|
177267
177499
|
HomeAssistantClient,
|
|
177268
|
-
new HomeAssistantClient(
|
|
177500
|
+
new HomeAssistantClient(logger251, this.options.homeAssistant)
|
|
177269
177501
|
);
|
|
177270
177502
|
this.set(
|
|
177271
177503
|
HomeAssistantConfig,
|
|
@@ -177273,7 +177505,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
177273
177505
|
);
|
|
177274
177506
|
this.set(
|
|
177275
177507
|
HomeAssistantActions,
|
|
177276
|
-
new HomeAssistantActions(
|
|
177508
|
+
new HomeAssistantActions(logger251, await this.load(HomeAssistantClient))
|
|
177277
177509
|
);
|
|
177278
177510
|
this.set(
|
|
177279
177511
|
HomeAssistantRegistry,
|
|
@@ -177309,7 +177541,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
177309
177541
|
this.set(
|
|
177310
177542
|
WebApi,
|
|
177311
177543
|
new WebApi(
|
|
177312
|
-
|
|
177544
|
+
logger251,
|
|
177313
177545
|
await this.load(BridgeService),
|
|
177314
177546
|
await this.load(HomeAssistantClient),
|
|
177315
177547
|
await this.load(HomeAssistantRegistry),
|
|
@@ -177330,7 +177562,7 @@ var AppEnvironment = class _AppEnvironment extends EnvironmentBase {
|
|
|
177330
177562
|
|
|
177331
177563
|
// src/matter/patches/patch-level-control-tlv.ts
|
|
177332
177564
|
init_esm();
|
|
177333
|
-
var
|
|
177565
|
+
var logger250 = Logger.get("PatchLevelControlTlv");
|
|
177334
177566
|
var optionalFieldModels = /* @__PURE__ */ new WeakSet();
|
|
177335
177567
|
var fieldModelMandatoryGetterPatched = false;
|
|
177336
177568
|
function patchLevelControlTlv() {
|
|
@@ -177386,11 +177618,11 @@ function patchLevelControlTlv() {
|
|
|
177386
177618
|
patched++;
|
|
177387
177619
|
}
|
|
177388
177620
|
if (patched > 0) {
|
|
177389
|
-
|
|
177621
|
+
logger250.info(
|
|
177390
177622
|
`Patched ${patched} LevelControl TLV schema(s): transitionTime is now optional (Google Home compatibility)`
|
|
177391
177623
|
);
|
|
177392
177624
|
} else {
|
|
177393
|
-
|
|
177625
|
+
logger250.warn(
|
|
177394
177626
|
"Failed to patch LevelControl TLV schemas, field definitions not found. Google Home brightness adjustment may not work.",
|
|
177395
177627
|
{
|
|
177396
177628
|
moveToLevel: describeFields(
|