@riddix/hamh 2.1.0-alpha.815 → 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;
|
|
@@ -164176,6 +164198,27 @@ function normalizeSupportedIndex(index) {
|
|
|
164176
164198
|
}
|
|
164177
164199
|
return null;
|
|
164178
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
|
+
}
|
|
164179
164222
|
function asFabricIndex(value) {
|
|
164180
164223
|
return value === void 0 || value === 0 ? null : FabricIndex3(value);
|
|
164181
164224
|
}
|
|
@@ -164266,7 +164309,7 @@ function buildGetCredentialStatusResponse(env, entityId, request) {
|
|
|
164266
164309
|
nextCredentialIndex: null
|
|
164267
164310
|
};
|
|
164268
164311
|
}
|
|
164269
|
-
async function applySetCredential(env, entityId, request, fabricIndex) {
|
|
164312
|
+
async function applySetCredential(env, entityId, request, fabricIndex, passthrough) {
|
|
164270
164313
|
if (request.credential.credentialType !== DoorLock3.CredentialType.Pin || normalizeSupportedIndex(request.credential.credentialIndex) === null) {
|
|
164271
164314
|
return {
|
|
164272
164315
|
status: Status2.Failure,
|
|
@@ -164292,6 +164335,9 @@ async function applySetCredential(env, entityId, request, fabricIndex) {
|
|
|
164292
164335
|
lastModifiedFabricIndex: fabricIndex,
|
|
164293
164336
|
creatorFabricIndex: fabricIndex
|
|
164294
164337
|
});
|
|
164338
|
+
passthrough?.callAction(
|
|
164339
|
+
buildUsercodeSetAction(passthrough.service, passthrough.slot, pinCode)
|
|
164340
|
+
);
|
|
164295
164341
|
}
|
|
164296
164342
|
return {
|
|
164297
164343
|
status: Status2.Success,
|
|
@@ -164311,15 +164357,35 @@ async function applySetUser(env, entityId, request, fabricIndex) {
|
|
|
164311
164357
|
fabricIndex
|
|
164312
164358
|
});
|
|
164313
164359
|
}
|
|
164314
|
-
async function applyClearCredential(env, entityId, request) {
|
|
164360
|
+
async function applyClearCredential(env, entityId, request, passthrough) {
|
|
164315
164361
|
if (request.credential === null) {
|
|
164316
164362
|
const storage2 = env.get(LockCredentialStorage);
|
|
164317
164363
|
await storage2.deleteCredential(entityId);
|
|
164364
|
+
passthrough?.callAction(
|
|
164365
|
+
buildUsercodeClearAction(passthrough.service, passthrough.slot)
|
|
164366
|
+
);
|
|
164318
164367
|
return;
|
|
164319
164368
|
}
|
|
164320
164369
|
if (request.credential.credentialType === DoorLock3.CredentialType.Pin && normalizeSupportedIndex(request.credential.credentialIndex) !== null) {
|
|
164321
164370
|
const storage2 = env.get(LockCredentialStorage);
|
|
164322
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
|
+
);
|
|
164323
164389
|
}
|
|
164324
164390
|
}
|
|
164325
164391
|
var LockServerBase = class extends DoorLockServer {
|
|
@@ -164495,12 +164561,13 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164495
164561
|
);
|
|
164496
164562
|
}
|
|
164497
164563
|
async clearUser(request) {
|
|
164498
|
-
const
|
|
164499
|
-
|
|
164500
|
-
|
|
164501
|
-
|
|
164502
|
-
|
|
164503
|
-
|
|
164564
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164565
|
+
await applyClearUser(
|
|
164566
|
+
this.env,
|
|
164567
|
+
homeAssistant.entityId,
|
|
164568
|
+
request,
|
|
164569
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164570
|
+
);
|
|
164504
164571
|
}
|
|
164505
164572
|
async setCredential(request) {
|
|
164506
164573
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -164508,7 +164575,8 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164508
164575
|
this.env,
|
|
164509
164576
|
homeAssistant.entityId,
|
|
164510
164577
|
request,
|
|
164511
|
-
this.context.fabric
|
|
164578
|
+
this.context.fabric,
|
|
164579
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164512
164580
|
);
|
|
164513
164581
|
}
|
|
164514
164582
|
getCredentialStatus(request) {
|
|
@@ -164521,7 +164589,12 @@ var LockServerWithPinBase = class extends PinCredentialBase {
|
|
|
164521
164589
|
}
|
|
164522
164590
|
async clearCredential(request) {
|
|
164523
164591
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164524
|
-
await applyClearCredential(
|
|
164592
|
+
await applyClearCredential(
|
|
164593
|
+
this.env,
|
|
164594
|
+
homeAssistant.entityId,
|
|
164595
|
+
request,
|
|
164596
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164597
|
+
);
|
|
164525
164598
|
}
|
|
164526
164599
|
};
|
|
164527
164600
|
((LockServerWithPinBase2) => {
|
|
@@ -164691,12 +164764,13 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164691
164764
|
);
|
|
164692
164765
|
}
|
|
164693
164766
|
async clearUser(request) {
|
|
164694
|
-
const
|
|
164695
|
-
|
|
164696
|
-
|
|
164697
|
-
|
|
164698
|
-
|
|
164699
|
-
|
|
164767
|
+
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164768
|
+
await applyClearUser(
|
|
164769
|
+
this.env,
|
|
164770
|
+
homeAssistant.entityId,
|
|
164771
|
+
request,
|
|
164772
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164773
|
+
);
|
|
164700
164774
|
}
|
|
164701
164775
|
async setCredential(request) {
|
|
164702
164776
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
@@ -164704,7 +164778,8 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164704
164778
|
this.env,
|
|
164705
164779
|
homeAssistant.entityId,
|
|
164706
164780
|
request,
|
|
164707
|
-
this.context.fabric
|
|
164781
|
+
this.context.fabric,
|
|
164782
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164708
164783
|
);
|
|
164709
164784
|
}
|
|
164710
164785
|
getCredentialStatus(request) {
|
|
@@ -164717,7 +164792,12 @@ var LockServerWithPinAndUnboltBase = class extends PinCredentialUnboltBase {
|
|
|
164717
164792
|
}
|
|
164718
164793
|
async clearCredential(request) {
|
|
164719
164794
|
const homeAssistant = this.agent.get(HomeAssistantEntityBehavior);
|
|
164720
|
-
await applyClearCredential(
|
|
164795
|
+
await applyClearCredential(
|
|
164796
|
+
this.env,
|
|
164797
|
+
homeAssistant.entityId,
|
|
164798
|
+
request,
|
|
164799
|
+
usercodePassthroughFrom(homeAssistant)
|
|
164800
|
+
);
|
|
164721
164801
|
}
|
|
164722
164802
|
};
|
|
164723
164803
|
((LockServerWithPinAndUnboltBase2) => {
|
|
@@ -170440,7 +170520,11 @@ init_esm();
|
|
|
170440
170520
|
init_esm3();
|
|
170441
170521
|
|
|
170442
170522
|
// src/plugins/builtin/camera/av-stream-server.ts
|
|
170443
|
-
var Base4 = CameraAvStreamManagementServer.with(
|
|
170523
|
+
var Base4 = CameraAvStreamManagementServer.with(
|
|
170524
|
+
"Video",
|
|
170525
|
+
"Snapshot",
|
|
170526
|
+
"ImageControl"
|
|
170527
|
+
);
|
|
170444
170528
|
var CameraAvStreamServer = class extends Base4 {
|
|
170445
170529
|
setStreamPriorities(request) {
|
|
170446
170530
|
this.state.streamUsagePriorities = request.streamPriorities;
|
|
@@ -170472,28 +170556,6 @@ var CameraAvStreamServer = class extends Base4 {
|
|
|
170472
170556
|
(s) => s.videoStreamId !== request.videoStreamId
|
|
170473
170557
|
);
|
|
170474
170558
|
}
|
|
170475
|
-
audioStreamAllocate(request) {
|
|
170476
|
-
const audioStreamId = this.state.nextAudioStreamId++;
|
|
170477
|
-
this.state.allocatedAudioStreams = [
|
|
170478
|
-
...this.state.allocatedAudioStreams,
|
|
170479
|
-
{
|
|
170480
|
-
audioStreamId,
|
|
170481
|
-
streamUsage: request.streamUsage,
|
|
170482
|
-
audioCodec: request.audioCodec,
|
|
170483
|
-
channelCount: request.channelCount,
|
|
170484
|
-
sampleRate: request.sampleRate,
|
|
170485
|
-
bitRate: request.bitRate,
|
|
170486
|
-
bitDepth: request.bitDepth,
|
|
170487
|
-
referenceCount: 1
|
|
170488
|
-
}
|
|
170489
|
-
];
|
|
170490
|
-
return { audioStreamId };
|
|
170491
|
-
}
|
|
170492
|
-
audioStreamDeallocate(request) {
|
|
170493
|
-
this.state.allocatedAudioStreams = this.state.allocatedAudioStreams.filter(
|
|
170494
|
-
(s) => s.audioStreamId !== request.audioStreamId
|
|
170495
|
-
);
|
|
170496
|
-
}
|
|
170497
170559
|
snapshotStreamAllocate(request) {
|
|
170498
170560
|
const snapshotStreamId = this.state.nextSnapshotStreamId++;
|
|
170499
170561
|
this.state.allocatedSnapshotStreams = [
|
|
@@ -170531,7 +170593,6 @@ var CameraAvStreamServer = class extends Base4 {
|
|
|
170531
170593
|
bridge;
|
|
170532
170594
|
entityId;
|
|
170533
170595
|
nextVideoStreamId = 1;
|
|
170534
|
-
nextAudioStreamId = 1;
|
|
170535
170596
|
nextSnapshotStreamId = 1;
|
|
170536
170597
|
}
|
|
170537
170598
|
CameraAvStreamServer2.State = State;
|
|
@@ -170611,7 +170672,12 @@ var CameraWebRtcProviderServer = class extends WebRtcTransportProviderServer {
|
|
|
170611
170672
|
})(CameraWebRtcProviderServer || (CameraWebRtcProviderServer = {}));
|
|
170612
170673
|
|
|
170613
170674
|
// src/plugins/builtin/camera/camera-endpoint.ts
|
|
170614
|
-
|
|
170675
|
+
var defaultSensorParams = {
|
|
170676
|
+
sensorWidth: 1920,
|
|
170677
|
+
sensorHeight: 1080,
|
|
170678
|
+
maxFps: 30
|
|
170679
|
+
};
|
|
170680
|
+
function createCameraEndpointType(bridge, entityId, sensor = defaultSensorParams) {
|
|
170615
170681
|
return CameraDevice.with(
|
|
170616
170682
|
CameraAvStreamServer,
|
|
170617
170683
|
CameraWebRtcProviderServer
|
|
@@ -170628,14 +170694,54 @@ function createCameraEndpointType(bridge, entityId) {
|
|
|
170628
170694
|
supportedStreamUsages: [StreamUsage.LiveView],
|
|
170629
170695
|
streamUsagePriorities: [StreamUsage.LiveView],
|
|
170630
170696
|
allocatedVideoStreams: [],
|
|
170631
|
-
allocatedAudioStreams: [],
|
|
170632
170697
|
allocatedSnapshotStreams: [],
|
|
170633
170698
|
maxConcurrentEncoders: 1,
|
|
170634
170699
|
maxEncodedPixelRate: 3840 * 2160 * 30,
|
|
170635
|
-
maxNetworkBandwidth:
|
|
170700
|
+
maxNetworkBandwidth: 2e7,
|
|
170701
|
+
// 20 Mbps, attribute is bits per second
|
|
170636
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
|
+
],
|
|
170637
170744
|
nextVideoStreamId: 1,
|
|
170638
|
-
nextAudioStreamId: 1,
|
|
170639
170745
|
nextSnapshotStreamId: 1
|
|
170640
170746
|
}
|
|
170641
170747
|
});
|
|
@@ -170848,6 +170954,27 @@ var CameraPlugin = class {
|
|
|
170848
170954
|
title: "Camera entity ids (comma-separated)",
|
|
170849
170955
|
description: "e.g. camera.front,camera.garage",
|
|
170850
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
|
|
170851
170978
|
}
|
|
170852
170979
|
}
|
|
170853
170980
|
};
|
|
@@ -170869,19 +170996,37 @@ var CameraPlugin = class {
|
|
|
170869
170996
|
this.log.info("no camera entity ids configured");
|
|
170870
170997
|
return;
|
|
170871
170998
|
}
|
|
170999
|
+
const sensor = this.sensorParams();
|
|
170872
171000
|
this.bridge = new WebRtcBridge({ haUrl, haToken });
|
|
170873
171001
|
for (const entityId of entityIds) {
|
|
170874
171002
|
const id = entityId.replace(/\./g, "_");
|
|
170875
171003
|
await context.registerDevice({
|
|
170876
171004
|
id,
|
|
170877
171005
|
name: entityId,
|
|
170878
|
-
endpointType: createCameraEndpointType(this.bridge, entityId),
|
|
171006
|
+
endpointType: createCameraEndpointType(this.bridge, entityId, sensor),
|
|
170879
171007
|
clusters: []
|
|
170880
171008
|
});
|
|
170881
171009
|
this.deviceIds.push(id);
|
|
170882
171010
|
}
|
|
170883
171011
|
this.log.info(`Exposed ${this.deviceIds.length} camera(s)`);
|
|
170884
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
|
+
}
|
|
170885
171030
|
async teardown() {
|
|
170886
171031
|
for (const id of this.deviceIds) {
|
|
170887
171032
|
await this.context?.unregisterDevice(id).catch(() => {
|