@kusinta/iot-schema 0.2.0-beta.19 → 0.2.0-beta.20

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.
@@ -61,8 +61,8 @@ export declare const TargetChangeSchema: GenMessage<TargetChange>;
61
61
  /**
62
62
  * The climate of one room.
63
63
  *
64
- * Apply as an upsert keyed on space_id: the same room is sent again whenever any of this
65
- * moves.
64
+ * Apply as an upsert keyed on space_id: the same room is sent again whenever any of it
65
+ * that the recipient is sent moves (see state_withheld).
66
66
  *
67
67
  * @generated from message kusinta.iot.climate.v1.RoomClimate
68
68
  */
@@ -83,7 +83,10 @@ export declare type RoomClimate = Message<"kusinta.iot.climate.v1.RoomClimate">
83
83
  targetCentidegrees?: number | undefined;
84
84
 
85
85
  /**
86
- * Who or what set target_centidegrees. Unset while the target is.
86
+ * Who or what set target_centidegrees. Unset while the target is, and when it is withheld
87
+ * from the recipient: from service in a home, and from anyone when it dates from before
88
+ * their current residency in the home, or from a home they did not live in at the time
89
+ * (see access.v1.MembershipRelation).
87
90
  *
88
91
  * @generated from field: kusinta.iot.climate.v1.TargetChange target_change = 3;
89
92
  */
@@ -134,18 +137,23 @@ export declare type RoomClimate = Message<"kusinta.iot.climate.v1.RoomClimate">
134
137
  * The sensors the room measures with, in order: the first is used, each later one
135
138
  * takes over while those before it are quiet. Only devices filed in this room.
136
139
  *
137
- * By default every temperature sensor filed in the room, in the order it was filed, so
138
- * a sensor filed later joins at the end without anyone configuring anything. An owner
139
- * can set the order explicitly (see sensors_configured). Empty: the room has no
140
- * temperature sensor, and its valves regulate on their own probes (NO_SENSOR).
140
+ * In a home, sensors its residents own come first, in the order they were filed, and then
141
+ * the building's; outside homes a room measures with the building's sensors only. The
142
+ * building's are by default every building temperature sensor filed in the room, in the
143
+ * order it was filed, so a sensor filed later joins at the end without anyone configuring
144
+ * anything; an owner can set their order explicitly (see sensors_configured). Empty: the
145
+ * room has no temperature sensor, and its valves regulate on their own probes
146
+ * (NO_SENSOR).
141
147
  *
142
148
  * @generated from field: repeated kusinta.iot.identity.v1.DeviceId sensor_ids = 8;
143
149
  */
144
150
  sensorIds: DeviceId[];
145
151
 
146
152
  /**
147
- * Whether sensor_ids is an order an owner chose, rather than the default of filing
148
- * order. A sensor filed into a room with a chosen order is not added to it.
153
+ * Whether the building's part of sensor_ids is an order an owner chose, rather than the
154
+ * default of filing order. A building sensor filed into a room with a chosen order is
155
+ * not added to it; a resident's own always is. A sensor that becomes the building's in a
156
+ * room — released by its owner — counts as filed there at that moment.
149
157
  *
150
158
  * @generated from field: bool sensors_configured = 14;
151
159
  */
@@ -177,12 +185,31 @@ export declare type RoomClimate = Message<"kusinta.iot.climate.v1.RoomClimate">
177
185
  *
178
186
  * Stated as the lock rather than as a permission so that the proto3 default — false,
179
187
  * unlocked — is the intended default: a room nobody has configured takes changes at its
180
- * devices, as a room in an apartment always should. Elsewhere locking is the owner's
181
- * choice.
188
+ * devices, as a room in an apartment should until its residents decide otherwise; when a
189
+ * home loses its last resident, its rooms' locks are cleared. Elsewhere locking is the
190
+ * owner's choice.
182
191
  *
183
192
  * @generated from field: bool lock_device_controls = 12;
184
193
  */
185
194
  lockDeviceControls: boolean;
195
+
196
+ /**
197
+ * Set when the recipient reaches this room only as service (see
198
+ * access.v1.MembershipRelation): the room is in someone's home, and what describes the
199
+ * people in it is WITHHELD — target_centidegrees, target_change,
200
+ * effective_target_centidegrees, overrides_mode, mode_space_id, measured_centidegrees,
201
+ * measured_by, condition and lock_device_controls are all left unset, and sensor_ids
202
+ * leaves out sensors a resident owns.
203
+ *
204
+ * Unset because withheld, not because unknown: an app must not render them as NO_TARGET or
205
+ * a lost sensor. A withheld room is sent again only when something that IS sent changes,
206
+ * so that the timing of an update does not give away what was withheld. Its limits and
207
+ * the sensors service may see are still sent, since setting a room up is service work.
208
+ * Its climate over time is available to service only as an ApartmentClimateSummary.
209
+ *
210
+ * @generated from field: bool state_withheld = 15;
211
+ */
212
+ stateWithheld: boolean;
186
213
  };
187
214
 
188
215
  /**
@@ -192,6 +219,17 @@ export declare type RoomClimate = Message<"kusinta.iot.climate.v1.RoomClimate">
192
219
  export declare const RoomClimateSchema: GenMessage<RoomClimate>;
193
220
 
194
221
  /**
222
+ * A mode on a home ends when whoever switched it on stops being one of its residents: a new
223
+ * tenant does not inherit the previous one's holiday. A mode on a room ends when the room
224
+ * joins a home, whose rooms follow the apartment's mode alone. Any other mode — one switched on by
225
+ * someone who is not one of its residents now: who never lived there, or a member still
226
+ * recorded with no relation — ends when the
227
+ * home gains a resident: when anyone other than its setter, not already its resident, is
228
+ * assigned RESIDENT on the apartment, a member recorded with no relation included, or the
229
+ * space becomes an apartment with RESIDENT members on it other than its setter. A mode's
230
+ * setter recorded with no relation being assigned RESIDENT ends none of their own modes;
231
+ * being assigned SERVICE or removed ends them.
232
+ *
195
233
  * A mode set on an apartment — or, for rooms that are not in one, on their floor or
196
234
  * common area. While it is on it sets back every room below that space, except that a
197
235
  * room inside an apartment follows only its apartment's mode: a mode on a floor does not
@@ -223,8 +261,10 @@ export declare type ClimateMode = Message<"kusinta.iot.climate.v1.ClimateMode">
223
261
 
224
262
  /**
225
263
  * HOLIDAY: when the setback begins and when the rooms are to be back at their own
226
- * targets — warm by then, not starting to heat (see warm_from). AWAY: starts_at is
227
- * when it was switched on; ends_at is unset.
264
+ * targets — warm by then, not starting to heat (see warm_from). AWAY: starts_at is when it
265
+ * was switched on; ends_at is unset. starts_at is unset when it dates from before the
266
+ * recipient's current residency in the home, or from a home they did not live in at the
267
+ * time; an ends_at ahead is always sent.
228
268
  *
229
269
  * @generated from field: google.protobuf.Timestamp starts_at = 4;
230
270
  */
@@ -236,7 +276,9 @@ export declare type ClimateMode = Message<"kusinta.iot.climate.v1.ClimateMode">
236
276
  endsAt?: Timestamp | undefined;
237
277
 
238
278
  /**
239
- * Who switched it on.
279
+ * Who switched it on. Unset when it is withheld from the recipient: from service in a
280
+ * home, and from anyone when it dates from before their current residency in the home, or
281
+ * from a home they did not live in at the time (see access.v1.MembershipRelation).
240
282
  *
241
283
  * @generated from field: kusinta.iot.identity.v1.UserId set_by = 6;
242
284
  */
@@ -352,7 +394,9 @@ export declare type RoomHistory = Message<"kusinta.iot.climate.v1.RoomHistory">
352
394
  /**
353
395
  * The earliest moment the gateway still holds for this room. The request's from_time
354
396
  * and to_time are clamped to [kept_from, now], so nothing before kept_from is ever
355
- * returned.
397
+ * returned. For a room in the recipient's own home it is no earlier than the start of
398
+ * their current residency, nor than when the room last joined their home; for any other
399
+ * room, no earlier than when it last left a home.
356
400
  *
357
401
  * @generated from field: google.protobuf.Timestamp kept_from = 2;
358
402
  */
@@ -372,6 +416,135 @@ export declare type RoomHistory = Message<"kusinta.iot.climate.v1.RoomHistory">
372
416
  */
373
417
  export declare const RoomHistorySchema: GenMessage<RoomHistory>;
374
418
 
419
+ /**
420
+ * An apartment's climate over one period.
421
+ *
422
+ * Each room's mean is taken over the quarter hours of the period in which it was in this
423
+ * apartment and had a value; coverage likewise counts only the quarter hours it was here,
424
+ * and the apartment's mean is formed from the rooms' means as the summary's weighting says.
425
+ * Every mean is optional: absent means nothing was known, never zero.
426
+ *
427
+ * @generated from message kusinta.iot.climate.v1.ClimatePeriodMean
428
+ */
429
+ export declare type ClimatePeriodMean = Message<"kusinta.iot.climate.v1.ClimatePeriodMean"> & {
430
+ /**
431
+ * The period, half-open: starts_at <= t < ends_at.
432
+ *
433
+ * @generated from field: google.protobuf.Timestamp starts_at = 1;
434
+ */
435
+ startsAt?: Timestamp | undefined;
436
+
437
+ /**
438
+ * @generated from field: google.protobuf.Timestamp ends_at = 2;
439
+ */
440
+ endsAt?: Timestamp | undefined;
441
+
442
+ /**
443
+ * The mean measured temperature, in centidegrees, taken from the building's own sensors
444
+ * only: in each room, the first of its building sensors that was heard. A reading from a
445
+ * sensor a resident owns never enters it.
446
+ *
447
+ * @generated from field: optional sint32 measured_centidegrees = 3;
448
+ */
449
+ measuredCentidegrees?: number | undefined;
450
+
451
+ /**
452
+ * The mean target, in centidegrees: RoomClimate.target_centidegrees — the temperature
453
+ * somebody asked for, not the effective target a mode set it back to, so that a
454
+ * setback is not reported as what the residents chose. The measured mean still falls
455
+ * while a home is set back; how much that reveals is governed by how long a period
456
+ * service may ask for (webrtc.v1.PrivacyDisclosure.climate_summary_period).
457
+ *
458
+ * @generated from field: optional sint32 target_centidegrees = 4;
459
+ */
460
+ targetCentidegrees?: number | undefined;
461
+
462
+ /**
463
+ * How much of the period the means rest on, in thousandths: the quarter hours with a
464
+ * value, summed over the apartment's rooms, divided by the quarter hours each room was in
465
+ * the apartment during the period, summed likewise. A room with no sensor, or one that
466
+ * went quiet, lowers it — a mean with low coverage describes part of the apartment, or
467
+ * part of the period.
468
+ *
469
+ * @generated from field: uint32 measured_coverage_permille = 5;
470
+ */
471
+ measuredCoveragePermille: number;
472
+
473
+ /**
474
+ * @generated from field: uint32 target_coverage_permille = 6;
475
+ */
476
+ targetCoveragePermille: number;
477
+
478
+ /**
479
+ * The rooms that contributed a measured value, of the rooms the apartment had at any time
480
+ * in the period.
481
+ *
482
+ * @generated from field: uint32 rooms_measured = 7;
483
+ */
484
+ roomsMeasured: number;
485
+
486
+ /**
487
+ * @generated from field: uint32 rooms = 8;
488
+ */
489
+ rooms: number;
490
+ };
491
+
492
+ /**
493
+ * Describes the message kusinta.iot.climate.v1.ClimatePeriodMean.
494
+ * Use `create(ClimatePeriodMeanSchema)` to create a new message.
495
+ */
496
+ export declare const ClimatePeriodMeanSchema: GenMessage<ClimatePeriodMean>;
497
+
498
+ /**
499
+ * An apartment's climate as means over whole periods, in reply to
500
+ * webrtc.v1.GetApartmentClimateSummary. What a party who does not live there may know of
501
+ * how warm it is kept — see webrtc.v1.PrivacyDisclosure.
502
+ *
503
+ * Only CLOSED periods are given. The period running now is never included, so that a
504
+ * summary cannot be polled into a live reading.
505
+ *
506
+ * @generated from message kusinta.iot.climate.v1.ApartmentClimateSummary
507
+ */
508
+ export declare type ApartmentClimateSummary = Message<"kusinta.iot.climate.v1.ApartmentClimateSummary"> & {
509
+ /**
510
+ * @generated from field: kusinta.iot.identity.v1.SpaceId apartment_id = 1;
511
+ */
512
+ apartmentId?: SpaceId | undefined;
513
+
514
+ /**
515
+ * @generated from field: kusinta.iot.climate.v1.ClimateSummaryPeriod period = 2;
516
+ */
517
+ period: ClimateSummaryPeriod;
518
+
519
+ /**
520
+ * @generated from field: kusinta.iot.climate.v1.ClimateSummaryWeighting weighting = 3;
521
+ */
522
+ weighting: ClimateSummaryWeighting;
523
+
524
+ /**
525
+ * The start of the earliest period the gateway still holds that the recipient may be
526
+ * given: for a resident of this apartment, no earlier than their current residency; for
527
+ * anyone else, of the length disclosed now, and no earlier than the first such period
528
+ * after it was last changed (see webrtc.v1.PrivacyDisclosure.climate_summary_period).
529
+ *
530
+ * @generated from field: google.protobuf.Timestamp kept_from = 4;
531
+ */
532
+ keptFrom?: Timestamp | undefined;
533
+
534
+ /**
535
+ * The periods within the requested range, in order of starts_at.
536
+ *
537
+ * @generated from field: repeated kusinta.iot.climate.v1.ClimatePeriodMean periods = 5;
538
+ */
539
+ periods: ClimatePeriodMean[];
540
+ };
541
+
542
+ /**
543
+ * Describes the message kusinta.iot.climate.v1.ApartmentClimateSummary.
544
+ * Use `create(ApartmentClimateSummarySchema)` to create a new message.
545
+ */
546
+ export declare const ApartmentClimateSummarySchema: GenMessage<ApartmentClimateSummary>;
547
+
375
548
  /**
376
549
  * What a room is doing right now, in one word. Details live in the fields of
377
550
  * RoomClimate; this is what a list row shows.
@@ -480,3 +653,74 @@ export enum ClimateModeKind {
480
653
  */
481
654
  export declare const ClimateModeKindSchema: GenEnum<ClimateModeKind>;
482
655
 
656
+ /**
657
+ * The length of the periods an ApartmentClimateSummary is given in. Each period runs from
658
+ * the start of one local date to the start of another in the building's time zone
659
+ * (space.v1.Space.time_zone) — midnight, or the first moment of the date where daylight
660
+ * saving skips midnight — so a day is 23 or 25 hours long across a change of daylight
661
+ * saving time. A period is cut by the time zone in force when it opened, and kept as cut.
662
+ * After a change of zone, the next period runs from that cut to the first boundary of its
663
+ * length in the new zone — a midnight, a Monday or a first of the month — that leaves it
664
+ * covering at least one whole day, week or month of the new zone's calendar, so no period
665
+ * covers less than one whole day, week or month of its calendar, however many hours that
666
+ * is. While the zone is unknown — never set, or cleared — nothing is summarised, and the
667
+ * period open when it was cleared ends unsummarised; once it is known again, the first
668
+ * period begins at the first boundary of its length after that.
669
+ *
670
+ * @generated from enum kusinta.iot.climate.v1.ClimateSummaryPeriod
671
+ */
672
+ export enum ClimateSummaryPeriod {
673
+ /**
674
+ * @generated from enum value: CLIMATE_SUMMARY_PERIOD_UNSPECIFIED = 0;
675
+ */
676
+ UNSPECIFIED = 0,
677
+
678
+ /**
679
+ * @generated from enum value: CLIMATE_SUMMARY_PERIOD_DAY = 1;
680
+ */
681
+ DAY = 1,
682
+
683
+ /**
684
+ * ISO weeks, Monday to Monday.
685
+ *
686
+ * @generated from enum value: CLIMATE_SUMMARY_PERIOD_WEEK = 2;
687
+ */
688
+ WEEK = 2,
689
+
690
+ /**
691
+ * Calendar months.
692
+ *
693
+ * @generated from enum value: CLIMATE_SUMMARY_PERIOD_MONTH = 3;
694
+ */
695
+ MONTH = 3,
696
+ }
697
+
698
+ /**
699
+ * Describes the enum kusinta.iot.climate.v1.ClimateSummaryPeriod.
700
+ */
701
+ export declare const ClimateSummaryPeriodSchema: GenEnum<ClimateSummaryPeriod>;
702
+
703
+ /**
704
+ * How an apartment's mean is formed from its rooms' means.
705
+ *
706
+ * @generated from enum kusinta.iot.climate.v1.ClimateSummaryWeighting
707
+ */
708
+ export enum ClimateSummaryWeighting {
709
+ /**
710
+ * @generated from enum value: CLIMATE_SUMMARY_WEIGHTING_UNSPECIFIED = 0;
711
+ */
712
+ UNSPECIFIED = 0,
713
+
714
+ /**
715
+ * Each room counts once, whatever its size: a bathroom weighs as much as a living room.
716
+ *
717
+ * @generated from enum value: CLIMATE_SUMMARY_WEIGHTING_ROOMS_EQUAL = 1;
718
+ */
719
+ ROOMS_EQUAL = 1,
720
+ }
721
+
722
+ /**
723
+ * Describes the enum kusinta.iot.climate.v1.ClimateSummaryWeighting.
724
+ */
725
+ export declare const ClimateSummaryWeightingSchema: GenEnum<ClimateSummaryWeighting>;
726
+
@@ -10,7 +10,7 @@ import { file_kusinta_iot_identity_v1_identity } from "../../identity/v1/identit
10
10
  * Describes the file kusinta/iot/climate/v1/climate.proto.
11
11
  */
12
12
  export const file_kusinta_iot_climate_v1_climate = /*@__PURE__*/
13
- fileDesc("CiRrdXNpbnRhL2lvdC9jbGltYXRlL3YxL2NsaW1hdGUucHJvdG8SFmt1c2ludGEuaW90LmNsaW1hdGUudjEiogEKDFRhcmdldENoYW5nZRImCgJhdBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoEdXNlchgCIAEoCzIfLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLlVzZXJJZEgAEjMKBmRldmljZRgDIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkSABCBAoCYnki5wUKC1Jvb21DbGltYXRlEjIKCHNwYWNlX2lkGAEgASgLMiAua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuU3BhY2VJZBIgChN0YXJnZXRfY2VudGlkZWdyZWVzGAIgASgRSACIAQESOwoNdGFyZ2V0X2NoYW5nZRgDIAEoCzIkLmt1c2ludGEuaW90LmNsaW1hdGUudjEuVGFyZ2V0Q2hhbmdlEioKHWVmZmVjdGl2ZV90YXJnZXRfY2VudGlkZWdyZWVzGAQgASgRSAGIAQESFgoOb3ZlcnJpZGVzX21vZGUYBSABKAgSNwoNbW9kZV9zcGFjZV9pZBgNIAEoCzIgLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLlNwYWNlSWQSHQoQbWluX2NlbnRpZGVncmVlcxgGIAEoEUgCiAEBEh0KEG1heF9jZW50aWRlZ3JlZXMYByABKBFIA4gBARI1CgpzZW5zb3JfaWRzGAggAygLMiEua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuRGV2aWNlSWQSGgoSc2Vuc29yc19jb25maWd1cmVkGA4gASgIEiIKFW1lYXN1cmVkX2NlbnRpZGVncmVlcxgJIAEoEUgEiAEBEjYKC21lYXN1cmVkX2J5GAogASgLMiEua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuRGV2aWNlSWQSPwoJY29uZGl0aW9uGAsgASgOMiwua3VzaW50YS5pb3QuY2xpbWF0ZS52MS5Sb29tQ2xpbWF0ZUNvbmRpdGlvbhIcChRsb2NrX2RldmljZV9jb250cm9scxgMIAEoCEIWChRfdGFyZ2V0X2NlbnRpZGVncmVlc0IgCh5fZWZmZWN0aXZlX3RhcmdldF9jZW50aWRlZ3JlZXNCEwoRX21pbl9jZW50aWRlZ3JlZXNCEwoRX21heF9jZW50aWRlZ3JlZXNCGAoWX21lYXN1cmVkX2NlbnRpZGVncmVlcyKDAwoLQ2xpbWF0ZU1vZGUSMgoIc3BhY2VfaWQYASABKAsyIC5rdXNpbnRhLmlvdC5pZGVudGl0eS52MS5TcGFjZUlkEjUKBGtpbmQYAiABKA4yJy5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLkNsaW1hdGVNb2RlS2luZBIhChRzZXRiYWNrX2NlbnRpZGVncmVlcxgDIAEoEUgAiAEBEi0KCXN0YXJ0c19hdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASKwoHZW5kc19hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoGc2V0X2J5GAYgASgLMh8ua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuVXNlcklkEjIKCXdhcm1fZnJvbRgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAYgBAUIXChVfc2V0YmFja19jZW50aWRlZ3JlZXNCDAoKX3dhcm1fZnJvbSJ5Cg9Sb29tQ2xpbWF0ZUxpc3QSMgoFcm9vbXMYASADKAsyIy5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLlJvb21DbGltYXRlEjIKBW1vZGVzGAIgAygLMiMua3VzaW50YS5pb3QuY2xpbWF0ZS52MS5DbGltYXRlTW9kZSLzAgoRUm9vbUhpc3RvcnlTYW1wbGUSJgoCYXQYASABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiIKFW1lYXN1cmVkX2NlbnRpZGVncmVlcxgCIAEoEUgAiAEBEiAKE3RhcmdldF9jZW50aWRlZ3JlZXMYAyABKBFIAYgBARIqCh1lZmZlY3RpdmVfdGFyZ2V0X2NlbnRpZGVncmVlcxgEIAEoEUgCiAEBEiAKE3ZhbHZlX29wZW5fcGVybWlsbGUYBSABKA1IA4gBARIfChJ2YWx2ZV9vcGVuX3NlY29uZHMYBiABKA1IBIgBAUIYChZfbWVhc3VyZWRfY2VudGlkZWdyZWVzQhYKFF90YXJnZXRfY2VudGlkZWdyZWVzQiAKHl9lZmZlY3RpdmVfdGFyZ2V0X2NlbnRpZGVncmVlc0IWChRfdmFsdmVfb3Blbl9wZXJtaWxsZUIVChNfdmFsdmVfb3Blbl9zZWNvbmRzIqsBCgtSb29tSGlzdG9yeRIxCgdyb29tX2lkGAEgASgLMiAua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuU3BhY2VJZBItCglrZXB0X2Zyb20YAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjoKB3NhbXBsZXMYAyADKAsyKS5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLlJvb21IaXN0b3J5U2FtcGxlKtUCChRSb29tQ2xpbWF0ZUNvbmRpdGlvbhImCiJST09NX0NMSU1BVEVfQ09ORElUSU9OX1VOU1BFQ0lGSUVEEAASIgoeUk9PTV9DTElNQVRFX0NPTkRJVElPTl9IT0xESU5HEAESJAogUk9PTV9DTElNQVRFX0NPTkRJVElPTl9OT19UQVJHRVQQAhImCiJST09NX0NMSU1BVEVfQ09ORElUSU9OX1NFTlNPUl9MT1NUEAMSJgoiUk9PTV9DTElNQVRFX0NPTkRJVElPTl9XSU5ET1dfT1BFThAEEiUKIVJPT01fQ0xJTUFURV9DT05ESVRJT05fTk9fSEVBVElORxAFEi4KKlJPT01fQ0xJTUFURV9DT05ESVRJT05fSEVBVElOR19VTlJFQUNIQUJMRRAGEiQKIFJPT01fQ0xJTUFURV9DT05ESVRJT05fTk9fU0VOU09SEAcqbwoPQ2xpbWF0ZU1vZGVLaW5kEiEKHUNMSU1BVEVfTU9ERV9LSU5EX1VOU1BFQ0lGSUVEEAASGgoWQ0xJTUFURV9NT0RFX0tJTkRfQVdBWRABEh0KGUNMSU1BVEVfTU9ERV9LSU5EX0hPTElEQVkQAkICSAFiBnByb3RvMw", [file_google_protobuf_timestamp, file_kusinta_iot_identity_v1_identity]);
13
+ fileDesc("CiRrdXNpbnRhL2lvdC9jbGltYXRlL3YxL2NsaW1hdGUucHJvdG8SFmt1c2ludGEuaW90LmNsaW1hdGUudjEiogEKDFRhcmdldENoYW5nZRImCgJhdBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoEdXNlchgCIAEoCzIfLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLlVzZXJJZEgAEjMKBmRldmljZRgDIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkSABCBAoCYnki/wUKC1Jvb21DbGltYXRlEjIKCHNwYWNlX2lkGAEgASgLMiAua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuU3BhY2VJZBIgChN0YXJnZXRfY2VudGlkZWdyZWVzGAIgASgRSACIAQESOwoNdGFyZ2V0X2NoYW5nZRgDIAEoCzIkLmt1c2ludGEuaW90LmNsaW1hdGUudjEuVGFyZ2V0Q2hhbmdlEioKHWVmZmVjdGl2ZV90YXJnZXRfY2VudGlkZWdyZWVzGAQgASgRSAGIAQESFgoOb3ZlcnJpZGVzX21vZGUYBSABKAgSNwoNbW9kZV9zcGFjZV9pZBgNIAEoCzIgLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLlNwYWNlSWQSHQoQbWluX2NlbnRpZGVncmVlcxgGIAEoEUgCiAEBEh0KEG1heF9jZW50aWRlZ3JlZXMYByABKBFIA4gBARI1CgpzZW5zb3JfaWRzGAggAygLMiEua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuRGV2aWNlSWQSGgoSc2Vuc29yc19jb25maWd1cmVkGA4gASgIEiIKFW1lYXN1cmVkX2NlbnRpZGVncmVlcxgJIAEoEUgEiAEBEjYKC21lYXN1cmVkX2J5GAogASgLMiEua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuRGV2aWNlSWQSPwoJY29uZGl0aW9uGAsgASgOMiwua3VzaW50YS5pb3QuY2xpbWF0ZS52MS5Sb29tQ2xpbWF0ZUNvbmRpdGlvbhIcChRsb2NrX2RldmljZV9jb250cm9scxgMIAEoCBIWCg5zdGF0ZV93aXRoaGVsZBgPIAEoCEIWChRfdGFyZ2V0X2NlbnRpZGVncmVlc0IgCh5fZWZmZWN0aXZlX3RhcmdldF9jZW50aWRlZ3JlZXNCEwoRX21pbl9jZW50aWRlZ3JlZXNCEwoRX21heF9jZW50aWRlZ3JlZXNCGAoWX21lYXN1cmVkX2NlbnRpZGVncmVlcyKDAwoLQ2xpbWF0ZU1vZGUSMgoIc3BhY2VfaWQYASABKAsyIC5rdXNpbnRhLmlvdC5pZGVudGl0eS52MS5TcGFjZUlkEjUKBGtpbmQYAiABKA4yJy5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLkNsaW1hdGVNb2RlS2luZBIhChRzZXRiYWNrX2NlbnRpZGVncmVlcxgDIAEoEUgAiAEBEi0KCXN0YXJ0c19hdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASKwoHZW5kc19hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASLwoGc2V0X2J5GAYgASgLMh8ua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuVXNlcklkEjIKCXdhcm1fZnJvbRgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAYgBAUIXChVfc2V0YmFja19jZW50aWRlZ3JlZXNCDAoKX3dhcm1fZnJvbSJ5Cg9Sb29tQ2xpbWF0ZUxpc3QSMgoFcm9vbXMYASADKAsyIy5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLlJvb21DbGltYXRlEjIKBW1vZGVzGAIgAygLMiMua3VzaW50YS5pb3QuY2xpbWF0ZS52MS5DbGltYXRlTW9kZSLzAgoRUm9vbUhpc3RvcnlTYW1wbGUSJgoCYXQYASABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiIKFW1lYXN1cmVkX2NlbnRpZGVncmVlcxgCIAEoEUgAiAEBEiAKE3RhcmdldF9jZW50aWRlZ3JlZXMYAyABKBFIAYgBARIqCh1lZmZlY3RpdmVfdGFyZ2V0X2NlbnRpZGVncmVlcxgEIAEoEUgCiAEBEiAKE3ZhbHZlX29wZW5fcGVybWlsbGUYBSABKA1IA4gBARIfChJ2YWx2ZV9vcGVuX3NlY29uZHMYBiABKA1IBIgBAUIYChZfbWVhc3VyZWRfY2VudGlkZWdyZWVzQhYKFF90YXJnZXRfY2VudGlkZWdyZWVzQiAKHl9lZmZlY3RpdmVfdGFyZ2V0X2NlbnRpZGVncmVlc0IWChRfdmFsdmVfb3Blbl9wZXJtaWxsZUIVChNfdmFsdmVfb3Blbl9zZWNvbmRzIqsBCgtSb29tSGlzdG9yeRIxCgdyb29tX2lkGAEgASgLMiAua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuU3BhY2VJZBItCglrZXB0X2Zyb20YAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjoKB3NhbXBsZXMYAyADKAsyKS5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLlJvb21IaXN0b3J5U2FtcGxlItQCChFDbGltYXRlUGVyaW9kTWVhbhItCglzdGFydHNfYXQYASABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEisKB2VuZHNfYXQYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEiIKFW1lYXN1cmVkX2NlbnRpZGVncmVlcxgDIAEoEUgAiAEBEiAKE3RhcmdldF9jZW50aWRlZ3JlZXMYBCABKBFIAYgBARIiChptZWFzdXJlZF9jb3ZlcmFnZV9wZXJtaWxsZRgFIAEoDRIgChh0YXJnZXRfY292ZXJhZ2VfcGVybWlsbGUYBiABKA0SFgoOcm9vbXNfbWVhc3VyZWQYByABKA0SDQoFcm9vbXMYCCABKA1CGAoWX21lYXN1cmVkX2NlbnRpZGVncmVlc0IWChRfdGFyZ2V0X2NlbnRpZGVncmVlcyK+AgoXQXBhcnRtZW50Q2xpbWF0ZVN1bW1hcnkSNgoMYXBhcnRtZW50X2lkGAEgASgLMiAua3VzaW50YS5pb3QuaWRlbnRpdHkudjEuU3BhY2VJZBI8CgZwZXJpb2QYAiABKA4yLC5rdXNpbnRhLmlvdC5jbGltYXRlLnYxLkNsaW1hdGVTdW1tYXJ5UGVyaW9kEkIKCXdlaWdodGluZxgDIAEoDjIvLmt1c2ludGEuaW90LmNsaW1hdGUudjEuQ2xpbWF0ZVN1bW1hcnlXZWlnaHRpbmcSLQoJa2VwdF9mcm9tGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI6CgdwZXJpb2RzGAUgAygLMikua3VzaW50YS5pb3QuY2xpbWF0ZS52MS5DbGltYXRlUGVyaW9kTWVhbirVAgoUUm9vbUNsaW1hdGVDb25kaXRpb24SJgoiUk9PTV9DTElNQVRFX0NPTkRJVElPTl9VTlNQRUNJRklFRBAAEiIKHlJPT01fQ0xJTUFURV9DT05ESVRJT05fSE9MRElORxABEiQKIFJPT01fQ0xJTUFURV9DT05ESVRJT05fTk9fVEFSR0VUEAISJgoiUk9PTV9DTElNQVRFX0NPTkRJVElPTl9TRU5TT1JfTE9TVBADEiYKIlJPT01fQ0xJTUFURV9DT05ESVRJT05fV0lORE9XX09QRU4QBBIlCiFST09NX0NMSU1BVEVfQ09ORElUSU9OX05PX0hFQVRJTkcQBRIuCipST09NX0NMSU1BVEVfQ09ORElUSU9OX0hFQVRJTkdfVU5SRUFDSEFCTEUQBhIkCiBST09NX0NMSU1BVEVfQ09ORElUSU9OX05PX1NFTlNPUhAHKm8KD0NsaW1hdGVNb2RlS2luZBIhCh1DTElNQVRFX01PREVfS0lORF9VTlNQRUNJRklFRBAAEhoKFkNMSU1BVEVfTU9ERV9LSU5EX0FXQVkQARIdChlDTElNQVRFX01PREVfS0lORF9IT0xJREFZEAIqoQEKFENsaW1hdGVTdW1tYXJ5UGVyaW9kEiYKIkNMSU1BVEVfU1VNTUFSWV9QRVJJT0RfVU5TUEVDSUZJRUQQABIeChpDTElNQVRFX1NVTU1BUllfUEVSSU9EX0RBWRABEh8KG0NMSU1BVEVfU1VNTUFSWV9QRVJJT0RfV0VFSxACEiAKHENMSU1BVEVfU1VNTUFSWV9QRVJJT0RfTU9OVEgQAypvChdDbGltYXRlU3VtbWFyeVdlaWdodGluZxIpCiVDTElNQVRFX1NVTU1BUllfV0VJR0hUSU5HX1VOU1BFQ0lGSUVEEAASKQolQ0xJTUFURV9TVU1NQVJZX1dFSUdIVElOR19ST09NU19FUVVBTBABQgJIAWIGcHJvdG8z", [file_google_protobuf_timestamp, file_kusinta_iot_identity_v1_identity]);
14
14
 
15
15
  /**
16
16
  * Describes the message kusinta.iot.climate.v1.TargetChange.
@@ -54,6 +54,20 @@ export const RoomHistorySampleSchema = /*@__PURE__*/
54
54
  export const RoomHistorySchema = /*@__PURE__*/
55
55
  messageDesc(file_kusinta_iot_climate_v1_climate, 5);
56
56
 
57
+ /**
58
+ * Describes the message kusinta.iot.climate.v1.ClimatePeriodMean.
59
+ * Use `create(ClimatePeriodMeanSchema)` to create a new message.
60
+ */
61
+ export const ClimatePeriodMeanSchema = /*@__PURE__*/
62
+ messageDesc(file_kusinta_iot_climate_v1_climate, 6);
63
+
64
+ /**
65
+ * Describes the message kusinta.iot.climate.v1.ApartmentClimateSummary.
66
+ * Use `create(ApartmentClimateSummarySchema)` to create a new message.
67
+ */
68
+ export const ApartmentClimateSummarySchema = /*@__PURE__*/
69
+ messageDesc(file_kusinta_iot_climate_v1_climate, 7);
70
+
57
71
  /**
58
72
  * Describes the enum kusinta.iot.climate.v1.RoomClimateCondition.
59
73
  */
@@ -87,3 +101,42 @@ export const ClimateModeKindSchema = /*@__PURE__*/
87
101
  export const ClimateModeKind = /*@__PURE__*/
88
102
  tsEnum(ClimateModeKindSchema);
89
103
 
104
+ /**
105
+ * Describes the enum kusinta.iot.climate.v1.ClimateSummaryPeriod.
106
+ */
107
+ export const ClimateSummaryPeriodSchema = /*@__PURE__*/
108
+ enumDesc(file_kusinta_iot_climate_v1_climate, 2);
109
+
110
+ /**
111
+ * The length of the periods an ApartmentClimateSummary is given in. Each period runs from
112
+ * the start of one local date to the start of another in the building's time zone
113
+ * (space.v1.Space.time_zone) — midnight, or the first moment of the date where daylight
114
+ * saving skips midnight — so a day is 23 or 25 hours long across a change of daylight
115
+ * saving time. A period is cut by the time zone in force when it opened, and kept as cut.
116
+ * After a change of zone, the next period runs from that cut to the first boundary of its
117
+ * length in the new zone — a midnight, a Monday or a first of the month — that leaves it
118
+ * covering at least one whole day, week or month of the new zone's calendar, so no period
119
+ * covers less than one whole day, week or month of its calendar, however many hours that
120
+ * is. While the zone is unknown — never set, or cleared — nothing is summarised, and the
121
+ * period open when it was cleared ends unsummarised; once it is known again, the first
122
+ * period begins at the first boundary of its length after that.
123
+ *
124
+ * @generated from enum kusinta.iot.climate.v1.ClimateSummaryPeriod
125
+ */
126
+ export const ClimateSummaryPeriod = /*@__PURE__*/
127
+ tsEnum(ClimateSummaryPeriodSchema);
128
+
129
+ /**
130
+ * Describes the enum kusinta.iot.climate.v1.ClimateSummaryWeighting.
131
+ */
132
+ export const ClimateSummaryWeightingSchema = /*@__PURE__*/
133
+ enumDesc(file_kusinta_iot_climate_v1_climate, 3);
134
+
135
+ /**
136
+ * How an apartment's mean is formed from its rooms' means.
137
+ *
138
+ * @generated from enum kusinta.iot.climate.v1.ClimateSummaryWeighting
139
+ */
140
+ export const ClimateSummaryWeighting = /*@__PURE__*/
141
+ tsEnum(ClimateSummaryWeightingSchema);
142
+
@@ -102,6 +102,10 @@ export declare type DeviceDescriptor = Message<"kusinta.iot.device.v1.DeviceDesc
102
102
  ownerUserId?: UserId | undefined;
103
103
 
104
104
  /**
105
+ * Unset when it is withheld from the recipient: in a service view, and from anyone when
106
+ * it dates from before their current residency in the home, or from a home they did not
107
+ * live in at the time (see access.v1.MembershipRelation).
108
+ *
105
109
  * @generated from field: google.protobuf.Timestamp claimed_at = 16;
106
110
  */
107
111
  claimedAt?: Timestamp | undefined;
@@ -121,7 +125,8 @@ export declare type DeviceDescriptor = Message<"kusinta.iot.device.v1.DeviceDesc
121
125
  *
122
126
  * So a Device is a Matter node OR one device behind one — the equivalence is deliberately
123
127
  * not exact, and this field is how a consumer tells which. Absent means the device is
124
- * reached directly.
128
+ * reached directly, or that its bridge is withheld from the recipient (see
129
+ * access.v1.ServiceSignal FILING).
125
130
  *
126
131
  * @generated from field: optional kusinta.iot.identity.v1.DeviceId bridged_by = 19;
127
132
  */
@@ -60,12 +60,21 @@ export declare type DeviceEvent = Message<"kusinta.iot.device.v1.DeviceEvent"> &
60
60
  eventId: number;
61
61
 
62
62
  /**
63
- * Matter's EventNumber: monotonically increasing per node, and the reason an event log
64
- * can be resumed rather than merely replayed. A consumer that sees a gap knows it missed
65
- * something and can say so — the one guarantee a PropertyUpdate stream cannot give.
63
+ * The device's event number, as its connector numbers it — per device, where Matter's
64
+ * EventNumber is per node; a connector renumbers what a node gives it. It is the reason
65
+ * an event log can be resumed rather than merely replayed. A consumer that sees a gap
66
+ * knows it missed something and can say so — the one guarantee a PropertyUpdate stream
67
+ * cannot give. On the app leg a gap is judged by previous_event_number and follows_loss
68
+ * below, not by a skip in this number.
66
69
  *
67
- * Monotonic within one device. Do NOT compare across devices; they are unrelated
68
- * sequences.
70
+ * Monotonic within one device, its connector and one numbering_id — a device that moves
71
+ * to another connector begins a new sequence — and consecutive as a connector delivers
72
+ * it: a connector numbers each device's events on its own, so a skip means events were
73
+ * lost — including ones the connector lost itself, whose numbers it skips. A number at or
74
+ * below one already received for the device from the same connector under the same
75
+ * numbering_id is that event again — a connector resends what it could not confirm,
76
+ * always the whole unconfirmed tail of what it sent, in order — and is dropped. Do NOT
77
+ * compare across devices; they are unrelated sequences.
69
78
  *
70
79
  * @generated from field: uint64 event_number = 5;
71
80
  */
@@ -92,6 +101,79 @@ export declare type DeviceEvent = Message<"kusinta.iot.device.v1.DeviceEvent"> &
92
101
  * @generated from field: kusinta.iot.device.v1.AttributeValue data = 8;
93
102
  */
94
103
  data?: AttributeValue | undefined;
104
+
105
+ /**
106
+ * How a recipient tells events it was not sent from events that were lost. Filled by the
107
+ * gateway on the app leg; a connector leaves both unset.
108
+ *
109
+ * A recipient is not sent every event of a device: which ones it receives depends on its
110
+ * grant (access.v1.DeviceAcl.allowed_event_refs), so event_number skips wherever an event
111
+ * went to somebody else. A skip in event_number is therefore NOT a gap. A gap is:
112
+ *
113
+ * * previous_event_number set, the recipient holding a last-received event_number for
114
+ * this device under the same numbering_id (whether or not it kept the event), and
115
+ * previous_event_number above it — its log misses events the gateway sent this user,
116
+ * on another session or while it was away, or that were lost; one at or below it is
117
+ * no gap; or
118
+ * * follows_loss set on an event above the last number the recipient holds, or when it
119
+ * holds none.
120
+ *
121
+ * Otherwise — previous_event_number unset, or the recipient holding no number for the
122
+ * device under that numbering_id — continuity is unknown, and only follows_loss claims a
123
+ * gap: the gateway knows events were lost, whatever the recipient holds.
124
+ *
125
+ * event_number counts a device's events over its life, so it tells anyone it reaches
126
+ * roughly how many events came before; that much the number discloses. And it is still
127
+ * the device's own, so a recipient granted only some of a device's events learns from it
128
+ * how many it was not sent: that much a partial grant of events discloses.
129
+ *
130
+ * previous_event_number never names an event from before the user's current residency in
131
+ * a home, nor from before their current, unbroken stretch of seeing the device — it is
132
+ * unset instead, and follows_loss then looks no further back either. Otherwise it is the
133
+ * event_number of the previous event of this device that this user was due — within the
134
+ * grant they held when it happened — whether or not any session of theirs was open to be
135
+ * sent it, so that events missed while away are a gap like any other. A number of the
136
+ * event's own numbering_id. Unset when the gateway has received no such event under that
137
+ * numbering since the gateway itself last started — the first event after a numbering
138
+ * restart included: continuity is then unknown. The gateway remembers nothing of a
139
+ * numbering across its own restart, so follows_loss too covers only what it received
140
+ * since, and a resend it can no longer recognise reaches the app: an app drops an event
141
+ * whose number is at or below the last it holds for the device under the same
142
+ * numbering_id.
143
+ *
144
+ * @generated from field: optional uint64 previous_event_number = 9;
145
+ */
146
+ previousEventNumber?: bigint | undefined;
147
+
148
+ /**
149
+ * Set when the gateway itself missed events of this device since previous_event_number —
150
+ * or, when that is unset, since the latest of the start of what the user may learn of the
151
+ * device, the start of the current numbering and the gateway's own last start — the
152
+ * sequence it receives from the device skipped. A restart of the numbering is not itself
153
+ * a loss; a connector shows what it lost by skipping numbers. What was lost is unknown,
154
+ * so it may have been an event this recipient would have been sent.
155
+ *
156
+ * @generated from field: bool follows_loss = 10;
157
+ */
158
+ followsLoss: boolean;
159
+
160
+ /**
161
+ * Which numbering event_number belongs to. A connector changes it whenever it restarts a
162
+ * device's numbering — after losing its own count — so that a restart is never mistaken
163
+ * for a resend. The gateway then begins a new sequence for the device: the first event of
164
+ * it that each user is due carries previous_event_number unset, continuity unknown. A new
165
+ * value is one never used before for the device — a UUIDv4 is the expected form. Opaque;
166
+ * compare for equality only. Empty is a numbering like any other, for a connector whose
167
+ * count for a device never restarts; a connector that begins a device's sequence anew —
168
+ * having lost its count, or the device having come back to it — must give it a
169
+ * numbering_id never used for that device before. Every numbering starts at 1. On the app leg
170
+ * the gateway derives it from the connector's own id and the connector's numbering_id
171
+ * alone, so that it is the same across a gateway restart and changes whenever either
172
+ * does — a numbering restart, or a device moving to another connector.
173
+ *
174
+ * @generated from field: string numbering_id = 11;
175
+ */
176
+ numberingId: string;
95
177
  };
96
178
 
97
179
  /**
@@ -11,7 +11,7 @@ import { file_kusinta_iot_identity_v1_identity } from "../../identity/v1/identit
11
11
  * Describes the file kusinta/iot/device/v1/device_event.proto.
12
12
  */
13
13
  export const file_kusinta_iot_device_v1_device_event = /*@__PURE__*/
14
- fileDesc("CihrdXNpbnRhL2lvdC9kZXZpY2UvdjEvZGV2aWNlX2V2ZW50LnByb3RvEhVrdXNpbnRhLmlvdC5kZXZpY2UudjEixQIKC0RldmljZUV2ZW50EjQKCWRldmljZV9pZBgBIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkEhgKC2VuZHBvaW50X2lkGAIgASgNSACIAQESEgoKY2x1c3Rlcl9pZBgDIAEoDRIQCghldmVudF9pZBgEIAEoDRIUCgxldmVudF9udW1iZXIYBSABKAQSLQoJdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI2Cghwcmlvcml0eRgHIAEoDjIkLmt1c2ludGEuaW90LmRldmljZS52MS5FdmVudFByaW9yaXR5EjMKBGRhdGEYCCABKAsyJS5rdXNpbnRhLmlvdC5kZXZpY2UudjEuQXR0cmlidXRlVmFsdWVCDgoMX2VuZHBvaW50X2lkIncKEERldmljZUV2ZW50QmF0Y2gSMgoGZXZlbnRzGAEgAygLMiIua3VzaW50YS5pb3QuZGV2aWNlLnYxLkRldmljZUV2ZW50Ei8KC3JlY2VpdmVkX2F0GAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCp/Cg1FdmVudFByaW9yaXR5Eh4KGkVWRU5UX1BSSU9SSVRZX1VOU1BFQ0lGSUVEEAASGAoURVZFTlRfUFJJT1JJVFlfREVCVUcQARIXChNFVkVOVF9QUklPUklUWV9JTkZPEAISGwoXRVZFTlRfUFJJT1JJVFlfQ1JJVElDQUwQA0ICSAFiBnByb3RvMw", [file_google_protobuf_timestamp, file_kusinta_iot_device_v1_cluster_state, file_kusinta_iot_identity_v1_identity]);
14
+ fileDesc("CihrdXNpbnRhL2lvdC9kZXZpY2UvdjEvZGV2aWNlX2V2ZW50LnByb3RvEhVrdXNpbnRhLmlvdC5kZXZpY2UudjEirwMKC0RldmljZUV2ZW50EjQKCWRldmljZV9pZBgBIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkEhgKC2VuZHBvaW50X2lkGAIgASgNSACIAQESEgoKY2x1c3Rlcl9pZBgDIAEoDRIQCghldmVudF9pZBgEIAEoDRIUCgxldmVudF9udW1iZXIYBSABKAQSLQoJdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI2Cghwcmlvcml0eRgHIAEoDjIkLmt1c2ludGEuaW90LmRldmljZS52MS5FdmVudFByaW9yaXR5EjMKBGRhdGEYCCABKAsyJS5rdXNpbnRhLmlvdC5kZXZpY2UudjEuQXR0cmlidXRlVmFsdWUSIgoVcHJldmlvdXNfZXZlbnRfbnVtYmVyGAkgASgESAGIAQESFAoMZm9sbG93c19sb3NzGAogASgIEhQKDG51bWJlcmluZ19pZBgLIAEoCUIOCgxfZW5kcG9pbnRfaWRCGAoWX3ByZXZpb3VzX2V2ZW50X251bWJlciJ3ChBEZXZpY2VFdmVudEJhdGNoEjIKBmV2ZW50cxgBIAMoCzIiLmt1c2ludGEuaW90LmRldmljZS52MS5EZXZpY2VFdmVudBIvCgtyZWNlaXZlZF9hdBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAqfwoNRXZlbnRQcmlvcml0eRIeChpFVkVOVF9QUklPUklUWV9VTlNQRUNJRklFRBAAEhgKFEVWRU5UX1BSSU9SSVRZX0RFQlVHEAESFwoTRVZFTlRfUFJJT1JJVFlfSU5GTxACEhsKF0VWRU5UX1BSSU9SSVRZX0NSSVRJQ0FMEANCAkgBYgZwcm90bzM", [file_google_protobuf_timestamp, file_kusinta_iot_device_v1_cluster_state, file_kusinta_iot_identity_v1_identity]);
15
15
 
16
16
  /**
17
17
  * Describes the message kusinta.iot.device.v1.DeviceEvent.
@@ -283,12 +283,20 @@ export declare type Device = Message<"kusinta.iot.device.v1.Device"> & {
283
283
  * Advisory, for showing staleness in a UI. It is not a removal signal — that is
284
284
  * webrtc.v1.DeviceRemoved, sent only when a connector reports the device gone.
285
285
  *
286
+ * Unset in a service view (access.v1.DeviceAcl.relation SERVICE): a device that reports on
287
+ * change would give away each opening and each turn of a knob. Service learns whether it
288
+ * is reachable from webrtc.v1.ServiceStatus.
289
+ *
286
290
  * @generated from field: google.protobuf.Timestamp last_seen = 20;
287
291
  */
288
292
  lastSeen?: Timestamp | undefined;
289
293
 
290
294
  /**
291
- * When any field of this Device last changed value.
295
+ * When any field of this Device last changed value. Unset in a service view, for the
296
+ * reason last_seen is. Both are also unset when they date from before the recipient's
297
+ * current residency in the home, or from a home they did not live in at the time (see
298
+ * access.v1.MembershipRelation).
299
+ * Whether such a device is reachable is still told by its webrtc.v1.ServiceStatus.
292
300
  *
293
301
  * @generated from field: google.protobuf.Timestamp last_updated = 21;
294
302
  */
@@ -102,6 +102,9 @@ export declare const ClimateLeadSettingsSchema: GenMessage<ClimateLeadSettings>;
102
102
  */
103
103
  export declare type DeviceLink = Message<"kusinta.iot.link.v1.DeviceLink"> & {
104
104
  /**
105
+ * Opaque, and must not encode when the link was made — a UUIDv4 is the expected form — since
106
+ * that time is withheld from some recipients (see created_at).
107
+ *
105
108
  * @generated from field: string link_id = 1;
106
109
  */
107
110
  linkId: string;
@@ -140,6 +143,10 @@ export declare type DeviceLink = Message<"kusinta.iot.link.v1.DeviceLink"> & {
140
143
  state: LinkState;
141
144
 
142
145
  /**
146
+ * Unset when it is withheld from the recipient: from service in a home, and from anyone
147
+ * when it dates from before their current residency in the home, or from a home they did
148
+ * not live in at the time (see access.v1.MembershipRelation).
149
+ *
143
150
  * @generated from field: google.protobuf.Timestamp created_at = 7;
144
151
  */
145
152
  createdAt?: Timestamp | undefined;
@@ -164,6 +171,16 @@ export declare type DeviceLink = Message<"kusinta.iot.link.v1.DeviceLink"> & {
164
171
  * @generated from field: kusinta.iot.link.v1.LinkSettings settings = 9;
165
172
  */
166
173
  settings?: LinkSettings | undefined;
174
+
175
+ /**
176
+ * Set when the recipient sees this link as service, because an end is in a home (see
177
+ * access.v1.MembershipRelation): state, state_detail, settings and created_at are
178
+ * WITHHELD and left unset, not unconfigured. An app must not render it as a link doing
179
+ * nothing.
180
+ *
181
+ * @generated from field: bool details_withheld = 10;
182
+ */
183
+ detailsWithheld: boolean;
167
184
  };
168
185
 
169
186
  /**
@@ -11,7 +11,7 @@ import { file_kusinta_iot_identity_v1_identity } from "../../identity/v1/identit
11
11
  * Describes the file kusinta/iot/link/v1/link.proto.
12
12
  */
13
13
  export const file_kusinta_iot_link_v1_link = /*@__PURE__*/
14
- fileDesc("Ch5rdXNpbnRhL2lvdC9saW5rL3YxL2xpbmsucHJvdG8SE2t1c2ludGEuaW90LmxpbmsudjEiYAoMTGlua1NldHRpbmdzEkAKDGNsaW1hdGVfbGVhZBgBIAEoCzIoLmt1c2ludGEuaW90LmxpbmsudjEuQ2xpbWF0ZUxlYWRTZXR0aW5nc0gAQg4KDHBlcl9mdW5jdGlvbiJHChNDbGltYXRlTGVhZFNldHRpbmdzEhwKD3RhcmdldF9zZXRwb2ludBgBIAEoEUgAiAEBQhIKEF90YXJnZXRfc2V0cG9pbnQilwMKCkRldmljZUxpbmsSDwoHbGlua19pZBgBIAEoCRIxCgZzZW5kZXIYAiABKAsyIS5rdXNpbnRhLmlvdC5pZGVudGl0eS52MS5EZXZpY2VJZBIzCghyZWNlaXZlchgDIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkEjMKCGZ1bmN0aW9uGAQgASgOMiEua3VzaW50YS5pb3QubGluay52MS5MaW5rRnVuY3Rpb24SKwoEbW9kZRgFIAEoDjIdLmt1c2ludGEuaW90LmxpbmsudjEuTGlua01vZGUSLQoFc3RhdGUYBiABKA4yHi5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtTdGF0ZRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIUCgxzdGF0ZV9kZXRhaWwYCCABKAkSMwoIc2V0dGluZ3MYCSABKAsyIS5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtTZXR0aW5nc0oECBQQHiL7AQoOTGlua0NhcGFiaWxpdHkSMwoIZnVuY3Rpb24YASABKA4yIS5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtGdW5jdGlvbhI1CglkaXJlY3Rpb24YAiABKA4yIi5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtEaXJlY3Rpb24SNgoPc3VwcG9ydGVkX21vZGVzGAMgAygOMh0ua3VzaW50YS5pb3QubGluay52MS5MaW5rTW9kZRI2CglhdHRyaWJ1dGUYBCABKAsyIy5rdXNpbnRhLmlvdC5hY2Nlc3MudjEuQXR0cmlidXRlUmVmEg0KBWxhYmVsGAUgASgJIkAKDkRldmljZUxpbmtMaXN0Ei4KBWxpbmtzGAEgAygLMh8ua3VzaW50YS5pb3QubGluay52MS5EZXZpY2VMaW5rKo8BCgxMaW5rRnVuY3Rpb24SHQoZTElOS19GVU5DVElPTl9VTlNQRUNJRklFRBAAEh4KGkxJTktfRlVOQ1RJT05fQ0xJTUFURV9MRUFEEAESHgoaTElOS19GVU5DVElPTl9XSU5ET1dfU1RBVEUQAhIgChxMSU5LX0ZVTkNUSU9OX1JFTU9URV9DT05UUk9MEAMqZQoNTGlua0RpcmVjdGlvbhIeChpMSU5LX0RJUkVDVElPTl9VTlNQRUNJRklFRBAAEhkKFUxJTktfRElSRUNUSU9OX1NPVVJDRRABEhkKFUxJTktfRElSRUNUSU9OX1RBUkdFVBACKk0KCExpbmtNb2RlEhkKFUxJTktfTU9ERV9VTlNQRUNJRklFRBAAEhIKDkxJTktfTU9ERV9IQVJEEAESEgoOTElOS19NT0RFX1NPRlQQAiptCglMaW5rU3RhdGUSGgoWTElOS19TVEFURV9VTlNQRUNJRklFRBAAEhUKEUxJTktfU1RBVEVfQUNUSVZFEAESFQoRTElOS19TVEFURV9CUk9LRU4QAhIWChJMSU5LX1NUQVRFX1VOS05PV04QA0ICSAFiBnByb3RvMw", [file_google_protobuf_timestamp, file_kusinta_iot_access_v1_acl, file_kusinta_iot_identity_v1_identity]);
14
+ fileDesc("Ch5rdXNpbnRhL2lvdC9saW5rL3YxL2xpbmsucHJvdG8SE2t1c2ludGEuaW90LmxpbmsudjEiYAoMTGlua1NldHRpbmdzEkAKDGNsaW1hdGVfbGVhZBgBIAEoCzIoLmt1c2ludGEuaW90LmxpbmsudjEuQ2xpbWF0ZUxlYWRTZXR0aW5nc0gAQg4KDHBlcl9mdW5jdGlvbiJHChNDbGltYXRlTGVhZFNldHRpbmdzEhwKD3RhcmdldF9zZXRwb2ludBgBIAEoEUgAiAEBQhIKEF90YXJnZXRfc2V0cG9pbnQisQMKCkRldmljZUxpbmsSDwoHbGlua19pZBgBIAEoCRIxCgZzZW5kZXIYAiABKAsyIS5rdXNpbnRhLmlvdC5pZGVudGl0eS52MS5EZXZpY2VJZBIzCghyZWNlaXZlchgDIAEoCzIhLmt1c2ludGEuaW90LmlkZW50aXR5LnYxLkRldmljZUlkEjMKCGZ1bmN0aW9uGAQgASgOMiEua3VzaW50YS5pb3QubGluay52MS5MaW5rRnVuY3Rpb24SKwoEbW9kZRgFIAEoDjIdLmt1c2ludGEuaW90LmxpbmsudjEuTGlua01vZGUSLQoFc3RhdGUYBiABKA4yHi5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtTdGF0ZRIuCgpjcmVhdGVkX2F0GAcgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIUCgxzdGF0ZV9kZXRhaWwYCCABKAkSMwoIc2V0dGluZ3MYCSABKAsyIS5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtTZXR0aW5ncxIYChBkZXRhaWxzX3dpdGhoZWxkGAogASgISgQIFBAeIvsBCg5MaW5rQ2FwYWJpbGl0eRIzCghmdW5jdGlvbhgBIAEoDjIhLmt1c2ludGEuaW90LmxpbmsudjEuTGlua0Z1bmN0aW9uEjUKCWRpcmVjdGlvbhgCIAEoDjIiLmt1c2ludGEuaW90LmxpbmsudjEuTGlua0RpcmVjdGlvbhI2Cg9zdXBwb3J0ZWRfbW9kZXMYAyADKA4yHS5rdXNpbnRhLmlvdC5saW5rLnYxLkxpbmtNb2RlEjYKCWF0dHJpYnV0ZRgEIAEoCzIjLmt1c2ludGEuaW90LmFjY2Vzcy52MS5BdHRyaWJ1dGVSZWYSDQoFbGFiZWwYBSABKAkiQAoORGV2aWNlTGlua0xpc3QSLgoFbGlua3MYASADKAsyHy5rdXNpbnRhLmlvdC5saW5rLnYxLkRldmljZUxpbmsqjwEKDExpbmtGdW5jdGlvbhIdChlMSU5LX0ZVTkNUSU9OX1VOU1BFQ0lGSUVEEAASHgoaTElOS19GVU5DVElPTl9DTElNQVRFX0xFQUQQARIeChpMSU5LX0ZVTkNUSU9OX1dJTkRPV19TVEFURRACEiAKHExJTktfRlVOQ1RJT05fUkVNT1RFX0NPTlRST0wQAyplCg1MaW5rRGlyZWN0aW9uEh4KGkxJTktfRElSRUNUSU9OX1VOU1BFQ0lGSUVEEAASGQoVTElOS19ESVJFQ1RJT05fU09VUkNFEAESGQoVTElOS19ESVJFQ1RJT05fVEFSR0VUEAIqTQoITGlua01vZGUSGQoVTElOS19NT0RFX1VOU1BFQ0lGSUVEEAASEgoOTElOS19NT0RFX0hBUkQQARISCg5MSU5LX01PREVfU09GVBACKm0KCUxpbmtTdGF0ZRIaChZMSU5LX1NUQVRFX1VOU1BFQ0lGSUVEEAASFQoRTElOS19TVEFURV9BQ1RJVkUQARIVChFMSU5LX1NUQVRFX0JST0tFThACEhYKEkxJTktfU1RBVEVfVU5LTk9XThADQgJIAWIGcHJvdG8z", [file_google_protobuf_timestamp, file_kusinta_iot_access_v1_acl, file_kusinta_iot_identity_v1_identity]);
15
15
 
16
16
  /**
17
17
  * Describes the message kusinta.iot.link.v1.LinkSettings.