@riddix/hamh 2.1.0-alpha.814 → 2.1.0-alpha.816
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
|
@@ -132609,6 +132609,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
132609
132609
|
batteryEntity: config11.batteryEntity,
|
|
132610
132610
|
roomEntities: config11.roomEntities,
|
|
132611
132611
|
disableLockPin: config11.disableLockPin,
|
|
132612
|
+
lockUsercodeService: config11.lockUsercodeService,
|
|
132613
|
+
lockUsercodeSlot: config11.lockUsercodeSlot,
|
|
132612
132614
|
powerEntity: config11.powerEntity,
|
|
132613
132615
|
energyEntity: config11.energyEntity,
|
|
132614
132616
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
@@ -132760,6 +132762,8 @@ WARNING: ${includeIdentity ? "This backup contains sensitive Matter identity dat
|
|
|
132760
132762
|
batteryEntity: config11.batteryEntity,
|
|
132761
132763
|
roomEntities: config11.roomEntities,
|
|
132762
132764
|
disableLockPin: config11.disableLockPin,
|
|
132765
|
+
lockUsercodeService: config11.lockUsercodeService,
|
|
132766
|
+
lockUsercodeSlot: config11.lockUsercodeSlot,
|
|
132763
132767
|
powerEntity: config11.powerEntity,
|
|
132764
132768
|
energyEntity: config11.energyEntity,
|
|
132765
132769
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
@@ -133602,6 +133606,8 @@ function entityMappingApi(mappingStorage) {
|
|
|
133602
133606
|
chargingStateEntity: body.chargingStateEntity,
|
|
133603
133607
|
roomEntities: body.roomEntities,
|
|
133604
133608
|
disableLockPin: body.disableLockPin,
|
|
133609
|
+
lockUsercodeService: body.lockUsercodeService,
|
|
133610
|
+
lockUsercodeSlot: body.lockUsercodeSlot,
|
|
133605
133611
|
powerEntity: body.powerEntity,
|
|
133606
133612
|
energyEntity: body.energyEntity,
|
|
133607
133613
|
suctionLevelEntity: body.suctionLevelEntity,
|
|
@@ -134092,6 +134098,8 @@ function configToProfileEntry(config11) {
|
|
|
134092
134098
|
batteryEntity: config11.batteryEntity,
|
|
134093
134099
|
roomEntities: config11.roomEntities,
|
|
134094
134100
|
disableLockPin: config11.disableLockPin,
|
|
134101
|
+
lockUsercodeService: config11.lockUsercodeService,
|
|
134102
|
+
lockUsercodeSlot: config11.lockUsercodeSlot,
|
|
134095
134103
|
powerEntity: config11.powerEntity,
|
|
134096
134104
|
energyEntity: config11.energyEntity,
|
|
134097
134105
|
suctionLevelEntity: config11.suctionLevelEntity,
|
|
@@ -134221,6 +134229,8 @@ function mappingProfileApi(mappingStorage) {
|
|
|
134221
134229
|
batteryEntity: entry.batteryEntity,
|
|
134222
134230
|
roomEntities: entry.roomEntities,
|
|
134223
134231
|
disableLockPin: entry.disableLockPin,
|
|
134232
|
+
lockUsercodeService: entry.lockUsercodeService,
|
|
134233
|
+
lockUsercodeSlot: entry.lockUsercodeSlot,
|
|
134224
134234
|
powerEntity: entry.powerEntity,
|
|
134225
134235
|
energyEntity: entry.energyEntity,
|
|
134226
134236
|
suctionLevelEntity: entry.suctionLevelEntity,
|
|
@@ -138410,6 +138420,8 @@ var EntityMappingStorage = class extends Service {
|
|
|
138410
138420
|
chargingStateEntity: request.chargingStateEntity?.trim() || void 0,
|
|
138411
138421
|
roomEntities: roomEntities.length > 0 ? roomEntities : void 0,
|
|
138412
138422
|
disableLockPin: request.disableLockPin || void 0,
|
|
138423
|
+
lockUsercodeService: request.lockUsercodeService?.trim() || void 0,
|
|
138424
|
+
lockUsercodeSlot: sanitizeUsercodeSlot(request.lockUsercodeSlot),
|
|
138413
138425
|
powerEntity: request.powerEntity?.trim() || void 0,
|
|
138414
138426
|
energyEntity: request.energyEntity?.trim() || void 0,
|
|
138415
138427
|
pressureEntity: request.pressureEntity?.trim() || void 0,
|
|
@@ -138439,7 +138451,7 @@ var EntityMappingStorage = class extends Service {
|
|
|
138439
138451
|
climateAutoMode: request.climateAutoMode || void 0,
|
|
138440
138452
|
composedEntities: request.composedEntities?.filter((e) => e.entityId?.trim()) ?? void 0
|
|
138441
138453
|
};
|
|
138442
|
-
if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
|
|
138454
|
+
if (!config11.matterDeviceType && !config11.customName && !config11.customProductName && !config11.customVendorName && !config11.customSerialNumber && config11.customVendorId === void 0 && config11.disabled !== true && !config11.filterLifeEntity && !config11.cleaningModeEntity && !config11.temperatureEntity && !config11.humidityEntity && !config11.batteryEntity && !config11.chargingStateEntity && !config11.roomEntities && !config11.disableLockPin && !config11.lockUsercodeService && config11.lockUsercodeSlot === void 0 && !config11.powerEntity && !config11.energyEntity && !config11.pressureEntity && !config11.suctionLevelEntity && !config11.mopIntensityEntity && (!config11.customServiceAreas || config11.customServiceAreas.length === 0) && (!config11.customFanSpeedTags || Object.keys(config11.customFanSpeedTags).length === 0) && (!config11.fanWindPresets || (config11.fanWindPresets.natural?.length ?? 0) === 0 && (config11.fanWindPresets.sleep?.length ?? 0) === 0) && !config11.fanRestoreSpeedOnPowerOn && !config11.currentRoomEntity && !config11.cleanedAreaEntity && !config11.disableCustomAreaRoomModes && !config11.valetudoIdentifier && !config11.coverSwapOpenClose && !config11.coverExposeAsDimmableLight && !config11.selectExposeAsSwitch && !config11.selectSwitchOnOption && !config11.selectSwitchOffOption && !config11.coverSliderDebounceMs && !config11.updateThrottleMs && !config11.disableClimateOnOff && !config11.disableClimateFanControl && !config11.climateKeepModeOnIdle && !config11.climateExposeFan && !config11.climateAutoMode && (!config11.composedEntities || config11.composedEntities.length === 0)) {
|
|
138443
138455
|
bridgeMap.delete(request.entityId);
|
|
138444
138456
|
} else {
|
|
138445
138457
|
bridgeMap.set(request.entityId, config11);
|
|
@@ -138469,6 +138481,16 @@ function sanitizeVendorId(value) {
|
|
|
138469
138481
|
}
|
|
138470
138482
|
return n;
|
|
138471
138483
|
}
|
|
138484
|
+
function sanitizeUsercodeSlot(value) {
|
|
138485
|
+
if (value === void 0 || value === null || value === "") {
|
|
138486
|
+
return void 0;
|
|
138487
|
+
}
|
|
138488
|
+
const n = typeof value === "string" ? Number(value) : value;
|
|
138489
|
+
if (typeof n !== "number" || !Number.isInteger(n) || n < 1) {
|
|
138490
|
+
return void 0;
|
|
138491
|
+
}
|
|
138492
|
+
return n;
|
|
138493
|
+
}
|
|
138472
138494
|
function sanitizeDebounceMs(value) {
|
|
138473
138495
|
if (value === void 0 || value === null || value === "") {
|
|
138474
138496
|
return void 0;
|
|
@@ -156747,6 +156769,7 @@ function getMappedEntityIds(mapping) {
|
|
|
156747
156769
|
if (!mapping) return [];
|
|
156748
156770
|
const ids = [];
|
|
156749
156771
|
if (mapping.batteryEntity) ids.push(mapping.batteryEntity);
|
|
156772
|
+
if (mapping.faultEntity) ids.push(mapping.faultEntity);
|
|
156750
156773
|
if (mapping.chargingStateEntity) ids.push(mapping.chargingStateEntity);
|
|
156751
156774
|
if (mapping.temperatureEntity) ids.push(mapping.temperatureEntity);
|
|
156752
156775
|
if (mapping.humidityEntity) ids.push(mapping.humidityEntity);
|
|
@@ -161283,6 +161306,47 @@ init_nodejs();
|
|
|
161283
161306
|
|
|
161284
161307
|
// src/matter/endpoints/legacy/binary-sensor/smoke-co-alarm.ts
|
|
161285
161308
|
init_home_assistant_entity_behavior();
|
|
161309
|
+
function getBatteryPercent(entity, agent) {
|
|
161310
|
+
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
161311
|
+
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
161312
|
+
if (batteryEntity) {
|
|
161313
|
+
const stateProvider = agent.env.get(EntityStateProvider);
|
|
161314
|
+
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
161315
|
+
if (battery != null) {
|
|
161316
|
+
return Math.max(0, Math.min(100, battery));
|
|
161317
|
+
}
|
|
161318
|
+
}
|
|
161319
|
+
const attrs = entity.attributes;
|
|
161320
|
+
const level = attrs.battery_level ?? attrs.battery;
|
|
161321
|
+
if (level == null || Number.isNaN(Number(level))) {
|
|
161322
|
+
return null;
|
|
161323
|
+
}
|
|
161324
|
+
return Number(level);
|
|
161325
|
+
}
|
|
161326
|
+
function getBatteryAlert(entity, agent) {
|
|
161327
|
+
const batteryEntity = agent.get(HomeAssistantEntityBehavior).state.mapping?.batteryEntity;
|
|
161328
|
+
if (batteryEntity?.startsWith("binary_sensor.")) {
|
|
161329
|
+
const state = agent.env.get(EntityStateProvider).getState(batteryEntity);
|
|
161330
|
+
return state?.state === "on" ? SmokeCoAlarm3.AlarmState.Warning : SmokeCoAlarm3.AlarmState.Normal;
|
|
161331
|
+
}
|
|
161332
|
+
const percent3 = getBatteryPercent(entity, agent);
|
|
161333
|
+
if (percent3 == null) return SmokeCoAlarm3.AlarmState.Normal;
|
|
161334
|
+
if (percent3 <= 10) return SmokeCoAlarm3.AlarmState.Critical;
|
|
161335
|
+
if (percent3 <= 20) return SmokeCoAlarm3.AlarmState.Warning;
|
|
161336
|
+
return SmokeCoAlarm3.AlarmState.Normal;
|
|
161337
|
+
}
|
|
161338
|
+
function getHardwareFault(agent) {
|
|
161339
|
+
const faultEntity = agent.get(HomeAssistantEntityBehavior).state.mapping?.faultEntity;
|
|
161340
|
+
if (!faultEntity) return false;
|
|
161341
|
+
return agent.env.get(EntityStateProvider).getState(faultEntity)?.state === "on";
|
|
161342
|
+
}
|
|
161343
|
+
function getExpressedState(primary, active, battery, fault) {
|
|
161344
|
+
if (primary !== SmokeCoAlarm3.AlarmState.Normal) return active;
|
|
161345
|
+
if (battery !== SmokeCoAlarm3.AlarmState.Normal)
|
|
161346
|
+
return SmokeCoAlarm3.ExpressedState.BatteryAlert;
|
|
161347
|
+
if (fault) return SmokeCoAlarm3.ExpressedState.HardwareFault;
|
|
161348
|
+
return SmokeCoAlarm3.ExpressedState.Normal;
|
|
161349
|
+
}
|
|
161286
161350
|
var SmokeAlarmServerWithFeature = SmokeCoAlarmServer.with(SmokeCoAlarm3.Feature.SmokeAlarm);
|
|
161287
161351
|
var CoAlarmServerWithFeature = SmokeCoAlarmServer.with(SmokeCoAlarm3.Feature.CoAlarm);
|
|
161288
161352
|
var SmokeAlarmServerImpl = class extends SmokeAlarmServerWithFeature {
|
|
@@ -161294,8 +161358,19 @@ var SmokeAlarmServerImpl = class extends SmokeAlarmServerWithFeature {
|
|
|
161294
161358
|
}
|
|
161295
161359
|
update(entity) {
|
|
161296
161360
|
const isOn = this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state.state === "on";
|
|
161361
|
+
const smokeState = isOn ? SmokeCoAlarm3.AlarmState.Warning : SmokeCoAlarm3.AlarmState.Normal;
|
|
161362
|
+
const batteryAlert = getBatteryAlert(entity.state, this.agent);
|
|
161363
|
+
const hardwareFaultAlert = getHardwareFault(this.agent);
|
|
161297
161364
|
applyPatchState(this.state, {
|
|
161298
|
-
smokeState
|
|
161365
|
+
smokeState,
|
|
161366
|
+
batteryAlert,
|
|
161367
|
+
hardwareFaultAlert,
|
|
161368
|
+
expressedState: getExpressedState(
|
|
161369
|
+
smokeState,
|
|
161370
|
+
SmokeCoAlarm3.ExpressedState.SmokeAlarm,
|
|
161371
|
+
batteryAlert,
|
|
161372
|
+
hardwareFaultAlert
|
|
161373
|
+
)
|
|
161299
161374
|
});
|
|
161300
161375
|
}
|
|
161301
161376
|
};
|
|
@@ -161308,30 +161383,23 @@ var CoAlarmServerImpl = class extends CoAlarmServerWithFeature {
|
|
|
161308
161383
|
}
|
|
161309
161384
|
update(entity) {
|
|
161310
161385
|
const isOn = this.agent.get(HomeAssistantEntityBehavior).isAvailable && entity.state.state === "on";
|
|
161386
|
+
const coState = isOn ? SmokeCoAlarm3.AlarmState.Warning : SmokeCoAlarm3.AlarmState.Normal;
|
|
161387
|
+
const batteryAlert = getBatteryAlert(entity.state, this.agent);
|
|
161388
|
+
const hardwareFaultAlert = getHardwareFault(this.agent);
|
|
161311
161389
|
applyPatchState(this.state, {
|
|
161312
|
-
coState
|
|
161390
|
+
coState,
|
|
161391
|
+
batteryAlert,
|
|
161392
|
+
hardwareFaultAlert,
|
|
161393
|
+
expressedState: getExpressedState(
|
|
161394
|
+
coState,
|
|
161395
|
+
SmokeCoAlarm3.ExpressedState.CoAlarm,
|
|
161396
|
+
batteryAlert,
|
|
161397
|
+
hardwareFaultAlert
|
|
161398
|
+
)
|
|
161313
161399
|
});
|
|
161314
161400
|
}
|
|
161315
161401
|
};
|
|
161316
|
-
var AlarmPowerSourceServer = PowerSourceServer2({
|
|
161317
|
-
getBatteryPercent: (entity, agent) => {
|
|
161318
|
-
const homeAssistant = agent.get(HomeAssistantEntityBehavior);
|
|
161319
|
-
const batteryEntity = homeAssistant.state.mapping?.batteryEntity;
|
|
161320
|
-
if (batteryEntity) {
|
|
161321
|
-
const stateProvider = agent.env.get(EntityStateProvider);
|
|
161322
|
-
const battery = stateProvider.getBatteryPercent(batteryEntity);
|
|
161323
|
-
if (battery != null) {
|
|
161324
|
-
return Math.max(0, Math.min(100, battery));
|
|
161325
|
-
}
|
|
161326
|
-
}
|
|
161327
|
-
const attrs = entity.attributes;
|
|
161328
|
-
const level = attrs.battery_level ?? attrs.battery;
|
|
161329
|
-
if (level == null || Number.isNaN(Number(level))) {
|
|
161330
|
-
return null;
|
|
161331
|
-
}
|
|
161332
|
-
return Number(level);
|
|
161333
|
-
}
|
|
161334
|
-
});
|
|
161402
|
+
var AlarmPowerSourceServer = PowerSourceServer2({ getBatteryPercent });
|
|
161335
161403
|
var SmokeAlarmType = SmokeCoAlarmDevice.with(
|
|
161336
161404
|
BasicInformationServer2,
|
|
161337
161405
|
IdentifyServer2,
|
|
@@ -164130,6 +164198,27 @@ function normalizeSupportedIndex(index) {
|
|
|
164130
164198
|
}
|
|
164131
164199
|
return null;
|
|
164132
164200
|
}
|
|
164201
|
+
function buildUsercodeSetAction(service, slot, pin) {
|
|
164202
|
+
const pinKey = service.split(".")[0] === "zha" ? "user_code" : "usercode";
|
|
164203
|
+
return { action: service, data: { code_slot: slot, [pinKey]: pin } };
|
|
164204
|
+
}
|
|
164205
|
+
function buildUsercodeClearAction(service, slot) {
|
|
164206
|
+
return {
|
|
164207
|
+
action: service.replace(".set_", ".clear_"),
|
|
164208
|
+
data: { code_slot: slot }
|
|
164209
|
+
};
|
|
164210
|
+
}
|
|
164211
|
+
function usercodePassthroughFrom(homeAssistant) {
|
|
164212
|
+
const service = homeAssistant.state.mapping?.lockUsercodeService?.trim();
|
|
164213
|
+
if (!service) {
|
|
164214
|
+
return void 0;
|
|
164215
|
+
}
|
|
164216
|
+
return {
|
|
164217
|
+
service,
|
|
164218
|
+
slot: homeAssistant.state.mapping?.lockUsercodeSlot ?? 1,
|
|
164219
|
+
callAction: (action) => homeAssistant.callAction(action)
|
|
164220
|
+
};
|
|
164221
|
+
}
|
|
164133
164222
|
function asFabricIndex(value) {
|
|
164134
164223
|
return value === void 0 || value === 0 ? null : FabricIndex3(value);
|
|
164135
164224
|
}
|
|
@@ -164220,7 +164309,7 @@ function buildGetCredentialStatusResponse(env, entityId, request) {
|
|
|
164220
164309
|
nextCredentialIndex: null
|
|
164221
164310
|
};
|
|
164222
164311
|
}
|
|
164223
|
-
async function applySetCredential(env, entityId, request, fabricIndex) {
|
|
164312
|
+
async function applySetCredential(env, entityId, request, fabricIndex, passthrough) {
|
|
164224
164313
|
if (request.credential.credentialType !== DoorLock3.CredentialType.Pin || normalizeSupportedIndex(request.credential.credentialIndex) === null) {
|
|
164225
164314
|
return {
|
|
164226
164315
|
status: Status2.Failure,
|
|
@@ -164246,6 +164335,9 @@ async function applySetCredential(env, entityId, request, fabricIndex) {
|
|
|
164246
164335
|
lastModifiedFabricIndex: fabricIndex,
|
|
164247
164336
|
creatorFabricIndex: fabricIndex
|
|
164248
164337
|
});
|
|
164338
|
+
passthrough?.callAction(
|
|
164339
|
+
buildUsercodeSetAction(passthrough.service, passthrough.slot, pinCode)
|
|
164340
|
+
);
|
|
164249
164341
|
}
|
|
164250
164342
|
return {
|
|
164251
164343
|
status: Status2.Success,
|
|
@@ -164265,15 +164357,35 @@ async function applySetUser(env, entityId, request, fabricIndex) {
|
|
|
164265
164357
|
fabricIndex
|
|
164266
164358
|
});
|
|
164267
164359
|
}
|
|
164268
|
-
async function applyClearCredential(env, entityId, request) {
|
|
164360
|
+
async function applyClearCredential(env, entityId, request, passthrough) {
|
|
164269
164361
|
if (request.credential === null) {
|
|
164270
164362
|
const storage2 = env.get(LockCredentialStorage);
|
|
164271
164363
|
await storage2.deleteCredential(entityId);
|
|
164364
|
+
passthrough?.callAction(
|
|
164365
|
+
buildUsercodeClearAction(passthrough.service, passthrough.slot)
|
|
164366
|
+
);
|
|
164272
164367
|
return;
|
|
164273
164368
|
}
|
|
164274
164369
|
if (request.credential.credentialType === DoorLock3.CredentialType.Pin && normalizeSupportedIndex(request.credential.credentialIndex) !== null) {
|
|
164275
164370
|
const storage2 = env.get(LockCredentialStorage);
|
|
164276
164371
|
await storage2.deleteCredential(entityId);
|
|
164372
|
+
passthrough?.callAction(
|
|
164373
|
+
buildUsercodeClearAction(passthrough.service, passthrough.slot)
|
|
164374
|
+
);
|
|
164375
|
+
}
|
|
164376
|
+
}
|
|
164377
|
+
async function applyClearUser(env, entityId, request, passthrough) {
|
|
164378
|
+
const slot = normalizeSupportedIndex(request.userIndex);
|
|
164379
|
+
if (slot === null && request.userIndex !== 65534) {
|
|
164380
|
+
return;
|
|
164381
|
+
}
|
|
164382
|
+
const storage2 = env.get(LockCredentialStorage);
|
|
164383
|
+
const hadCredential = storage2.hasCredential(entityId);
|
|
164384
|
+
await storage2.deleteCredential(entityId);
|
|
164385
|
+
if (hadCredential) {
|
|
164386
|
+
passthrough?.callAction(
|
|
164387
|
+
buildUsercodeClearAction(passthrough.service, passthrough.slot)
|
|
164388
|
+
);
|
|
164277
164389
|
}
|
|
164278
164390
|
}
|
|
164279
164391
|
var LockServerBase = class extends DoorLockServer {
|
|
@@ -164449,12 +164561,13 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164449
164561
|
);
|
|
164450
164562
|
}
|
|
164451
164563
|
async clearUser(request) {
|
|
164452
|
-
const
|
|
164453
|
-
|
|
164454
|
-
|
|
164455
|
-
|
|
164456
|
-
|
|
164457
|
-
|
|
164564
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164565
|
+
await applyClearUser(
|
|
164566
|
+
this.env,
|
|
164567
|
+
homeAssistant.entityId,
|
|
164568
|
+
request,
|
|
164569
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164570
|
+
);
|
|
164458
164571
|
}
|
|
164459
164572
|
async setCredential(request) {
|
|
164460
164573
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -164462,7 +164575,8 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164462
164575
|
this.env,
|
|
164463
164576
|
homeAssistant.entityId,
|
|
164464
164577
|
request,
|
|
164465
|
-
this.context.fabric
|
|
164578
|
+
this.context.fabric,
|
|
164579
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164466
164580
|
);
|
|
164467
164581
|
}
|
|
164468
164582
|
getCredentialStatus(request) {
|
|
@@ -164475,7 +164589,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164475
164589
|
}
|
|
164476
164590
|
async clearCredential(request) {
|
|
164477
164591
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164478
|
-
await applyClearCredential(
|
|
164592
|
+
await applyClearCredential(
|
|
164593
|
+
this.env,
|
|
164594
|
+
homeAssistant.entityId,
|
|
164595
|
+
request,
|
|
164596
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164597
|
+
);
|
|
164479
164598
|
}
|
|
164480
164599
|
};
|
|
164481
164600
|
((LockServerWithPinBase2) => {
|
|
@@ -164645,12 +164764,13 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164645
164764
|
);
|
|
164646
164765
|
}
|
|
164647
164766
|
async clearUser(request) {
|
|
164648
|
-
const
|
|
164649
|
-
|
|
164650
|
-
|
|
164651
|
-
|
|
164652
|
-
|
|
164653
|
-
|
|
164767
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164768
|
+
await applyClearUser(
|
|
164769
|
+
this.env,
|
|
164770
|
+
homeAssistant.entityId,
|
|
164771
|
+
request,
|
|
164772
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164773
|
+
);
|
|
164654
164774
|
}
|
|
164655
164775
|
async setCredential(request) {
|
|
164656
164776
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -164658,7 +164778,8 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164658
164778
|
this.env,
|
|
164659
164779
|
homeAssistant.entityId,
|
|
164660
164780
|
request,
|
|
164661
|
-
this.context.fabric
|
|
164781
|
+
this.context.fabric,
|
|
164782
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164662
164783
|
);
|
|
164663
164784
|
}
|
|
164664
164785
|
getCredentialStatus(request) {
|
|
@@ -164671,7 +164792,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164671
164792
|
}
|
|
164672
164793
|
async clearCredential(request) {
|
|
164673
164794
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164674
|
-
await applyClearCredential(
|
|
164795
|
+
await applyClearCredential(
|
|
164796
|
+
this.env,
|
|
164797
|
+
homeAssistant.entityId,
|
|
164798
|
+
request,
|
|
164799
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164800
|
+
);
|
|
164675
164801
|
}
|
|
164676
164802
|
};
|
|
164677
164803
|
((LockServerWithPinAndUnboltBase2) => {
|
|
@@ -170038,6 +170164,21 @@ var LegacyEndpoint = class _LegacyEndpoint extends EntityEndpoint {
|
|
|
170038
170164
|
);
|
|
170039
170165
|
}
|
|
170040
170166
|
}
|
|
170167
|
+
const alarmDeviceClass = state.attributes.device_class;
|
|
170168
|
+
const isSmokeCoAlarm = mapping?.matterDeviceType === "smoke_co_alarm" || entityId.startsWith("binary_sensor.") && (alarmDeviceClass === "smoke" || alarmDeviceClass === "carbon_monoxide" || alarmDeviceClass === "gas");
|
|
170169
|
+
if (registry2.isAutoBatteryMappingEnabled() && !mapping?.faultEntity && isSmokeCoAlarm) {
|
|
170170
|
+
const faultEntityId = registry2.findProblemEntityForDevice(
|
|
170171
|
+
entity.device_id
|
|
170172
|
+
);
|
|
170173
|
+
if (faultEntityId && faultEntityId !== entityId) {
|
|
170174
|
+
effectiveMapping = {
|
|
170175
|
+
...effectiveMapping,
|
|
170176
|
+
entityId: effectiveMapping?.entityId ?? entityId,
|
|
170177
|
+
faultEntity: faultEntityId
|
|
170178
|
+
};
|
|
170179
|
+
logger240.debug(`Auto-assigned fault ${faultEntityId} to ${entityId}`);
|
|
170180
|
+
}
|
|
170181
|
+
}
|
|
170041
170182
|
if (!mapping?.powerEntity) {
|
|
170042
170183
|
const domain = entityId.split(".")[0];
|
|
170043
170184
|
if (domain === "switch") {
|
|
@@ -170379,7 +170520,11 @@ init_esm();
|
|
|
170379
170520
|
init_esm3();
|
|
170380
170521
|
|
|
170381
170522
|
// src/plugins/builtin/camera/av-stream-server.ts
|
|
170382
|
-
var Base4 = CameraAvStreamManagementServer.with(
|
|
170523
|
+
var Base4 = CameraAvStreamManagementServer.with(
|
|
170524
|
+
"Video",
|
|
170525
|
+
"Snapshot",
|
|
170526
|
+
"ImageControl"
|
|
170527
|
+
);
|
|
170383
170528
|
var CameraAvStreamServer = class extends Base4 {
|
|
170384
170529
|
setStreamPriorities(request) {
|
|
170385
170530
|
this.state.streamUsagePriorities = request.streamPriorities;
|
|
@@ -170411,28 +170556,6 @@ var CameraAvStreamServer = class extends Base4 {
|
|
|
170411
170556
|
(s) => s.videoStreamId !== request.videoStreamId
|
|
170412
170557
|
);
|
|
170413
170558
|
}
|
|
170414
|
-
audioStreamAllocate(request) {
|
|
170415
|
-
const audioStreamId = this.state.nextAudioStreamId++;
|
|
170416
|
-
this.state.allocatedAudioStreams = [
|
|
170417
|
-
...this.state.allocatedAudioStreams,
|
|
170418
|
-
{
|
|
170419
|
-
audioStreamId,
|
|
170420
|
-
streamUsage: request.streamUsage,
|
|
170421
|
-
audioCodec: request.audioCodec,
|
|
170422
|
-
channelCount: request.channelCount,
|
|
170423
|
-
sampleRate: request.sampleRate,
|
|
170424
|
-
bitRate: request.bitRate,
|
|
170425
|
-
bitDepth: request.bitDepth,
|
|
170426
|
-
referenceCount: 1
|
|
170427
|
-
}
|
|
170428
|
-
];
|
|
170429
|
-
return { audioStreamId };
|
|
170430
|
-
}
|
|
170431
|
-
audioStreamDeallocate(request) {
|
|
170432
|
-
this.state.allocatedAudioStreams = this.state.allocatedAudioStreams.filter(
|
|
170433
|
-
(s) => s.audioStreamId !== request.audioStreamId
|
|
170434
|
-
);
|
|
170435
|
-
}
|
|
170436
170559
|
snapshotStreamAllocate(request) {
|
|
170437
170560
|
const snapshotStreamId = this.state.nextSnapshotStreamId++;
|
|
170438
170561
|
this.state.allocatedSnapshotStreams = [
|
|
@@ -170470,7 +170593,6 @@ var CameraAvStreamServer = class extends Base4 {
|
|
|
170470
170593
|
bridge;
|
|
170471
170594
|
entityId;
|
|
170472
170595
|
nextVideoStreamId = 1;
|
|
170473
|
-
nextAudioStreamId = 1;
|
|
170474
170596
|
nextSnapshotStreamId = 1;
|
|
170475
170597
|
}
|
|
170476
170598
|
CameraAvStreamServer2.State = State;
|
|
@@ -170550,7 +170672,12 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
170550
170672
|
})(CameraWebRtcProviderServer || (CameraWebRtcProviderServer = {}));
|
|
170551
170673
|
|
|
170552
170674
|
// src/plugins/builtin/camera/camera-endpoint.ts
|
|
170553
|
-
|
|
170675
|
+
var defaultSensorParams = {
|
|
170676
|
+
sensorWidth: 1920,
|
|
170677
|
+
sensorHeight: 1080,
|
|
170678
|
+
maxFps: 30
|
|
170679
|
+
};
|
|
170680
|
+
function createCameraEndpointType(bridge, entityId, sensor = defaultSensorParams) {
|
|
170554
170681
|
return CameraDevice.with(
|
|
170555
170682
|
CameraAvStreamServer,
|
|
170556
170683
|
CameraWebRtcProviderServer
|
|
@@ -170567,14 +170694,54 @@ function createCameraEndpointType(bridge, entityId) {
|
|
|
170567
170694
|
supportedStreamUsages: [StreamUsage.LiveView],
|
|
170568
170695
|
streamUsagePriorities: [StreamUsage.LiveView],
|
|
170569
170696
|
allocatedVideoStreams: [],
|
|
170570
|
-
allocatedAudioStreams: [],
|
|
170571
170697
|
allocatedSnapshotStreams: [],
|
|
170572
170698
|
maxConcurrentEncoders: 1,
|
|
170573
170699
|
maxEncodedPixelRate: 3840 * 2160 * 30,
|
|
170574
|
-
maxNetworkBandwidth:
|
|
170700
|
+
maxNetworkBandwidth: 2e7,
|
|
170701
|
+
// 20 Mbps, attribute is bits per second
|
|
170575
170702
|
currentFrameRate: 0,
|
|
170703
|
+
videoSensorParams: {
|
|
170704
|
+
sensorWidth: sensor.sensorWidth,
|
|
170705
|
+
sensorHeight: sensor.sensorHeight,
|
|
170706
|
+
maxFps: sensor.maxFps
|
|
170707
|
+
},
|
|
170708
|
+
viewport: {
|
|
170709
|
+
x1: 0,
|
|
170710
|
+
y1: 0,
|
|
170711
|
+
x2: sensor.sensorWidth,
|
|
170712
|
+
y2: sensor.sensorHeight
|
|
170713
|
+
},
|
|
170714
|
+
minViewportResolution: { width: 64, height: 64 },
|
|
170715
|
+
rateDistortionTradeOffPoints: [
|
|
170716
|
+
{
|
|
170717
|
+
codec: CameraAvStreamManagement3.VideoCodec.H264,
|
|
170718
|
+
resolution: {
|
|
170719
|
+
width: sensor.sensorWidth,
|
|
170720
|
+
height: sensor.sensorHeight
|
|
170721
|
+
},
|
|
170722
|
+
minBitRate: 1e4
|
|
170723
|
+
}
|
|
170724
|
+
],
|
|
170725
|
+
maxContentBufferSize: 1048576,
|
|
170726
|
+
// one snapshot jpeg in flight
|
|
170727
|
+
// ImageControl attributes: matter.js 0.17.5 conformance forces the
|
|
170728
|
+
// feature. Controllers can write these but the proxied HA media path
|
|
170729
|
+
// never applies a transform.
|
|
170730
|
+
imageRotation: 0,
|
|
170731
|
+
imageFlipHorizontal: false,
|
|
170732
|
+
imageFlipVertical: false,
|
|
170733
|
+
snapshotCapabilities: [
|
|
170734
|
+
{
|
|
170735
|
+
resolution: {
|
|
170736
|
+
width: sensor.sensorWidth,
|
|
170737
|
+
height: sensor.sensorHeight
|
|
170738
|
+
},
|
|
170739
|
+
maxFrameRate: 1,
|
|
170740
|
+
imageCodec: CameraAvStreamManagement3.ImageCodec.Jpeg,
|
|
170741
|
+
requiresEncodedPixels: false
|
|
170742
|
+
}
|
|
170743
|
+
],
|
|
170576
170744
|
nextVideoStreamId: 1,
|
|
170577
|
-
nextAudioStreamId: 1,
|
|
170578
170745
|
nextSnapshotStreamId: 1
|
|
170579
170746
|
}
|
|
170580
170747
|
});
|
|
@@ -170787,6 +170954,27 @@ var CameraPlugin = class {
|
|
|
170787
170954
|
title: "Camera entity ids (comma-separated)",
|
|
170788
170955
|
description: "e.g. camera.front,camera.garage",
|
|
170789
170956
|
required: true
|
|
170957
|
+
},
|
|
170958
|
+
sensorWidth: {
|
|
170959
|
+
type: "number",
|
|
170960
|
+
title: "Sensor width (px)",
|
|
170961
|
+
description: "Video sensor width reported to controllers.",
|
|
170962
|
+
default: defaultSensorParams.sensorWidth,
|
|
170963
|
+
required: false
|
|
170964
|
+
},
|
|
170965
|
+
sensorHeight: {
|
|
170966
|
+
type: "number",
|
|
170967
|
+
title: "Sensor height (px)",
|
|
170968
|
+
description: "Video sensor height reported to controllers.",
|
|
170969
|
+
default: defaultSensorParams.sensorHeight,
|
|
170970
|
+
required: false
|
|
170971
|
+
},
|
|
170972
|
+
maxFps: {
|
|
170973
|
+
type: "number",
|
|
170974
|
+
title: "Max frame rate (fps)",
|
|
170975
|
+
description: "Maximum frame rate the sensor supports.",
|
|
170976
|
+
default: defaultSensorParams.maxFps,
|
|
170977
|
+
required: false
|
|
170790
170978
|
}
|
|
170791
170979
|
}
|
|
170792
170980
|
};
|
|
@@ -170808,19 +170996,37 @@ var CameraPlugin = class {
|
|
|
170808
170996
|
this.log.info("no camera entity ids configured");
|
|
170809
170997
|
return;
|
|
170810
170998
|
}
|
|
170999
|
+
const sensor = this.sensorParams();
|
|
170811
171000
|
this.bridge = new WebRtcBridge({ haUrl, haToken });
|
|
170812
171001
|
for (const entityId of entityIds) {
|
|
170813
171002
|
const id = entityId.replace(/\./g, "_");
|
|
170814
171003
|
await context.registerDevice({
|
|
170815
171004
|
id,
|
|
170816
171005
|
name: entityId,
|
|
170817
|
-
endpointType: createCameraEndpointType(this.bridge, entityId),
|
|
171006
|
+
endpointType: createCameraEndpointType(this.bridge, entityId, sensor),
|
|
170818
171007
|
clusters: []
|
|
170819
171008
|
});
|
|
170820
171009
|
this.deviceIds.push(id);
|
|
170821
171010
|
}
|
|
170822
171011
|
this.log.info(`Exposed ${this.deviceIds.length} camera(s)`);
|
|
170823
171012
|
}
|
|
171013
|
+
// Clamp the configured sensor to values the cluster accepts; a bad or missing
|
|
171014
|
+
// entry falls back to the default for that field.
|
|
171015
|
+
sensorParams() {
|
|
171016
|
+
const dim = (n, fallback) => typeof n === "number" && Number.isFinite(n) ? Math.min(65535, Math.max(64, Math.floor(n))) : fallback;
|
|
171017
|
+
const fps = (n, fallback) => typeof n === "number" && Number.isFinite(n) ? Math.min(65535, Math.max(1, Math.floor(n))) : fallback;
|
|
171018
|
+
return {
|
|
171019
|
+
sensorWidth: dim(
|
|
171020
|
+
this.config.sensorWidth,
|
|
171021
|
+
defaultSensorParams.sensorWidth
|
|
171022
|
+
),
|
|
171023
|
+
sensorHeight: dim(
|
|
171024
|
+
this.config.sensorHeight,
|
|
171025
|
+
defaultSensorParams.sensorHeight
|
|
171026
|
+
),
|
|
171027
|
+
maxFps: fps(this.config.maxFps, defaultSensorParams.maxFps)
|
|
171028
|
+
};
|
|
171029
|
+
}
|
|
170824
171030
|
async teardown() {
|
|
170825
171031
|
for (const id of this.deviceIds) {
|
|
170826
171032
|
await this.context?.unregisterDevice(id).catch(() => {
|
|
@@ -171752,6 +171958,8 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
171752
171958
|
_usedBatteryEntities = /* @__PURE__ */ new Set();
|
|
171753
171959
|
// Cache for battery entity lookups (deviceId -> entityId or null)
|
|
171754
171960
|
_batteryEntityCache = /* @__PURE__ */ new Map();
|
|
171961
|
+
// Cache for problem entity lookups (deviceId -> entityId or null) (#408)
|
|
171962
|
+
_problemEntityCache = /* @__PURE__ */ new Map();
|
|
171755
171963
|
// Track humidity entities that have been auto-assigned to temperature sensors
|
|
171756
171964
|
_usedHumidityEntities = /* @__PURE__ */ new Set();
|
|
171757
171965
|
// Track pressure entities that have been auto-assigned to temperature sensors
|
|
@@ -171845,6 +172053,35 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
171845
172053
|
isBatteryEntityUsed(entityId) {
|
|
171846
172054
|
return this._usedBatteryEntities.has(entityId);
|
|
171847
172055
|
}
|
|
172056
|
+
/**
|
|
172057
|
+
* Find a problem/safety binary sensor on the same HA device, so a smoke/CO
|
|
172058
|
+
* alarm can drive hardwareFaultAlert from it. Prefers device_class=problem
|
|
172059
|
+
* over safety. Returns the entity_id, or undefined if none found (#408).
|
|
172060
|
+
*/
|
|
172061
|
+
findProblemEntityForDevice(deviceId) {
|
|
172062
|
+
if (this._problemEntityCache.has(deviceId)) {
|
|
172063
|
+
const cached = this._problemEntityCache.get(deviceId);
|
|
172064
|
+
return cached === null ? void 0 : cached;
|
|
172065
|
+
}
|
|
172066
|
+
const entities = values3(this.registry.entities);
|
|
172067
|
+
const sameDevice = entities.filter((e) => e.device_id === deviceId);
|
|
172068
|
+
let safety;
|
|
172069
|
+
for (const entity of sameDevice) {
|
|
172070
|
+
if (!entity.entity_id.startsWith("binary_sensor.")) continue;
|
|
172071
|
+
const state = this.registry.states[entity.entity_id];
|
|
172072
|
+
if (!state) continue;
|
|
172073
|
+
const attrs = state.attributes;
|
|
172074
|
+
if (attrs.device_class === "problem") {
|
|
172075
|
+
this._problemEntityCache.set(deviceId, entity.entity_id);
|
|
172076
|
+
return entity.entity_id;
|
|
172077
|
+
}
|
|
172078
|
+
if (attrs.device_class === "safety" && !safety) {
|
|
172079
|
+
safety = entity.entity_id;
|
|
172080
|
+
}
|
|
172081
|
+
}
|
|
172082
|
+
this._problemEntityCache.set(deviceId, safety ?? null);
|
|
172083
|
+
return safety;
|
|
172084
|
+
}
|
|
171848
172085
|
/**
|
|
171849
172086
|
* Check if auto battery mapping is enabled for this bridge.
|
|
171850
172087
|
*/
|
|
@@ -172303,6 +172540,7 @@ var BridgeRegistry = class _BridgeRegistry {
|
|
|
172303
172540
|
this._usedEnergyEntities.clear();
|
|
172304
172541
|
this._usedComposedSubEntities.clear();
|
|
172305
172542
|
this._batteryEntityCache.clear();
|
|
172543
|
+
this._problemEntityCache.clear();
|
|
172306
172544
|
this._entities = pickBy(this.registry.entities, (entity) => {
|
|
172307
172545
|
const device = this.registry.devices[entity.device_id];
|
|
172308
172546
|
const filter = this.dataProvider.filter;
|