@camstack/addon-osd-manager 0.1.107 → 0.1.109

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.
Files changed (18) hide show
  1. package/dist/{MotionZonesSettings-DTpC54ou.mjs → MotionZonesSettings-BzISdGHH.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-K9WMLRT4.mjs → PrivacyMaskSettings-Bt3_2EKl.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-bJ5CtWqm.mjs → SceneMonitorEditor-Dio7Clk9.mjs} +13 -13
  4. package/dist/_stub.js +12 -14
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CZqlDPwb.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-G_SxKlXu.mjs} +4 -4
  6. package/dist/{_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CZASEbn6.mjs → _virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BblS1MmL.mjs} +1 -1
  7. package/dist/addon-osd-manager.css +1 -1
  8. package/dist/{hostInit-lcXT-lNe.mjs → hostInit-ZRYk7qMW.mjs} +3 -3
  9. package/dist/index.js +252 -6
  10. package/dist/index.mjs +252 -6
  11. package/dist/{player-overlays-xGXw37CE.mjs → player-overlays-tTeFLkD9.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-NnnlKBxM.mjs → responsive-Bh8IG8OT.mjs} +1 -1
  14. package/dist/{use-device-snapshot-DiLFlRE2.mjs → scene-monitor-copy-CPceNqW8.mjs} +46 -46
  15. package/dist/{square-Bt0d1Cqc.mjs → square-CI7Yp8Gw.mjs} +1 -1
  16. package/dist/{trash-2-BELXm9Fe.mjs → trash-2-DbCE3CFA.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-v4_63Ok2.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-YMUMbi0J.mjs} +1 -1
  18. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5363,7 +5363,7 @@ var ZodIssueCode = {
5363
5363
  var ZodFirstPartyTypeKind;
5364
5364
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5365
5365
  //#endregion
5366
- //#region ../types/dist/sleep-BDR76Ykr.mjs
5366
+ //#region ../types/dist/sleep-vl6nBE8d.mjs
5367
5367
  /**
5368
5368
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5369
5369
  * window to float samples (D455).
@@ -36271,14 +36271,81 @@ var privacyMaskCapability = {
36271
36271
  * whether persisting is worth a SQLite commit. */
36272
36272
  volatileStateFields: ["lastFetchedAt"]
36273
36273
  };
36274
+ /**
36275
+ * What a preset id DOES on this camera.
36276
+ *
36277
+ * On several PTZ firmwares the preset namespace is shared: low ids are stored
36278
+ * positions, a reserved band triggers camera FUNCTIONS. The dispensa camera
36279
+ * (Hikvision) returns its own reserved band in the preset list, named by the
36280
+ * firmware:
36281
+ *
36282
+ * 34 Back to origin · 39 Day mode · 40 Night mode · 46 Day/Night Auto Mode
36283
+ * 92 Set manual limits · 93 Save manual limits · 94 Remote reboot
36284
+ * 95 Call OSD menu
36285
+ *
36286
+ * We used to hand all of these to the UI as ordinary presets. Saving over one
36287
+ * is what produced `PUT /ISAPI/PTZCtrl/channels/1/presets/34 -> HTTP 500`: the
36288
+ * camera refusing to let "Back to origin" be overwritten, surfaced to the
36289
+ * operator as a transport failure.
36290
+ *
36291
+ * A function preset stays fully usable as a DESTINATION -- `goToPreset('34')`
36292
+ * is the single most useful thing that camera can do. Only `savePreset` and
36293
+ * `deletePreset` are gated.
36294
+ */
36295
+ var PtzPresetFunctionSchema = _enum([
36296
+ "home",
36297
+ "day-mode",
36298
+ "night-mode",
36299
+ "day-night-auto",
36300
+ "set-limits",
36301
+ "save-limits",
36302
+ "reboot",
36303
+ "osd-menu"
36304
+ ]);
36274
36305
  var PtzPresetSchema = object({
36275
36306
  id: string(),
36276
- name: string()
36307
+ name: string(),
36308
+ /**
36309
+ * The firmware function this id performs, when the provider KNOWS the id is
36310
+ * reserved. `null` = an ordinary stored position, OR a reserved id this
36311
+ * provider does not recognise -- the two are told apart by `writable`.
36312
+ */
36313
+ fn: PtzPresetFunctionSchema.nullable(),
36314
+ /**
36315
+ * Whether `savePreset` / `deletePreset` may target this id. A provider sets
36316
+ * it false only for a band it KNOWS is reserved; where the firmware is not
36317
+ * documented it stays true and a refusal comes from the camera, named.
36318
+ */
36319
+ writable: boolean()
36277
36320
  });
36321
+ /**
36322
+ * Where the head is pointing -- per axis, and `null` when the driver cannot
36323
+ * read it.
36324
+ *
36325
+ * It used to be three REQUIRED numbers, which left a provider that cannot read
36326
+ * position no way to say so. All four said `0`:
36327
+ *
36328
+ * reolink `return { pan: 0, tilt: 0, zoom: 0 }` "until a position-query
36329
+ * path lands upstream"
36330
+ * hikvision stub, "firmware-dependent and frequently absent"
36331
+ * amcrest stub, "no generic absolute-position read for this model family"
36332
+ * onvif throws
36333
+ *
36334
+ * So every consumer asking where a camera points was told "perfectly centred"
36335
+ * by four cameras that had never looked. That is D393 -- a measurement that
36336
+ * FAILED is `null`, never `0`, and the type says so all the way to the
36337
+ * decision -- the same shape as the unreadable `statfs` folded into "0 bytes of
36338
+ * headroom", which evacuated a healthy disk.
36339
+ *
36340
+ * D393 also says to check for a narrower structural TWIN of the result type.
36341
+ * There is one: `PtzStatusSchema` extends this, so the lie had already
36342
+ * propagated into `getStatus`, which is the surface `getPosition`'s own comment
36343
+ * tells callers to migrate to.
36344
+ */
36278
36345
  var PtzPositionSchema = object({
36279
- pan: number(),
36280
- tilt: number(),
36281
- zoom: number()
36346
+ pan: number().nullable(),
36347
+ tilt: number().nullable(),
36348
+ zoom: number().nullable()
36282
36349
  });
36283
36350
  var PtzMoveCommandSchema = object({
36284
36351
  pan: number().optional(),
@@ -36300,7 +36367,72 @@ var PtzOptionsSchema = object({
36300
36367
  maxPresets: number().optional(),
36301
36368
  /** Whether the camera exposes a controllable autofocus toggle
36302
36369
  * (boolean `hasX` per the getOptions availability convention). */
36303
- hasAutofocus: boolean()
36370
+ hasAutofocus: boolean(),
36371
+ /**
36372
+ * How many distinct speeds this camera's NATIVE scale offers.
36373
+ *
36374
+ * The cap's `speed` is normalized 0..1 and each provider maps it down --
36375
+ * Baichuan 1..63, Dahua 1..8, ISAPI's percentage -100..100. The normalized
36376
+ * value hides how coarse that really is: asking an amcrest for `0.37` is
36377
+ * meaningless, because it has eight steps and three of them round to the
36378
+ * same one. A loop that tunes its own gain has to know the granularity of
36379
+ * the knob it is turning.
36380
+ *
36381
+ * `null` = the driver does not know, or the scale is continuous (ONVIF takes
36382
+ * a float). Never a made-up number.
36383
+ */
36384
+ speedSteps: number().int().positive().nullable(),
36385
+ /**
36386
+ * How long ONE `move` pulse runs on this driver, ms.
36387
+ *
36388
+ * `move` is a self-terminating burst everywhere, but every provider hardcoded
36389
+ * its own duration in private -- 200 reolink, 350 amcrest, 500 hikvision,
36390
+ * 1000 onvif -- so no caller could read it. It is the DENOMINATOR of "how far
36391
+ * did the head travel per pulse": without it a measured displacement has no
36392
+ * gain to be divided into.
36393
+ *
36394
+ * `null` = the driver cannot say.
36395
+ */
36396
+ moveImpulseMs: number().int().positive().nullable()
36397
+ });
36398
+ /**
36399
+ * Which preset `goHome` goes to, and WHO decided.
36400
+ *
36401
+ * `goHome` used to be three vendor "conventions" written in three comments --
36402
+ * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
36403
+ * not one of the three cameras honours its own:
36404
+ *
36405
+ * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
36406
+ * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
36407
+ * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
36408
+ *
36409
+ * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
36410
+ * and two of the three swallowed the failure in a bare `catch`. For autotrack
36411
+ * this is the HOTTEST path -- it runs every time a subject is released -- so it
36412
+ * needs an answer that is true per camera and audible when it is missing.
36413
+ *
36414
+ * `source` is what makes it honest:
36415
+ * - `operator` -- picked in the UI, stored by the provider.
36416
+ * - `firmware` -- the camera itself named a preset `fn: 'home'` (Hikvision's
36417
+ * "Back to origin"), adopted as the default with nothing to configure.
36418
+ * - `native` -- the driver homes WITHOUT a preset at all. ONVIF does:
36419
+ * `goHome` is `ptzAbsoluteMove({x:0, y:0, zoom:0})`. `presetId` is null and
36420
+ * that is not a failure -- there is nothing to pick, and the UI must offer
36421
+ * no picker.
36422
+ * - `none` -- nothing is configured and the camera names nothing.
36423
+ * `goHome` REFUSES rather than moving the head somewhere arbitrary.
36424
+ *
36425
+ * `source === 'none'` is the refusal condition, NOT `presetId === null`: the
36426
+ * native case has no preset and homes perfectly well.
36427
+ */
36428
+ var PtzHomePresetSchema = object({
36429
+ presetId: string().nullable(),
36430
+ source: _enum([
36431
+ "operator",
36432
+ "firmware",
36433
+ "native",
36434
+ "none"
36435
+ ])
36304
36436
  });
36305
36437
  var ptzCapability = {
36306
36438
  name: "ptz",
@@ -36341,7 +36473,66 @@ var ptzCapability = {
36341
36473
  auth: "admin"
36342
36474
  }),
36343
36475
  getOptions: method(object({ deviceId: number() }), PtzOptionsSchema),
36476
+ /**
36477
+ * Move to the camera's configured home preset. THROWS when
36478
+ * `getHomePreset()` resolves to `none` -- a head that did not move must
36479
+ * never look like a head that went home.
36480
+ */
36344
36481
  goHome: method(object({ deviceId: number() }), _void(), { kind: "mutation" }),
36482
+ /** Which preset `goHome` targets, and who decided it. */
36483
+ getHomePreset: method(object({ deviceId: number() }), PtzHomePresetSchema),
36484
+ /**
36485
+ * Pin the home preset for this camera. `null` clears the operator's choice
36486
+ * and falls back to whatever the firmware names, or to `none`.
36487
+ */
36488
+ setHomePreset: method(object({
36489
+ deviceId: number(),
36490
+ presetId: string().nullable()
36491
+ }), _void(), {
36492
+ kind: "mutation",
36493
+ auth: "admin"
36494
+ }),
36495
+ /**
36496
+ * Make WHERE THE HEAD IS POINTING RIGHT NOW this camera's home.
36497
+ *
36498
+ * `setHomePreset` takes a preset id, and a preset id is the wrong shape for
36499
+ * the most natural thing an operator does: aim the camera, then say "here".
36500
+ * It is also the only shape a camera whose home is NOT a preset can accept
36501
+ * -- Reolink's home is a guard point, a stored position with no id at all,
36502
+ * and hiding the control for that case (as the UI briefly did) left the one
36503
+ * vendor with a native home unable to set it.
36504
+ *
36505
+ * Each provider does it its own way:
36506
+ * reolink `setGrd` with `needSetPos`, pinning the guard point here
36507
+ * hikvision / amcrest save a preset, then pin it as home
36508
+ * onvif REFUSES -- its home is the PTZ origin and cannot be moved
36509
+ *
36510
+ * A provider that cannot honour it throws rather than silently doing
36511
+ * nothing: an operator who pressed "set home here" and saw no error would
36512
+ * believe it took.
36513
+ */
36514
+ captureHomeHere: method(object({ deviceId: number() }), _void(), {
36515
+ kind: "mutation",
36516
+ auth: "admin"
36517
+ }),
36518
+ /**
36519
+ * How long the camera waits, idle, before returning home on its own --
36520
+ * `null` when it has no such behaviour.
36521
+ *
36522
+ * Reolink's guard point carries one (`timeout`, freely settable in
36523
+ * seconds). It is a real function of the camera that we did not expose at
36524
+ * all, and it belongs next to the home it governs rather than in a vendor
36525
+ * settings page nobody associates with Home.
36526
+ */
36527
+ getHomeReturnSeconds: method(object({ deviceId: number() }), number().int().nullable()),
36528
+ /** Set the idle-return delay. Refused by a camera that has no such timer. */
36529
+ setHomeReturnSeconds: method(object({
36530
+ deviceId: number(),
36531
+ seconds: number().int().min(0).max(3600)
36532
+ }), _void(), {
36533
+ kind: "mutation",
36534
+ auth: "admin"
36535
+ }),
36345
36536
  /**
36346
36537
  * Pull the current PTZ position. Redundant with the auto-injected
36347
36538
  * `getStatus` method (see `status` below); kept for callers that
@@ -44746,6 +44937,12 @@ Object.freeze({
44746
44937
  addonId: null,
44747
44938
  access: "create"
44748
44939
  },
44940
+ "ptz.captureHomeHere": {
44941
+ capName: "ptz",
44942
+ capScope: "device",
44943
+ addonId: null,
44944
+ access: "create"
44945
+ },
44749
44946
  "ptz.continuousMove": {
44750
44947
  capName: "ptz",
44751
44948
  capScope: "device",
@@ -44758,6 +44955,18 @@ Object.freeze({
44758
44955
  addonId: null,
44759
44956
  access: "delete"
44760
44957
  },
44958
+ "ptz.getHomePreset": {
44959
+ capName: "ptz",
44960
+ capScope: "device",
44961
+ addonId: null,
44962
+ access: "view"
44963
+ },
44964
+ "ptz.getHomeReturnSeconds": {
44965
+ capName: "ptz",
44966
+ capScope: "device",
44967
+ addonId: null,
44968
+ access: "view"
44969
+ },
44761
44970
  "ptz.getOptions": {
44762
44971
  capName: "ptz",
44763
44972
  capScope: "device",
@@ -44806,6 +45015,18 @@ Object.freeze({
44806
45015
  addonId: null,
44807
45016
  access: "create"
44808
45017
  },
45018
+ "ptz.setHomePreset": {
45019
+ capName: "ptz",
45020
+ capScope: "device",
45021
+ addonId: null,
45022
+ access: "create"
45023
+ },
45024
+ "ptz.setHomeReturnSeconds": {
45025
+ capName: "ptz",
45026
+ capScope: "device",
45027
+ addonId: null,
45028
+ access: "create"
45029
+ },
44809
45030
  "ptz.stop": {
44810
45031
  capName: "ptz",
44811
45032
  capScope: "device",
@@ -47969,6 +48190,11 @@ Object.freeze({
47969
48190
  form: "single",
47970
48191
  optional: false
47971
48192
  }],
48193
+ "ptz.captureHomeHere": [{
48194
+ name: "deviceId",
48195
+ form: "single",
48196
+ optional: false
48197
+ }],
47972
48198
  "ptz.continuousMove": [{
47973
48199
  name: "deviceId",
47974
48200
  form: "single",
@@ -47979,6 +48205,16 @@ Object.freeze({
47979
48205
  form: "single",
47980
48206
  optional: false
47981
48207
  }],
48208
+ "ptz.getHomePreset": [{
48209
+ name: "deviceId",
48210
+ form: "single",
48211
+ optional: false
48212
+ }],
48213
+ "ptz.getHomeReturnSeconds": [{
48214
+ name: "deviceId",
48215
+ form: "single",
48216
+ optional: false
48217
+ }],
47982
48218
  "ptz.getOptions": [{
47983
48219
  name: "deviceId",
47984
48220
  form: "single",
@@ -48019,6 +48255,16 @@ Object.freeze({
48019
48255
  form: "single",
48020
48256
  optional: false
48021
48257
  }],
48258
+ "ptz.setHomePreset": [{
48259
+ name: "deviceId",
48260
+ form: "single",
48261
+ optional: false
48262
+ }],
48263
+ "ptz.setHomeReturnSeconds": [{
48264
+ name: "deviceId",
48265
+ form: "single",
48266
+ optional: false
48267
+ }],
48022
48268
  "ptz.stop": [{
48023
48269
  name: "deviceId",
48024
48270
  form: "single",
package/dist/index.mjs CHANGED
@@ -5359,7 +5359,7 @@ var ZodIssueCode = {
5359
5359
  var ZodFirstPartyTypeKind;
5360
5360
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5361
5361
  //#endregion
5362
- //#region ../types/dist/sleep-BDR76Ykr.mjs
5362
+ //#region ../types/dist/sleep-vl6nBE8d.mjs
5363
5363
  /**
5364
5364
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5365
5365
  * window to float samples (D455).
@@ -36267,14 +36267,81 @@ var privacyMaskCapability = {
36267
36267
  * whether persisting is worth a SQLite commit. */
36268
36268
  volatileStateFields: ["lastFetchedAt"]
36269
36269
  };
36270
+ /**
36271
+ * What a preset id DOES on this camera.
36272
+ *
36273
+ * On several PTZ firmwares the preset namespace is shared: low ids are stored
36274
+ * positions, a reserved band triggers camera FUNCTIONS. The dispensa camera
36275
+ * (Hikvision) returns its own reserved band in the preset list, named by the
36276
+ * firmware:
36277
+ *
36278
+ * 34 Back to origin · 39 Day mode · 40 Night mode · 46 Day/Night Auto Mode
36279
+ * 92 Set manual limits · 93 Save manual limits · 94 Remote reboot
36280
+ * 95 Call OSD menu
36281
+ *
36282
+ * We used to hand all of these to the UI as ordinary presets. Saving over one
36283
+ * is what produced `PUT /ISAPI/PTZCtrl/channels/1/presets/34 -> HTTP 500`: the
36284
+ * camera refusing to let "Back to origin" be overwritten, surfaced to the
36285
+ * operator as a transport failure.
36286
+ *
36287
+ * A function preset stays fully usable as a DESTINATION -- `goToPreset('34')`
36288
+ * is the single most useful thing that camera can do. Only `savePreset` and
36289
+ * `deletePreset` are gated.
36290
+ */
36291
+ var PtzPresetFunctionSchema = _enum([
36292
+ "home",
36293
+ "day-mode",
36294
+ "night-mode",
36295
+ "day-night-auto",
36296
+ "set-limits",
36297
+ "save-limits",
36298
+ "reboot",
36299
+ "osd-menu"
36300
+ ]);
36270
36301
  var PtzPresetSchema = object({
36271
36302
  id: string(),
36272
- name: string()
36303
+ name: string(),
36304
+ /**
36305
+ * The firmware function this id performs, when the provider KNOWS the id is
36306
+ * reserved. `null` = an ordinary stored position, OR a reserved id this
36307
+ * provider does not recognise -- the two are told apart by `writable`.
36308
+ */
36309
+ fn: PtzPresetFunctionSchema.nullable(),
36310
+ /**
36311
+ * Whether `savePreset` / `deletePreset` may target this id. A provider sets
36312
+ * it false only for a band it KNOWS is reserved; where the firmware is not
36313
+ * documented it stays true and a refusal comes from the camera, named.
36314
+ */
36315
+ writable: boolean()
36273
36316
  });
36317
+ /**
36318
+ * Where the head is pointing -- per axis, and `null` when the driver cannot
36319
+ * read it.
36320
+ *
36321
+ * It used to be three REQUIRED numbers, which left a provider that cannot read
36322
+ * position no way to say so. All four said `0`:
36323
+ *
36324
+ * reolink `return { pan: 0, tilt: 0, zoom: 0 }` "until a position-query
36325
+ * path lands upstream"
36326
+ * hikvision stub, "firmware-dependent and frequently absent"
36327
+ * amcrest stub, "no generic absolute-position read for this model family"
36328
+ * onvif throws
36329
+ *
36330
+ * So every consumer asking where a camera points was told "perfectly centred"
36331
+ * by four cameras that had never looked. That is D393 -- a measurement that
36332
+ * FAILED is `null`, never `0`, and the type says so all the way to the
36333
+ * decision -- the same shape as the unreadable `statfs` folded into "0 bytes of
36334
+ * headroom", which evacuated a healthy disk.
36335
+ *
36336
+ * D393 also says to check for a narrower structural TWIN of the result type.
36337
+ * There is one: `PtzStatusSchema` extends this, so the lie had already
36338
+ * propagated into `getStatus`, which is the surface `getPosition`'s own comment
36339
+ * tells callers to migrate to.
36340
+ */
36274
36341
  var PtzPositionSchema = object({
36275
- pan: number(),
36276
- tilt: number(),
36277
- zoom: number()
36342
+ pan: number().nullable(),
36343
+ tilt: number().nullable(),
36344
+ zoom: number().nullable()
36278
36345
  });
36279
36346
  var PtzMoveCommandSchema = object({
36280
36347
  pan: number().optional(),
@@ -36296,7 +36363,72 @@ var PtzOptionsSchema = object({
36296
36363
  maxPresets: number().optional(),
36297
36364
  /** Whether the camera exposes a controllable autofocus toggle
36298
36365
  * (boolean `hasX` per the getOptions availability convention). */
36299
- hasAutofocus: boolean()
36366
+ hasAutofocus: boolean(),
36367
+ /**
36368
+ * How many distinct speeds this camera's NATIVE scale offers.
36369
+ *
36370
+ * The cap's `speed` is normalized 0..1 and each provider maps it down --
36371
+ * Baichuan 1..63, Dahua 1..8, ISAPI's percentage -100..100. The normalized
36372
+ * value hides how coarse that really is: asking an amcrest for `0.37` is
36373
+ * meaningless, because it has eight steps and three of them round to the
36374
+ * same one. A loop that tunes its own gain has to know the granularity of
36375
+ * the knob it is turning.
36376
+ *
36377
+ * `null` = the driver does not know, or the scale is continuous (ONVIF takes
36378
+ * a float). Never a made-up number.
36379
+ */
36380
+ speedSteps: number().int().positive().nullable(),
36381
+ /**
36382
+ * How long ONE `move` pulse runs on this driver, ms.
36383
+ *
36384
+ * `move` is a self-terminating burst everywhere, but every provider hardcoded
36385
+ * its own duration in private -- 200 reolink, 350 amcrest, 500 hikvision,
36386
+ * 1000 onvif -- so no caller could read it. It is the DENOMINATOR of "how far
36387
+ * did the head travel per pulse": without it a measured displacement has no
36388
+ * gain to be divided into.
36389
+ *
36390
+ * `null` = the driver cannot say.
36391
+ */
36392
+ moveImpulseMs: number().int().positive().nullable()
36393
+ });
36394
+ /**
36395
+ * Which preset `goHome` goes to, and WHO decided.
36396
+ *
36397
+ * `goHome` used to be three vendor "conventions" written in three comments --
36398
+ * Reolink preset 0, Hikvision preset '1', Dahua preset 1 -- and on this fleet
36399
+ * not one of the three cameras honours its own:
36400
+ *
36401
+ * 592 Videocamera camera Daniel (reolink) preset 0 holds "stanza"
36402
+ * 1438 Videocamera dispensa (hikvision) preset 1 holds "Credenza"
36403
+ * 3836 Videocamera studio (amcrest) preset 1 holds "Preset1"
36404
+ *
36405
+ * So `goHome` meant "go wherever the operator happened to save in slot 0 or 1",
36406
+ * and two of the three swallowed the failure in a bare `catch`. For autotrack
36407
+ * this is the HOTTEST path -- it runs every time a subject is released -- so it
36408
+ * needs an answer that is true per camera and audible when it is missing.
36409
+ *
36410
+ * `source` is what makes it honest:
36411
+ * - `operator` -- picked in the UI, stored by the provider.
36412
+ * - `firmware` -- the camera itself named a preset `fn: 'home'` (Hikvision's
36413
+ * "Back to origin"), adopted as the default with nothing to configure.
36414
+ * - `native` -- the driver homes WITHOUT a preset at all. ONVIF does:
36415
+ * `goHome` is `ptzAbsoluteMove({x:0, y:0, zoom:0})`. `presetId` is null and
36416
+ * that is not a failure -- there is nothing to pick, and the UI must offer
36417
+ * no picker.
36418
+ * - `none` -- nothing is configured and the camera names nothing.
36419
+ * `goHome` REFUSES rather than moving the head somewhere arbitrary.
36420
+ *
36421
+ * `source === 'none'` is the refusal condition, NOT `presetId === null`: the
36422
+ * native case has no preset and homes perfectly well.
36423
+ */
36424
+ var PtzHomePresetSchema = object({
36425
+ presetId: string().nullable(),
36426
+ source: _enum([
36427
+ "operator",
36428
+ "firmware",
36429
+ "native",
36430
+ "none"
36431
+ ])
36300
36432
  });
36301
36433
  var ptzCapability = {
36302
36434
  name: "ptz",
@@ -36337,7 +36469,66 @@ var ptzCapability = {
36337
36469
  auth: "admin"
36338
36470
  }),
36339
36471
  getOptions: method(object({ deviceId: number() }), PtzOptionsSchema),
36472
+ /**
36473
+ * Move to the camera's configured home preset. THROWS when
36474
+ * `getHomePreset()` resolves to `none` -- a head that did not move must
36475
+ * never look like a head that went home.
36476
+ */
36340
36477
  goHome: method(object({ deviceId: number() }), _void(), { kind: "mutation" }),
36478
+ /** Which preset `goHome` targets, and who decided it. */
36479
+ getHomePreset: method(object({ deviceId: number() }), PtzHomePresetSchema),
36480
+ /**
36481
+ * Pin the home preset for this camera. `null` clears the operator's choice
36482
+ * and falls back to whatever the firmware names, or to `none`.
36483
+ */
36484
+ setHomePreset: method(object({
36485
+ deviceId: number(),
36486
+ presetId: string().nullable()
36487
+ }), _void(), {
36488
+ kind: "mutation",
36489
+ auth: "admin"
36490
+ }),
36491
+ /**
36492
+ * Make WHERE THE HEAD IS POINTING RIGHT NOW this camera's home.
36493
+ *
36494
+ * `setHomePreset` takes a preset id, and a preset id is the wrong shape for
36495
+ * the most natural thing an operator does: aim the camera, then say "here".
36496
+ * It is also the only shape a camera whose home is NOT a preset can accept
36497
+ * -- Reolink's home is a guard point, a stored position with no id at all,
36498
+ * and hiding the control for that case (as the UI briefly did) left the one
36499
+ * vendor with a native home unable to set it.
36500
+ *
36501
+ * Each provider does it its own way:
36502
+ * reolink `setGrd` with `needSetPos`, pinning the guard point here
36503
+ * hikvision / amcrest save a preset, then pin it as home
36504
+ * onvif REFUSES -- its home is the PTZ origin and cannot be moved
36505
+ *
36506
+ * A provider that cannot honour it throws rather than silently doing
36507
+ * nothing: an operator who pressed "set home here" and saw no error would
36508
+ * believe it took.
36509
+ */
36510
+ captureHomeHere: method(object({ deviceId: number() }), _void(), {
36511
+ kind: "mutation",
36512
+ auth: "admin"
36513
+ }),
36514
+ /**
36515
+ * How long the camera waits, idle, before returning home on its own --
36516
+ * `null` when it has no such behaviour.
36517
+ *
36518
+ * Reolink's guard point carries one (`timeout`, freely settable in
36519
+ * seconds). It is a real function of the camera that we did not expose at
36520
+ * all, and it belongs next to the home it governs rather than in a vendor
36521
+ * settings page nobody associates with Home.
36522
+ */
36523
+ getHomeReturnSeconds: method(object({ deviceId: number() }), number().int().nullable()),
36524
+ /** Set the idle-return delay. Refused by a camera that has no such timer. */
36525
+ setHomeReturnSeconds: method(object({
36526
+ deviceId: number(),
36527
+ seconds: number().int().min(0).max(3600)
36528
+ }), _void(), {
36529
+ kind: "mutation",
36530
+ auth: "admin"
36531
+ }),
36341
36532
  /**
36342
36533
  * Pull the current PTZ position. Redundant with the auto-injected
36343
36534
  * `getStatus` method (see `status` below); kept for callers that
@@ -44742,6 +44933,12 @@ Object.freeze({
44742
44933
  addonId: null,
44743
44934
  access: "create"
44744
44935
  },
44936
+ "ptz.captureHomeHere": {
44937
+ capName: "ptz",
44938
+ capScope: "device",
44939
+ addonId: null,
44940
+ access: "create"
44941
+ },
44745
44942
  "ptz.continuousMove": {
44746
44943
  capName: "ptz",
44747
44944
  capScope: "device",
@@ -44754,6 +44951,18 @@ Object.freeze({
44754
44951
  addonId: null,
44755
44952
  access: "delete"
44756
44953
  },
44954
+ "ptz.getHomePreset": {
44955
+ capName: "ptz",
44956
+ capScope: "device",
44957
+ addonId: null,
44958
+ access: "view"
44959
+ },
44960
+ "ptz.getHomeReturnSeconds": {
44961
+ capName: "ptz",
44962
+ capScope: "device",
44963
+ addonId: null,
44964
+ access: "view"
44965
+ },
44757
44966
  "ptz.getOptions": {
44758
44967
  capName: "ptz",
44759
44968
  capScope: "device",
@@ -44802,6 +45011,18 @@ Object.freeze({
44802
45011
  addonId: null,
44803
45012
  access: "create"
44804
45013
  },
45014
+ "ptz.setHomePreset": {
45015
+ capName: "ptz",
45016
+ capScope: "device",
45017
+ addonId: null,
45018
+ access: "create"
45019
+ },
45020
+ "ptz.setHomeReturnSeconds": {
45021
+ capName: "ptz",
45022
+ capScope: "device",
45023
+ addonId: null,
45024
+ access: "create"
45025
+ },
44805
45026
  "ptz.stop": {
44806
45027
  capName: "ptz",
44807
45028
  capScope: "device",
@@ -47965,6 +48186,11 @@ Object.freeze({
47965
48186
  form: "single",
47966
48187
  optional: false
47967
48188
  }],
48189
+ "ptz.captureHomeHere": [{
48190
+ name: "deviceId",
48191
+ form: "single",
48192
+ optional: false
48193
+ }],
47968
48194
  "ptz.continuousMove": [{
47969
48195
  name: "deviceId",
47970
48196
  form: "single",
@@ -47975,6 +48201,16 @@ Object.freeze({
47975
48201
  form: "single",
47976
48202
  optional: false
47977
48203
  }],
48204
+ "ptz.getHomePreset": [{
48205
+ name: "deviceId",
48206
+ form: "single",
48207
+ optional: false
48208
+ }],
48209
+ "ptz.getHomeReturnSeconds": [{
48210
+ name: "deviceId",
48211
+ form: "single",
48212
+ optional: false
48213
+ }],
47978
48214
  "ptz.getOptions": [{
47979
48215
  name: "deviceId",
47980
48216
  form: "single",
@@ -48015,6 +48251,16 @@ Object.freeze({
48015
48251
  form: "single",
48016
48252
  optional: false
48017
48253
  }],
48254
+ "ptz.setHomePreset": [{
48255
+ name: "deviceId",
48256
+ form: "single",
48257
+ optional: false
48258
+ }],
48259
+ "ptz.setHomeReturnSeconds": [{
48260
+ name: "deviceId",
48261
+ form: "single",
48262
+ optional: false
48263
+ }],
48018
48264
  "ptz.stop": [{
48019
48265
  name: "deviceId",
48020
48266
  form: "single",
@@ -1,5 +1,5 @@
1
1
  import { h as e, l as t, u as n, y as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-Bs1t18EM.mjs";
2
- import { o as i, s as a } from "./responsive-NnnlKBxM.mjs";
2
+ import { o as i, s as a } from "./responsive-Bh8IG8OT.mjs";
3
3
  import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
4
4
  var l = a("chevron-down", [["path", {
5
5
  d: "m6 9 6 6 6-6",
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-v4_63Ok2.mjs";
1
+ import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-YMUMbi0J.mjs";
2
2
  export { t as get, e as init };
@@ -1,6 +1,6 @@
1
1
  import { c as e, g as t, h as n, l as r, n as i, p as a, r as o, t as s, u as c, y as l } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-Bs1t18EM.mjs";
2
2
  import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
3
- import { n as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CZASEbn6.mjs";
3
+ import { n as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BblS1MmL.mjs";
4
4
  //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
5
5
  l();
6
6
  var d = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), f = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), p = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), m = (e) => {