@camstack/addon-mqtt-broker 1.2.106 → 1.2.108

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.
@@ -12341,7 +12341,23 @@ var PickStreamRequirementsSchema = object({
12341
12341
  * This is what lets one picker serve both the bypass and the full source
12342
12342
  * choice, instead of a consumer scoring privately when the bypass misses.
12343
12343
  */
12344
- allowTranscode: boolean().optional()
12344
+ allowTranscode: boolean().optional(),
12345
+ /**
12346
+ * Consider ONLY streams the broker has bound to a profile slot.
12347
+ *
12348
+ * A consumer that dials the broker — which is every exporter, since none
12349
+ * of them may open the camera's own URL — can do nothing with a source
12350
+ * that has no slot: there is no restream to dial. Without this the picker
12351
+ * can name such a stream, and each consumer discovers the dead end for
12352
+ * itself: Alexa's `profileForCamStream` returns `null` and it quietly
12353
+ * falls back, and HomeKit would have had to grow the same function again.
12354
+ *
12355
+ * Default `false`, and deliberately so: the BROKER itself picks through
12356
+ * here when it decides which source to BIND to a slot
12357
+ * (`computeInitialAssignment`), and it must see the unbound ones or it
12358
+ * could never bind them.
12359
+ */
12360
+ requireProfileBound: boolean().optional()
12345
12361
  }).readonly();
12346
12362
  var PickStreamPreferencesSchema = object({
12347
12363
  /**
@@ -12382,7 +12398,43 @@ var PickedCamStreamSchema = object({
12382
12398
  */
12383
12399
  transcodes: boolean(),
12384
12400
  /** One-line explanation of why this stream won — for logs / debug UI. */
12385
- reason: string()
12401
+ reason: string(),
12402
+ /**
12403
+ * The broker profile slot this source is bound to, when it is bound.
12404
+ *
12405
+ * Answered HERE because every consumer needs it and none of them can get it
12406
+ * from the `camStreamId` alone. Alexa wrote `profileForCamStream` for it —
12407
+ * a second cap read plus a `null` branch — and HomeKit was about to write
12408
+ * the same function a second time.
12409
+ *
12410
+ * Absent when the source has no slot, which a caller passing
12411
+ * `requireProfileBound` can never see.
12412
+ */
12413
+ profile: CamProfileSchema.optional(),
12414
+ /** The broker id of that slot, for logs that must name what was dialled. */
12415
+ brokerId: string().optional(),
12416
+ /**
12417
+ * The broker restream URL to dial for this stream.
12418
+ *
12419
+ * An exporter must never open the camera's own URL — the broker is the one
12420
+ * that dials the camera, and every consumer goes through its restream. So
12421
+ * the picker answers with the thing a consumer may actually use, instead of
12422
+ * naming a source and leaving each caller to look the URL up.
12423
+ */
12424
+ url: string().optional(),
12425
+ /**
12426
+ * Frames per second this stream really delivers, and where the number came
12427
+ * from.
12428
+ *
12429
+ * It is here because getting it wrong is expensive and silent: a HomeKit
12430
+ * accessory advertised 720p at 24 fps while the slot serving it ran at 9,
12431
+ * and the controller rendered nothing at all. The source is carried with the
12432
+ * value for the same reason the bitrate evidence is: `published` is what the
12433
+ * publisher declares and `measured` is what the broker observed, and they
12434
+ * are not interchangeable.
12435
+ */
12436
+ fps: number().positive().optional(),
12437
+ fpsSource: _enum(["published", "measured"]).optional()
12386
12438
  });
12387
12439
  DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), array(CameraStreamSchema).readonly()), method(object({ deviceId: number().int().nonnegative() }), array(ProfileSlotSchema).readonly()), method(object({
12388
12440
  deviceId: number().int().nonnegative(),
@@ -13356,6 +13408,70 @@ var LocationIconAssignmentSchema = object({
13356
13408
  locationKey: string(),
13357
13409
  icon: LocationIconIdSchema
13358
13410
  });
13411
+ /**
13412
+ * One (location, description) assignment as it travels.
13413
+ *
13414
+ * Same key discipline as {@link LocationIconAssignmentSchema}, and for the same
13415
+ * reason: this lived for a while in the post-analysis addon's own settings,
13416
+ * keyed by a HAND-TYPED label matched exactly and case-sensitively. A rename in
13417
+ * the Locations page carried the icon and silently orphaned the description —
13418
+ * two authorities for one thing, joined by two different rules. Now both hang
13419
+ * off the location itself, on `locationIconKey`.
13420
+ */
13421
+ var LocationDescriptionAssignmentSchema = object({
13422
+ locationKey: string(),
13423
+ description: string()
13424
+ });
13425
+ /**
13426
+ * A SITE ZONE — a named part of the property that several locations belong to.
13427
+ *
13428
+ * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
13429
+ * kitchen. A camera belongs to exactly one location, and a location to at most
13430
+ * one zone, so a camera's zone is derived and never stored on the device: the
13431
+ * whole point of this entity is that grouping rooms touches no device row.
13432
+ *
13433
+ * ## Why not `zone`
13434
+ *
13435
+ * Because `zone` is already the most loaded word in this product: 612 source
13436
+ * files and 24 Italian strings where it means a DETECTION zone drawn on a
13437
+ * camera. The two are unrelated — one is a polygon in a frame, the other is a
13438
+ * set of rooms — and a reader who confuses them will look for a camera's
13439
+ * bedrooms. So the code says `siteZone` everywhere, and the UI frees the plain
13440
+ * word by calling the drawn one what it actually is: a detection zone.
13441
+ *
13442
+ * ## The key
13443
+ *
13444
+ * `siteZoneKey(label)` — trimmed, lower-cased, the SAME derivation locations
13445
+ * use (`locationIconKey`). Membership and the icon both hang off it, so a
13446
+ * case-only rename keeps them, which is exactly the orphaning that cost us a
13447
+ * silently-dropped location description.
13448
+ *
13449
+ * The icon vocabulary is the location one, unchanged: a zone is drawn on the
13450
+ * same two surfaces by the same glyph map, so a second vocabulary would be a
13451
+ * second thing to keep drawable (`scripts/check-location-icons-drawable.ts`).
13452
+ */
13453
+ /**
13454
+ * One zone as it travels: its key, the label the operator typed, its icon and
13455
+ * the locations inside it.
13456
+ *
13457
+ * The LABEL is carried alongside the key because the key is lossy on purpose —
13458
+ * a surface must show "Zona notte", not "zona notte". Locations are carried
13459
+ * here, rather than left to a second call, because every consumer wants both
13460
+ * at once and a viewer that asked twice could render a zone whose membership
13461
+ * it has not fetched yet.
13462
+ *
13463
+ * `icon: null` means nobody chose one, which is NOT the fallback pin: only one
13464
+ * of those two is a choice, and a picker has to draw them differently.
13465
+ */
13466
+ var SiteZoneSchema = object({
13467
+ zoneKey: string(),
13468
+ label: string(),
13469
+ icon: LocationIconIdSchema.nullable(),
13470
+ /** Folded location keys, sorted. A location listed here need not be
13471
+ * REGISTERED — devices carry labels nobody registered, and those rooms are
13472
+ * the ones that most want grouping. */
13473
+ locationKeys: array(string())
13474
+ });
13359
13475
  var ProviderStatusSchema = object({
13360
13476
  connected: boolean(),
13361
13477
  deviceCount: number(),
@@ -13873,6 +13989,33 @@ method(object({
13873
13989
  }), _void(), {
13874
13990
  kind: "mutation",
13875
13991
  auth: "admin"
13992
+ }), method(_void(), array(LocationDescriptionAssignmentSchema)), method(object({
13993
+ location: string(),
13994
+ description: string().max(400).nullable()
13995
+ }), _void(), {
13996
+ kind: "mutation",
13997
+ auth: "admin"
13998
+ }), method(_void(), array(SiteZoneSchema)), method(object({
13999
+ name: string(),
14000
+ icon: LocationIconIdSchema.nullable().optional()
14001
+ }), _void(), {
14002
+ kind: "mutation",
14003
+ auth: "admin"
14004
+ }), method(object({ name: string() }), _void(), {
14005
+ kind: "mutation",
14006
+ auth: "admin"
14007
+ }), method(object({
14008
+ from: string(),
14009
+ to: string()
14010
+ }), _void(), {
14011
+ kind: "mutation",
14012
+ auth: "admin"
14013
+ }), method(object({
14014
+ location: string(),
14015
+ zone: string().nullable()
14016
+ }), _void(), {
14017
+ kind: "mutation",
14018
+ auth: "admin"
13876
14019
  }), method(object({
13877
14020
  deviceId: number(),
13878
14021
  disabled: boolean()
@@ -32715,6 +32858,12 @@ Object.freeze({
32715
32858
  addonId: null,
32716
32859
  access: "view"
32717
32860
  },
32861
+ "deviceManager.listLocationDescriptions": {
32862
+ capName: "device-manager",
32863
+ capScope: "system",
32864
+ addonId: null,
32865
+ access: "view"
32866
+ },
32718
32867
  "deviceManager.listLocationIcons": {
32719
32868
  capName: "device-manager",
32720
32869
  capScope: "system",
@@ -32733,6 +32882,12 @@ Object.freeze({
32733
32882
  addonId: null,
32734
32883
  access: "view"
32735
32884
  },
32885
+ "deviceManager.listSiteZones": {
32886
+ capName: "device-manager",
32887
+ capScope: "system",
32888
+ addonId: null,
32889
+ access: "view"
32890
+ },
32736
32891
  "deviceManager.listWrappersForCap": {
32737
32892
  capName: "device-manager",
32738
32893
  capScope: "system",
@@ -32817,12 +32972,24 @@ Object.freeze({
32817
32972
  addonId: null,
32818
32973
  access: "delete"
32819
32974
  },
32975
+ "deviceManager.removeSiteZone": {
32976
+ capName: "device-manager",
32977
+ capScope: "system",
32978
+ addonId: null,
32979
+ access: "delete"
32980
+ },
32820
32981
  "deviceManager.renameLocation": {
32821
32982
  capName: "device-manager",
32822
32983
  capScope: "system",
32823
32984
  addonId: null,
32824
32985
  access: "create"
32825
32986
  },
32987
+ "deviceManager.renameSiteZone": {
32988
+ capName: "device-manager",
32989
+ capScope: "system",
32990
+ addonId: null,
32991
+ access: "create"
32992
+ },
32826
32993
  "deviceManager.runDeviceAction": {
32827
32994
  capName: "device-manager",
32828
32995
  capScope: "system",
@@ -32865,12 +33032,24 @@ Object.freeze({
32865
33032
  addonId: null,
32866
33033
  access: "create"
32867
33034
  },
33035
+ "deviceManager.setLocationDescription": {
33036
+ capName: "device-manager",
33037
+ capScope: "system",
33038
+ addonId: null,
33039
+ access: "create"
33040
+ },
32868
33041
  "deviceManager.setLocationIcon": {
32869
33042
  capName: "device-manager",
32870
33043
  capScope: "system",
32871
33044
  addonId: null,
32872
33045
  access: "create"
32873
33046
  },
33047
+ "deviceManager.setLocationZone": {
33048
+ capName: "device-manager",
33049
+ capScope: "system",
33050
+ addonId: null,
33051
+ access: "create"
33052
+ },
32874
33053
  "deviceManager.setMetadata": {
32875
33054
  capName: "device-manager",
32876
33055
  capScope: "system",
@@ -32901,6 +33080,12 @@ Object.freeze({
32901
33080
  addonId: null,
32902
33081
  access: "create"
32903
33082
  },
33083
+ "deviceManager.setSiteZone": {
33084
+ capName: "device-manager",
33085
+ capScope: "system",
33086
+ addonId: null,
33087
+ access: "create"
33088
+ },
32904
33089
  "deviceManager.setStreamProfileMap": {
32905
33090
  capName: "device-manager",
32906
33091
  capScope: "system",
@@ -12336,7 +12336,23 @@ var PickStreamRequirementsSchema = object({
12336
12336
  * This is what lets one picker serve both the bypass and the full source
12337
12337
  * choice, instead of a consumer scoring privately when the bypass misses.
12338
12338
  */
12339
- allowTranscode: boolean().optional()
12339
+ allowTranscode: boolean().optional(),
12340
+ /**
12341
+ * Consider ONLY streams the broker has bound to a profile slot.
12342
+ *
12343
+ * A consumer that dials the broker — which is every exporter, since none
12344
+ * of them may open the camera's own URL — can do nothing with a source
12345
+ * that has no slot: there is no restream to dial. Without this the picker
12346
+ * can name such a stream, and each consumer discovers the dead end for
12347
+ * itself: Alexa's `profileForCamStream` returns `null` and it quietly
12348
+ * falls back, and HomeKit would have had to grow the same function again.
12349
+ *
12350
+ * Default `false`, and deliberately so: the BROKER itself picks through
12351
+ * here when it decides which source to BIND to a slot
12352
+ * (`computeInitialAssignment`), and it must see the unbound ones or it
12353
+ * could never bind them.
12354
+ */
12355
+ requireProfileBound: boolean().optional()
12340
12356
  }).readonly();
12341
12357
  var PickStreamPreferencesSchema = object({
12342
12358
  /**
@@ -12377,7 +12393,43 @@ var PickedCamStreamSchema = object({
12377
12393
  */
12378
12394
  transcodes: boolean(),
12379
12395
  /** One-line explanation of why this stream won — for logs / debug UI. */
12380
- reason: string()
12396
+ reason: string(),
12397
+ /**
12398
+ * The broker profile slot this source is bound to, when it is bound.
12399
+ *
12400
+ * Answered HERE because every consumer needs it and none of them can get it
12401
+ * from the `camStreamId` alone. Alexa wrote `profileForCamStream` for it —
12402
+ * a second cap read plus a `null` branch — and HomeKit was about to write
12403
+ * the same function a second time.
12404
+ *
12405
+ * Absent when the source has no slot, which a caller passing
12406
+ * `requireProfileBound` can never see.
12407
+ */
12408
+ profile: CamProfileSchema.optional(),
12409
+ /** The broker id of that slot, for logs that must name what was dialled. */
12410
+ brokerId: string().optional(),
12411
+ /**
12412
+ * The broker restream URL to dial for this stream.
12413
+ *
12414
+ * An exporter must never open the camera's own URL — the broker is the one
12415
+ * that dials the camera, and every consumer goes through its restream. So
12416
+ * the picker answers with the thing a consumer may actually use, instead of
12417
+ * naming a source and leaving each caller to look the URL up.
12418
+ */
12419
+ url: string().optional(),
12420
+ /**
12421
+ * Frames per second this stream really delivers, and where the number came
12422
+ * from.
12423
+ *
12424
+ * It is here because getting it wrong is expensive and silent: a HomeKit
12425
+ * accessory advertised 720p at 24 fps while the slot serving it ran at 9,
12426
+ * and the controller rendered nothing at all. The source is carried with the
12427
+ * value for the same reason the bitrate evidence is: `published` is what the
12428
+ * publisher declares and `measured` is what the broker observed, and they
12429
+ * are not interchangeable.
12430
+ */
12431
+ fps: number().positive().optional(),
12432
+ fpsSource: _enum(["published", "measured"]).optional()
12381
12433
  });
12382
12434
  DeviceType.Camera, method(object({ deviceId: number().int().nonnegative() }), array(CameraStreamSchema).readonly()), method(object({ deviceId: number().int().nonnegative() }), array(ProfileSlotSchema).readonly()), method(object({
12383
12435
  deviceId: number().int().nonnegative(),
@@ -13351,6 +13403,70 @@ var LocationIconAssignmentSchema = object({
13351
13403
  locationKey: string(),
13352
13404
  icon: LocationIconIdSchema
13353
13405
  });
13406
+ /**
13407
+ * One (location, description) assignment as it travels.
13408
+ *
13409
+ * Same key discipline as {@link LocationIconAssignmentSchema}, and for the same
13410
+ * reason: this lived for a while in the post-analysis addon's own settings,
13411
+ * keyed by a HAND-TYPED label matched exactly and case-sensitively. A rename in
13412
+ * the Locations page carried the icon and silently orphaned the description —
13413
+ * two authorities for one thing, joined by two different rules. Now both hang
13414
+ * off the location itself, on `locationIconKey`.
13415
+ */
13416
+ var LocationDescriptionAssignmentSchema = object({
13417
+ locationKey: string(),
13418
+ description: string()
13419
+ });
13420
+ /**
13421
+ * A SITE ZONE — a named part of the property that several locations belong to.
13422
+ *
13423
+ * "Zona notte" holds every bedroom; "Zona giorno" the living room and the
13424
+ * kitchen. A camera belongs to exactly one location, and a location to at most
13425
+ * one zone, so a camera's zone is derived and never stored on the device: the
13426
+ * whole point of this entity is that grouping rooms touches no device row.
13427
+ *
13428
+ * ## Why not `zone`
13429
+ *
13430
+ * Because `zone` is already the most loaded word in this product: 612 source
13431
+ * files and 24 Italian strings where it means a DETECTION zone drawn on a
13432
+ * camera. The two are unrelated — one is a polygon in a frame, the other is a
13433
+ * set of rooms — and a reader who confuses them will look for a camera's
13434
+ * bedrooms. So the code says `siteZone` everywhere, and the UI frees the plain
13435
+ * word by calling the drawn one what it actually is: a detection zone.
13436
+ *
13437
+ * ## The key
13438
+ *
13439
+ * `siteZoneKey(label)` — trimmed, lower-cased, the SAME derivation locations
13440
+ * use (`locationIconKey`). Membership and the icon both hang off it, so a
13441
+ * case-only rename keeps them, which is exactly the orphaning that cost us a
13442
+ * silently-dropped location description.
13443
+ *
13444
+ * The icon vocabulary is the location one, unchanged: a zone is drawn on the
13445
+ * same two surfaces by the same glyph map, so a second vocabulary would be a
13446
+ * second thing to keep drawable (`scripts/check-location-icons-drawable.ts`).
13447
+ */
13448
+ /**
13449
+ * One zone as it travels: its key, the label the operator typed, its icon and
13450
+ * the locations inside it.
13451
+ *
13452
+ * The LABEL is carried alongside the key because the key is lossy on purpose —
13453
+ * a surface must show "Zona notte", not "zona notte". Locations are carried
13454
+ * here, rather than left to a second call, because every consumer wants both
13455
+ * at once and a viewer that asked twice could render a zone whose membership
13456
+ * it has not fetched yet.
13457
+ *
13458
+ * `icon: null` means nobody chose one, which is NOT the fallback pin: only one
13459
+ * of those two is a choice, and a picker has to draw them differently.
13460
+ */
13461
+ var SiteZoneSchema = object({
13462
+ zoneKey: string(),
13463
+ label: string(),
13464
+ icon: LocationIconIdSchema.nullable(),
13465
+ /** Folded location keys, sorted. A location listed here need not be
13466
+ * REGISTERED — devices carry labels nobody registered, and those rooms are
13467
+ * the ones that most want grouping. */
13468
+ locationKeys: array(string())
13469
+ });
13354
13470
  var ProviderStatusSchema = object({
13355
13471
  connected: boolean(),
13356
13472
  deviceCount: number(),
@@ -13868,6 +13984,33 @@ method(object({
13868
13984
  }), _void(), {
13869
13985
  kind: "mutation",
13870
13986
  auth: "admin"
13987
+ }), method(_void(), array(LocationDescriptionAssignmentSchema)), method(object({
13988
+ location: string(),
13989
+ description: string().max(400).nullable()
13990
+ }), _void(), {
13991
+ kind: "mutation",
13992
+ auth: "admin"
13993
+ }), method(_void(), array(SiteZoneSchema)), method(object({
13994
+ name: string(),
13995
+ icon: LocationIconIdSchema.nullable().optional()
13996
+ }), _void(), {
13997
+ kind: "mutation",
13998
+ auth: "admin"
13999
+ }), method(object({ name: string() }), _void(), {
14000
+ kind: "mutation",
14001
+ auth: "admin"
14002
+ }), method(object({
14003
+ from: string(),
14004
+ to: string()
14005
+ }), _void(), {
14006
+ kind: "mutation",
14007
+ auth: "admin"
14008
+ }), method(object({
14009
+ location: string(),
14010
+ zone: string().nullable()
14011
+ }), _void(), {
14012
+ kind: "mutation",
14013
+ auth: "admin"
13871
14014
  }), method(object({
13872
14015
  deviceId: number(),
13873
14016
  disabled: boolean()
@@ -32710,6 +32853,12 @@ Object.freeze({
32710
32853
  addonId: null,
32711
32854
  access: "view"
32712
32855
  },
32856
+ "deviceManager.listLocationDescriptions": {
32857
+ capName: "device-manager",
32858
+ capScope: "system",
32859
+ addonId: null,
32860
+ access: "view"
32861
+ },
32713
32862
  "deviceManager.listLocationIcons": {
32714
32863
  capName: "device-manager",
32715
32864
  capScope: "system",
@@ -32728,6 +32877,12 @@ Object.freeze({
32728
32877
  addonId: null,
32729
32878
  access: "view"
32730
32879
  },
32880
+ "deviceManager.listSiteZones": {
32881
+ capName: "device-manager",
32882
+ capScope: "system",
32883
+ addonId: null,
32884
+ access: "view"
32885
+ },
32731
32886
  "deviceManager.listWrappersForCap": {
32732
32887
  capName: "device-manager",
32733
32888
  capScope: "system",
@@ -32812,12 +32967,24 @@ Object.freeze({
32812
32967
  addonId: null,
32813
32968
  access: "delete"
32814
32969
  },
32970
+ "deviceManager.removeSiteZone": {
32971
+ capName: "device-manager",
32972
+ capScope: "system",
32973
+ addonId: null,
32974
+ access: "delete"
32975
+ },
32815
32976
  "deviceManager.renameLocation": {
32816
32977
  capName: "device-manager",
32817
32978
  capScope: "system",
32818
32979
  addonId: null,
32819
32980
  access: "create"
32820
32981
  },
32982
+ "deviceManager.renameSiteZone": {
32983
+ capName: "device-manager",
32984
+ capScope: "system",
32985
+ addonId: null,
32986
+ access: "create"
32987
+ },
32821
32988
  "deviceManager.runDeviceAction": {
32822
32989
  capName: "device-manager",
32823
32990
  capScope: "system",
@@ -32860,12 +33027,24 @@ Object.freeze({
32860
33027
  addonId: null,
32861
33028
  access: "create"
32862
33029
  },
33030
+ "deviceManager.setLocationDescription": {
33031
+ capName: "device-manager",
33032
+ capScope: "system",
33033
+ addonId: null,
33034
+ access: "create"
33035
+ },
32863
33036
  "deviceManager.setLocationIcon": {
32864
33037
  capName: "device-manager",
32865
33038
  capScope: "system",
32866
33039
  addonId: null,
32867
33040
  access: "create"
32868
33041
  },
33042
+ "deviceManager.setLocationZone": {
33043
+ capName: "device-manager",
33044
+ capScope: "system",
33045
+ addonId: null,
33046
+ access: "create"
33047
+ },
32869
33048
  "deviceManager.setMetadata": {
32870
33049
  capName: "device-manager",
32871
33050
  capScope: "system",
@@ -32896,6 +33075,12 @@ Object.freeze({
32896
33075
  addonId: null,
32897
33076
  access: "create"
32898
33077
  },
33078
+ "deviceManager.setSiteZone": {
33079
+ capName: "device-manager",
33080
+ capScope: "system",
33081
+ addonId: null,
33082
+ access: "create"
33083
+ },
32899
33084
  "deviceManager.setStreamProfileMap": {
32900
33085
  capName: "device-manager",
32901
33086
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-mqtt-broker",
3
- "version": "1.2.106",
3
+ "version": "1.2.108",
4
4
  "description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
5
5
  "keywords": [
6
6
  "camstack",