@kusinta/iot-schema 0.1.0-beta.18 → 0.1.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kusinta/iot-schema",
3
- "version": "0.1.0-beta.18",
3
+ "version": "0.1.0-beta.19",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "files": ["src"],
@@ -14,6 +14,7 @@
14
14
  "./device": "./src/kusinta/iot/device/v1/device_pb.js",
15
15
  "./device/descriptor": "./src/kusinta/iot/device/v1/descriptor_pb.js",
16
16
  "./device/properties": "./src/kusinta/iot/device/v1/properties_pb.js",
17
+ "./device/matter-options": "./src/kusinta/iot/device/v1/matter_options_pb.js",
17
18
  "./device/property-update": "./src/kusinta/iot/device/v1/property_update_pb.js",
18
19
  "./space": "./src/kusinta/iot/space/v1/space_pb.js",
19
20
  "./access": "./src/kusinta/iot/access/v1/acl_pb.js",
@@ -19,6 +19,24 @@ export declare const file_kusinta_iot_device_v1_device: GenFile;
19
19
  * Field number convention: 1 = descriptor, 2-49 = standard Matter device types,
20
20
  * 50-99 = vendor extensions, 20+ = timestamps.
21
21
  *
22
+ * Selecting the properties case
23
+ *
24
+ * Each non-vendor case's message type declares the Matter device type it models in
25
+ * (matter_device_type), so the mapping from DeviceDescriptor.matter_device_type_id to a
26
+ * case is read from the descriptor rather than hard-coded. See matter_options.proto, and
27
+ * property_update.proto for the full resolution rule.
28
+ *
29
+ * matter_device_type_id stays a bare uint32: a connector must be able to report a device
30
+ * type this schema does not model. Such a device is legitimate — it exists, it belongs in
31
+ * a device list, it simply carries no typed properties. A consumer that cannot match the
32
+ * device type leaves the properties oneof unset and keeps the Device; it MUST NOT drop the
33
+ * device or substitute a nearby case. An unset oneof therefore means either "not modelled"
34
+ * or "modelled but nothing reported yet", which are indistinguishable here on purpose;
35
+ * distinguish them by re-resolving matter_device_type_id if you need to.
36
+ *
37
+ * Adding a case: annotate the new *Properties message with its (matter_device_type). A case
38
+ * without one resolves for nobody.
39
+ *
22
40
  * @generated from message kusinta.iot.device.v1.Device
23
41
  */
24
42
  export declare type Device = Message<"kusinta.iot.device.v1.Device"> & {
@@ -0,0 +1,46 @@
1
+ // @generated by protoc-gen-es v2.12.0 with parameter "target=js+dts,import_extension=js"
2
+ // @generated from file kusinta/iot/device/v1/matter_options.proto (package kusinta.iot.device.v1, syntax proto3)
3
+ /* eslint-disable */
4
+
5
+ import type { GenExtension, GenFile } from "@bufbuild/protobuf/codegenv2";
6
+ import type { FieldOptions, MessageOptions } from "@bufbuild/protobuf/wkt";
7
+
8
+ /**
9
+ * Describes the file kusinta/iot/device/v1/matter_options.proto.
10
+ */
11
+ export declare const file_kusinta_iot_device_v1_matter_options: GenFile;
12
+
13
+ /**
14
+ * The Matter cluster this attribute belongs to, e.g. 0x0201 for Thermostat.
15
+ *
16
+ * Required alongside matter_attribute because a properties message may span
17
+ * clusters: DimmableLightProperties.on_off is On/Off (0x0006) while its
18
+ * current_level is Level Control (0x0008). Matches PropertyUpdate.cluster_id_hex
19
+ * parsed as a hex integer.
20
+ *
21
+ * @generated from extension: uint32 matter_cluster_id = 50001;
22
+ */
23
+ export declare const matter_cluster_id: GenExtension<FieldOptions, number>;
24
+
25
+ /**
26
+ * The Matter attribute name in the spec's own PascalCase, e.g.
27
+ * "PIROccupiedToUnoccupiedDelay". This is the authoritative spelling; the proto
28
+ * field name is not derived from it and must not be assumed to be. Matches
29
+ * PropertyUpdate.attribute_name byte for byte.
30
+ *
31
+ * @generated from extension: string matter_attribute = 50002;
32
+ */
33
+ export declare const matter_attribute: GenExtension<FieldOptions, string>;
34
+
35
+ /**
36
+ * The Matter device type IDs this properties message models, e.g. 0x0301 for
37
+ * Thermostat. Repeated because one shape of properties can serve several device
38
+ * types; empty on vendor extension messages, which have no Matter device type.
39
+ *
40
+ * A device type appears on at most one properties message, so the mapping from
41
+ * DeviceDescriptor.matter_device_type_id to a Device.properties case is a function.
42
+ *
43
+ * @generated from extension: repeated uint32 matter_device_type = 50003;
44
+ */
45
+ export declare const matter_device_type: GenExtension<MessageOptions, number[]>;
46
+
@@ -0,0 +1,50 @@
1
+ // @generated by protoc-gen-es v2.12.0 with parameter "target=js+dts,import_extension=js"
2
+ // @generated from file kusinta/iot/device/v1/matter_options.proto (package kusinta.iot.device.v1, syntax proto3)
3
+ /* eslint-disable */
4
+
5
+ import { extDesc, fileDesc } from "@bufbuild/protobuf/codegenv2";
6
+ import { file_google_protobuf_descriptor } from "@bufbuild/protobuf/wkt";
7
+
8
+ /**
9
+ * Describes the file kusinta/iot/device/v1/matter_options.proto.
10
+ */
11
+ export const file_kusinta_iot_device_v1_matter_options = /*@__PURE__*/
12
+ fileDesc("CiprdXNpbnRhL2lvdC9kZXZpY2UvdjEvbWF0dGVyX29wdGlvbnMucHJvdG8SFWt1c2ludGEuaW90LmRldmljZS52MTpLChFtYXR0ZXJfY2x1c3Rlcl9pZBIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMY0YYDIAEoDVIPbWF0dGVyQ2x1c3RlcklkOkoKEG1hdHRlcl9hdHRyaWJ1dGUSHS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGNKGAyABKAlSD21hdHRlckF0dHJpYnV0ZTpPChJtYXR0ZXJfZGV2aWNlX3R5cGUSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY04YDIAMoDVIQbWF0dGVyRGV2aWNlVHlwZUICSAFiBnByb3RvMw", [file_google_protobuf_descriptor]);
13
+
14
+ /**
15
+ * The Matter cluster this attribute belongs to, e.g. 0x0201 for Thermostat.
16
+ *
17
+ * Required alongside matter_attribute because a properties message may span
18
+ * clusters: DimmableLightProperties.on_off is On/Off (0x0006) while its
19
+ * current_level is Level Control (0x0008). Matches PropertyUpdate.cluster_id_hex
20
+ * parsed as a hex integer.
21
+ *
22
+ * @generated from extension: uint32 matter_cluster_id = 50001;
23
+ */
24
+ export const matter_cluster_id = /*@__PURE__*/
25
+ extDesc(file_kusinta_iot_device_v1_matter_options, 0);
26
+
27
+ /**
28
+ * The Matter attribute name in the spec's own PascalCase, e.g.
29
+ * "PIROccupiedToUnoccupiedDelay". This is the authoritative spelling; the proto
30
+ * field name is not derived from it and must not be assumed to be. Matches
31
+ * PropertyUpdate.attribute_name byte for byte.
32
+ *
33
+ * @generated from extension: string matter_attribute = 50002;
34
+ */
35
+ export const matter_attribute = /*@__PURE__*/
36
+ extDesc(file_kusinta_iot_device_v1_matter_options, 1);
37
+
38
+ /**
39
+ * The Matter device type IDs this properties message models, e.g. 0x0301 for
40
+ * Thermostat. Repeated because one shape of properties can serve several device
41
+ * types; empty on vendor extension messages, which have no Matter device type.
42
+ *
43
+ * A device type appears on at most one properties message, so the mapping from
44
+ * DeviceDescriptor.matter_device_type_id to a Device.properties case is a function.
45
+ *
46
+ * @generated from extension: repeated uint32 matter_device_type = 50003;
47
+ */
48
+ export const matter_device_type = /*@__PURE__*/
49
+ extDesc(file_kusinta_iot_device_v1_matter_options, 2);
50
+
@@ -11,80 +11,66 @@ import type { Message } from "@bufbuild/protobuf";
11
11
  export declare const file_kusinta_iot_device_v1_properties: GenFile;
12
12
 
13
13
  /**
14
- * Matter Thermostat cluster (0x0201) — device type 0x0301
14
+ * Matter Thermostat cluster (0x0201)
15
15
  *
16
16
  * @generated from message kusinta.iot.device.v1.ThermostatProperties
17
17
  */
18
18
  export declare type ThermostatProperties = Message<"kusinta.iot.device.v1.ThermostatProperties"> & {
19
19
  /**
20
- * LocalTemperature
21
- *
22
- * @generated from field: sint32 local_temperature = 1;
20
+ * @generated from field: optional sint32 local_temperature = 1;
23
21
  */
24
- localTemperature: number;
22
+ localTemperature?: number | undefined;
25
23
 
26
24
  /**
27
- * OccupiedHeatingSetpoint
28
- *
29
- * @generated from field: sint32 occupied_heating_setpoint = 2;
25
+ * @generated from field: optional sint32 occupied_heating_setpoint = 2;
30
26
  */
31
- occupiedHeatingSetpoint: number;
27
+ occupiedHeatingSetpoint?: number | undefined;
32
28
 
33
29
  /**
34
- * OccupiedCoolingSetpoint
35
- *
36
- * @generated from field: sint32 occupied_cooling_setpoint = 3;
30
+ * @generated from field: optional sint32 occupied_cooling_setpoint = 3;
37
31
  */
38
- occupiedCoolingSetpoint: number;
32
+ occupiedCoolingSetpoint?: number | undefined;
39
33
 
40
34
  /**
41
- * MinHeatSetpointLimit — property-owner constraint
35
+ * Property-owner constraint
42
36
  *
43
- * @generated from field: sint32 min_heat_setpoint_limit = 4;
37
+ * @generated from field: optional sint32 min_heat_setpoint_limit = 4;
44
38
  */
45
- minHeatSetpointLimit: number;
39
+ minHeatSetpointLimit?: number | undefined;
46
40
 
47
41
  /**
48
- * MaxHeatSetpointLimit — property-owner constraint
42
+ * Property-owner constraint
49
43
  *
50
- * @generated from field: sint32 max_heat_setpoint_limit = 5;
44
+ * @generated from field: optional sint32 max_heat_setpoint_limit = 5;
51
45
  */
52
- maxHeatSetpointLimit: number;
46
+ maxHeatSetpointLimit?: number | undefined;
53
47
 
54
48
  /**
55
- * MinCoolSetpointLimit
56
- *
57
- * @generated from field: sint32 min_cool_setpoint_limit = 6;
49
+ * @generated from field: optional sint32 min_cool_setpoint_limit = 6;
58
50
  */
59
- minCoolSetpointLimit: number;
51
+ minCoolSetpointLimit?: number | undefined;
60
52
 
61
53
  /**
62
- * MaxCoolSetpointLimit
63
- *
64
- * @generated from field: sint32 max_cool_setpoint_limit = 7;
54
+ * @generated from field: optional sint32 max_cool_setpoint_limit = 7;
65
55
  */
66
- maxCoolSetpointLimit: number;
56
+ maxCoolSetpointLimit?: number | undefined;
67
57
 
68
58
  /**
69
- * ControlSequenceOfOperation enum
70
- *
71
- * @generated from field: uint32 control_sequence_of_operation = 8;
59
+ * @generated from field: optional uint32 control_sequence_of_operation = 8;
72
60
  */
73
- controlSequenceOfOperation: number;
61
+ controlSequenceOfOperation?: number | undefined;
74
62
 
75
63
  /**
76
64
  * SystemMode: Off=0,Auto=1,Cool=3,Heat=4,EmHeat=5
77
65
  *
78
- * @generated from field: uint32 system_mode = 9;
66
+ * @generated from field: optional uint32 system_mode = 9;
79
67
  */
80
- systemMode: number;
68
+ systemMode?: number | undefined;
81
69
 
82
70
  /**
83
- * ThermostatRunningMode
84
- *
85
- * @generated from field: uint32 thermostat_running_mode = 10;
71
+ * @generated from field: optional uint32 thermostat_running_mode = 10;
86
72
  */
87
- thermostatRunningMode: number;
73
+ thermostatRunningMode?: number | undefined;
88
74
  };
89
75
 
90
76
  /**
@@ -94,38 +80,30 @@ export declare type ThermostatProperties = Message<"kusinta.iot.device.v1.Thermo
94
80
  export declare const ThermostatPropertiesSchema: GenMessage<ThermostatProperties>;
95
81
 
96
82
  /**
97
- * Matter Temperature Measurement cluster (0x0402) — device type 0x0302
83
+ * Matter Temperature Measurement cluster (0x0402)
98
84
  *
99
85
  * @generated from message kusinta.iot.device.v1.TemperatureSensorProperties
100
86
  */
101
87
  export declare type TemperatureSensorProperties = Message<"kusinta.iot.device.v1.TemperatureSensorProperties"> & {
102
88
  /**
103
- * MeasuredValue
104
- *
105
- * @generated from field: sint32 measured_value = 1;
89
+ * @generated from field: optional sint32 measured_value = 1;
106
90
  */
107
- measuredValue: number;
91
+ measuredValue?: number | undefined;
108
92
 
109
93
  /**
110
- * MinMeasuredValue
111
- *
112
- * @generated from field: sint32 min_measured_value = 2;
94
+ * @generated from field: optional sint32 min_measured_value = 2;
113
95
  */
114
- minMeasuredValue: number;
96
+ minMeasuredValue?: number | undefined;
115
97
 
116
98
  /**
117
- * MaxMeasuredValue
118
- *
119
- * @generated from field: sint32 max_measured_value = 3;
99
+ * @generated from field: optional sint32 max_measured_value = 3;
120
100
  */
121
- maxMeasuredValue: number;
101
+ maxMeasuredValue?: number | undefined;
122
102
 
123
103
  /**
124
- * Tolerance
125
- *
126
- * @generated from field: uint32 tolerance = 4;
104
+ * @generated from field: optional uint32 tolerance = 4;
127
105
  */
128
- tolerance: number;
106
+ tolerance?: number | undefined;
129
107
  };
130
108
 
131
109
  /**
@@ -135,32 +113,32 @@ export declare type TemperatureSensorProperties = Message<"kusinta.iot.device.v1
135
113
  export declare const TemperatureSensorPropertiesSchema: GenMessage<TemperatureSensorProperties>;
136
114
 
137
115
  /**
138
- * Matter Relative Humidity Measurement cluster (0x0405) — device type 0x0307
116
+ * Matter Relative Humidity Measurement cluster (0x0405)
139
117
  *
140
118
  * @generated from message kusinta.iot.device.v1.HumiditySensorProperties
141
119
  */
142
120
  export declare type HumiditySensorProperties = Message<"kusinta.iot.device.v1.HumiditySensorProperties"> & {
143
121
  /**
144
- * MeasuredValue (% × 100, 0–10000)
122
+ * % × 100, 0–10000
145
123
  *
146
- * @generated from field: uint32 measured_value = 1;
124
+ * @generated from field: optional uint32 measured_value = 1;
147
125
  */
148
- measuredValue: number;
126
+ measuredValue?: number | undefined;
149
127
 
150
128
  /**
151
- * @generated from field: uint32 min_measured_value = 2;
129
+ * @generated from field: optional uint32 min_measured_value = 2;
152
130
  */
153
- minMeasuredValue: number;
131
+ minMeasuredValue?: number | undefined;
154
132
 
155
133
  /**
156
- * @generated from field: uint32 max_measured_value = 3;
134
+ * @generated from field: optional uint32 max_measured_value = 3;
157
135
  */
158
- maxMeasuredValue: number;
136
+ maxMeasuredValue?: number | undefined;
159
137
 
160
138
  /**
161
- * @generated from field: uint32 tolerance = 4;
139
+ * @generated from field: optional uint32 tolerance = 4;
162
140
  */
163
- tolerance: number;
141
+ tolerance?: number | undefined;
164
142
  };
165
143
 
166
144
  /**
@@ -170,7 +148,7 @@ export declare type HumiditySensorProperties = Message<"kusinta.iot.device.v1.Hu
170
148
  export declare const HumiditySensorPropertiesSchema: GenMessage<HumiditySensorProperties>;
171
149
 
172
150
  /**
173
- * Matter Occupancy Sensing cluster (0x0406) — device type 0x0107
151
+ * Matter Occupancy Sensing cluster (0x0406)
174
152
  *
175
153
  * @generated from message kusinta.iot.device.v1.OccupancySensorProperties
176
154
  */
@@ -178,31 +156,31 @@ export declare type OccupancySensorProperties = Message<"kusinta.iot.device.v1.O
178
156
  /**
179
157
  * Occupancy bitmask: bit 0 = occupied
180
158
  *
181
- * @generated from field: uint32 occupancy = 1;
159
+ * @generated from field: optional uint32 occupancy = 1;
182
160
  */
183
- occupancy: number;
161
+ occupancy?: number | undefined;
184
162
 
185
163
  /**
186
164
  * OccupancySensorType: PIR=0,Ultrasonic=1,PIRandUS=2,PhysicalContact=3
187
165
  *
188
- * @generated from field: uint32 occupancy_sensor_type = 2;
166
+ * @generated from field: optional uint32 occupancy_sensor_type = 2;
189
167
  */
190
- occupancySensorType: number;
168
+ occupancySensorType?: number | undefined;
191
169
 
192
170
  /**
193
- * @generated from field: uint32 occupancy_sensor_type_bitmap = 3;
171
+ * @generated from field: optional uint32 occupancy_sensor_type_bitmap = 3;
194
172
  */
195
- occupancySensorTypeBitmap: number;
173
+ occupancySensorTypeBitmap?: number | undefined;
196
174
 
197
175
  /**
198
- * @generated from field: uint32 pir_occ_to_unocc_delay = 4;
176
+ * @generated from field: optional uint32 pir_occupied_to_unoccupied_delay = 4;
199
177
  */
200
- pirOccToUnoccDelay: number;
178
+ pirOccupiedToUnoccupiedDelay?: number | undefined;
201
179
 
202
180
  /**
203
- * @generated from field: uint32 pir_unocc_to_occ_delay = 5;
181
+ * @generated from field: optional uint32 pir_unoccupied_to_occupied_delay = 5;
204
182
  */
205
- pirUnoccToOccDelay: number;
183
+ pirUnoccupiedToOccupiedDelay?: number | undefined;
206
184
  };
207
185
 
208
186
  /**
@@ -212,7 +190,7 @@ export declare type OccupancySensorProperties = Message<"kusinta.iot.device.v1.O
212
190
  export declare const OccupancySensorPropertiesSchema: GenMessage<OccupancySensorProperties>;
213
191
 
214
192
  /**
215
- * Matter Boolean State cluster (0x0045) — device type 0x0015 (Contact Sensor)
193
+ * Matter Boolean State cluster (0x0045)
216
194
  *
217
195
  * @generated from message kusinta.iot.device.v1.ContactSensorProperties
218
196
  */
@@ -220,9 +198,9 @@ export declare type ContactSensorProperties = Message<"kusinta.iot.device.v1.Con
220
198
  /**
221
199
  * StateValue: false = contact open (alarm), true = contact closed (normal)
222
200
  *
223
- * @generated from field: bool state_value = 1;
201
+ * @generated from field: optional bool state_value = 1;
224
202
  */
225
- stateValue: boolean;
203
+ stateValue?: boolean | undefined;
226
204
  };
227
205
 
228
206
  /**
@@ -232,54 +210,58 @@ export declare type ContactSensorProperties = Message<"kusinta.iot.device.v1.Con
232
210
  export declare const ContactSensorPropertiesSchema: GenMessage<ContactSensorProperties>;
233
211
 
234
212
  /**
235
- * Matter Window Covering cluster (0x0102) — device type 0x0202
213
+ * Matter Window Covering cluster (0x0102)
236
214
  *
237
215
  * @generated from message kusinta.iot.device.v1.WindowCoveringProperties
238
216
  */
239
217
  export declare type WindowCoveringProperties = Message<"kusinta.iot.device.v1.WindowCoveringProperties"> & {
240
218
  /**
241
- * @generated from field: uint32 covering_type = 1;
219
+ * The Matter attribute is the bare "Type"; the field keeps a qualified name because
220
+ * `type` is a poor field name and keyword-adjacent in several target languages. The
221
+ * mapping is in (matter_attribute), so the divergence costs consumers nothing.
222
+ *
223
+ * @generated from field: optional uint32 covering_type = 1;
242
224
  */
243
- coveringType: number;
225
+ coveringType?: number | undefined;
244
226
 
245
227
  /**
246
228
  * current_position_lift_percent100ths is the primary attribute in Matter 1.5.1 (0–10000)
247
229
  *
248
- * @generated from field: uint32 current_position_lift_percent100ths = 2;
230
+ * @generated from field: optional uint32 current_position_lift_percent100ths = 2;
249
231
  */
250
- currentPositionLiftPercent100ths: number;
232
+ currentPositionLiftPercent100ths?: number | undefined;
251
233
 
252
234
  /**
253
- * @generated from field: uint32 current_position_tilt_percent100ths = 3;
235
+ * @generated from field: optional uint32 current_position_tilt_percent100ths = 3;
254
236
  */
255
- currentPositionTiltPercent100ths: number;
237
+ currentPositionTiltPercent100ths?: number | undefined;
256
238
 
257
239
  /**
258
- * @generated from field: uint32 target_position_lift_percent100ths = 4;
240
+ * @generated from field: optional uint32 target_position_lift_percent100ths = 4;
259
241
  */
260
- targetPositionLiftPercent100ths: number;
242
+ targetPositionLiftPercent100ths?: number | undefined;
261
243
 
262
244
  /**
263
- * @generated from field: uint32 target_position_tilt_percent100ths = 5;
245
+ * @generated from field: optional uint32 target_position_tilt_percent100ths = 5;
264
246
  */
265
- targetPositionTiltPercent100ths: number;
247
+ targetPositionTiltPercent100ths?: number | undefined;
266
248
 
267
249
  /**
268
250
  * bitmask: global, lift, tilt
269
251
  *
270
- * @generated from field: uint32 operational_status = 6;
252
+ * @generated from field: optional uint32 operational_status = 6;
271
253
  */
272
- operationalStatus: number;
254
+ operationalStatus?: number | undefined;
273
255
 
274
256
  /**
275
- * @generated from field: uint32 end_product_type = 7;
257
+ * @generated from field: optional uint32 end_product_type = 7;
276
258
  */
277
- endProductType: number;
259
+ endProductType?: number | undefined;
278
260
 
279
261
  /**
280
- * @generated from field: uint32 mode = 8;
262
+ * @generated from field: optional uint32 mode = 8;
281
263
  */
282
- mode: number;
264
+ mode?: number | undefined;
283
265
  };
284
266
 
285
267
  /**
@@ -289,7 +271,7 @@ export declare type WindowCoveringProperties = Message<"kusinta.iot.device.v1.Wi
289
271
  export declare const WindowCoveringPropertiesSchema: GenMessage<WindowCoveringProperties>;
290
272
 
291
273
  /**
292
- * Matter Door Lock cluster (0x0101) — device type 0x000A
274
+ * Matter Door Lock cluster (0x0101 — a cluster ID, not the 0x0101 Dimmable Light device type)
293
275
  *
294
276
  * @generated from message kusinta.iot.device.v1.DoorLockProperties
295
277
  */
@@ -297,37 +279,31 @@ export declare type DoorLockProperties = Message<"kusinta.iot.device.v1.DoorLock
297
279
  /**
298
280
  * LockState: NotFullyLocked=0,Locked=1,Unlocked=2,Unlatched=3
299
281
  *
300
- * @generated from field: uint32 lock_state = 1;
282
+ * @generated from field: optional uint32 lock_state = 1;
301
283
  */
302
- lockState: number;
284
+ lockState?: number | undefined;
303
285
 
304
286
  /**
305
- * LockType enum
306
- *
307
- * @generated from field: uint32 lock_type = 2;
287
+ * @generated from field: optional uint32 lock_type = 2;
308
288
  */
309
- lockType: number;
289
+ lockType?: number | undefined;
310
290
 
311
291
  /**
312
- * ActuatorEnabled
313
- *
314
- * @generated from field: bool actuator_enabled = 3;
292
+ * @generated from field: optional bool actuator_enabled = 3;
315
293
  */
316
- actuatorEnabled: boolean;
294
+ actuatorEnabled?: boolean | undefined;
317
295
 
318
296
  /**
319
- * DoorState (requires door sensor hardware)
297
+ * Requires door sensor hardware
320
298
  *
321
- * @generated from field: uint32 door_state = 4;
299
+ * @generated from field: optional uint32 door_state = 4;
322
300
  */
323
- doorState: number;
301
+ doorState?: number | undefined;
324
302
 
325
303
  /**
326
- * OperatingMode
327
- *
328
- * @generated from field: uint32 operating_mode = 5;
304
+ * @generated from field: optional uint32 operating_mode = 5;
329
305
  */
330
- operatingMode: number;
306
+ operatingMode?: number | undefined;
331
307
  };
332
308
 
333
309
  /**
@@ -337,45 +313,35 @@ export declare type DoorLockProperties = Message<"kusinta.iot.device.v1.DoorLock
337
313
  export declare const DoorLockPropertiesSchema: GenMessage<DoorLockProperties>;
338
314
 
339
315
  /**
340
- * Matter On/Off cluster (0x0006) — device type 0x0100 (On/Off Light)
316
+ * Matter On/Off cluster (0x0006)
341
317
  *
342
318
  * @generated from message kusinta.iot.device.v1.OnOffLightProperties
343
319
  */
344
320
  export declare type OnOffLightProperties = Message<"kusinta.iot.device.v1.OnOffLightProperties"> & {
345
321
  /**
346
- * OnOff
347
- *
348
- * @generated from field: bool on_off = 1;
322
+ * @generated from field: optional bool on_off = 1;
349
323
  */
350
- onOff: boolean;
324
+ onOff?: boolean | undefined;
351
325
 
352
326
  /**
353
- * GlobalSceneControl
354
- *
355
- * @generated from field: bool global_scene_control = 2;
327
+ * @generated from field: optional bool global_scene_control = 2;
356
328
  */
357
- globalSceneControl: boolean;
329
+ globalSceneControl?: boolean | undefined;
358
330
 
359
331
  /**
360
- * OnTime
361
- *
362
- * @generated from field: uint32 on_time = 3;
332
+ * @generated from field: optional uint32 on_time = 3;
363
333
  */
364
- onTime: number;
334
+ onTime?: number | undefined;
365
335
 
366
336
  /**
367
- * OffWaitTime
368
- *
369
- * @generated from field: uint32 off_wait_time = 4;
337
+ * @generated from field: optional uint32 off_wait_time = 4;
370
338
  */
371
- offWaitTime: number;
339
+ offWaitTime?: number | undefined;
372
340
 
373
341
  /**
374
- * StartUpOnOff
375
- *
376
- * @generated from field: uint32 start_up_on_off = 5;
342
+ * @generated from field: optional uint32 start_up_on_off = 5;
377
343
  */
378
- startUpOnOff: number;
344
+ startUpOnOff?: number | undefined;
379
345
  };
380
346
 
381
347
  /**
@@ -385,57 +351,47 @@ export declare type OnOffLightProperties = Message<"kusinta.iot.device.v1.OnOffL
385
351
  export declare const OnOffLightPropertiesSchema: GenMessage<OnOffLightProperties>;
386
352
 
387
353
  /**
388
- * Matter On/Off + Level Control cluster (0x0008) — device type 0x010B (Dimmable Light)
354
+ * Matter On/Off (0x0006) + Level Control (0x0008) clusters
389
355
  *
390
356
  * @generated from message kusinta.iot.device.v1.DimmableLightProperties
391
357
  */
392
358
  export declare type DimmableLightProperties = Message<"kusinta.iot.device.v1.DimmableLightProperties"> & {
393
359
  /**
394
- * @generated from field: bool on_off = 1;
360
+ * @generated from field: optional bool on_off = 1;
395
361
  */
396
- onOff: boolean;
362
+ onOff?: boolean | undefined;
397
363
 
398
364
  /**
399
365
  * CurrentLevel (0–254)
400
366
  *
401
- * @generated from field: uint32 current_level = 2;
367
+ * @generated from field: optional uint32 current_level = 2;
402
368
  */
403
- currentLevel: number;
369
+ currentLevel?: number | undefined;
404
370
 
405
371
  /**
406
- * MinLevel
407
- *
408
- * @generated from field: uint32 min_level = 3;
372
+ * @generated from field: optional uint32 min_level = 3;
409
373
  */
410
- minLevel: number;
374
+ minLevel?: number | undefined;
411
375
 
412
376
  /**
413
- * MaxLevel
414
- *
415
- * @generated from field: uint32 max_level = 4;
377
+ * @generated from field: optional uint32 max_level = 4;
416
378
  */
417
- maxLevel: number;
379
+ maxLevel?: number | undefined;
418
380
 
419
381
  /**
420
- * OnLevel
421
- *
422
- * @generated from field: uint32 on_level = 5;
382
+ * @generated from field: optional uint32 on_level = 5;
423
383
  */
424
- onLevel: number;
384
+ onLevel?: number | undefined;
425
385
 
426
386
  /**
427
- * StartUpCurrentLevel
428
- *
429
- * @generated from field: uint32 start_up_current_level = 6;
387
+ * @generated from field: optional uint32 start_up_current_level = 6;
430
388
  */
431
- startUpCurrentLevel: number;
389
+ startUpCurrentLevel?: number | undefined;
432
390
 
433
391
  /**
434
- * RemainingTime
435
- *
436
- * @generated from field: uint32 remaining_time = 7;
392
+ * @generated from field: optional uint32 remaining_time = 7;
437
393
  */
438
- remainingTime: number;
394
+ remainingTime?: number | undefined;
439
395
  };
440
396
 
441
397
  /**
@@ -445,55 +401,45 @@ export declare type DimmableLightProperties = Message<"kusinta.iot.device.v1.Dim
445
401
  export declare const DimmableLightPropertiesSchema: GenMessage<DimmableLightProperties>;
446
402
 
447
403
  /**
448
- * Matter On/Off + Level + Color Control cluster (0x0300) — device type 0x010C
404
+ * Matter On/Off (0x0006) + Level Control (0x0008) + Color Control (0x0300) clusters
449
405
  *
450
406
  * @generated from message kusinta.iot.device.v1.ColorTemperatureLightProperties
451
407
  */
452
408
  export declare type ColorTemperatureLightProperties = Message<"kusinta.iot.device.v1.ColorTemperatureLightProperties"> & {
453
409
  /**
454
- * @generated from field: bool on_off = 1;
410
+ * @generated from field: optional bool on_off = 1;
455
411
  */
456
- onOff: boolean;
412
+ onOff?: boolean | undefined;
457
413
 
458
414
  /**
459
- * @generated from field: uint32 current_level = 2;
415
+ * @generated from field: optional uint32 current_level = 2;
460
416
  */
461
- currentLevel: number;
417
+ currentLevel?: number | undefined;
462
418
 
463
419
  /**
464
- * ColorTemperatureMireds
465
- *
466
- * @generated from field: uint32 color_temperature_mireds = 3;
420
+ * @generated from field: optional uint32 color_temperature_mireds = 3;
467
421
  */
468
- colorTemperatureMireds: number;
422
+ colorTemperatureMireds?: number | undefined;
469
423
 
470
424
  /**
471
- * ColorTempPhysicalMinMireds
472
- *
473
- * @generated from field: uint32 color_temp_physical_min_mireds = 4;
425
+ * @generated from field: optional uint32 color_temp_physical_min_mireds = 4;
474
426
  */
475
- colorTempPhysicalMinMireds: number;
427
+ colorTempPhysicalMinMireds?: number | undefined;
476
428
 
477
429
  /**
478
- * ColorTempPhysicalMaxMireds
479
- *
480
- * @generated from field: uint32 color_temp_physical_max_mireds = 5;
430
+ * @generated from field: optional uint32 color_temp_physical_max_mireds = 5;
481
431
  */
482
- colorTempPhysicalMaxMireds: number;
432
+ colorTempPhysicalMaxMireds?: number | undefined;
483
433
 
484
434
  /**
485
- * StartUpColorTemperatureMireds
486
- *
487
- * @generated from field: uint32 startup_color_temperature_mireds = 6;
435
+ * @generated from field: optional uint32 startup_color_temperature_mireds = 6;
488
436
  */
489
- startupColorTemperatureMireds: number;
437
+ startupColorTemperatureMireds?: number | undefined;
490
438
 
491
439
  /**
492
- * ColorMode
493
- *
494
- * @generated from field: uint32 color_mode = 7;
440
+ * @generated from field: optional uint32 color_mode = 7;
495
441
  */
496
- colorMode: number;
442
+ colorMode?: number | undefined;
497
443
  };
498
444
 
499
445
  /**
@@ -503,38 +449,59 @@ export declare type ColorTemperatureLightProperties = Message<"kusinta.iot.devic
503
449
  export declare const ColorTemperatureLightPropertiesSchema: GenMessage<ColorTemperatureLightProperties>;
504
450
 
505
451
  /**
506
- * Matter Electrical Measurement cluster (0x0B04) — device type 0x0510
452
+ * Matter Electrical Power Measurement cluster (0x0090)
453
+ *
454
+ * Was Zigbee ElectricalMeasurement (0x0B04) with that cluster's RMS* attribute names;
455
+ * 0x0B04 does not exist in Matter, so a Matter connector could never have produced a
456
+ * PropertyUpdate that resolved here.
457
+ *
458
+ * Values are Matter's own units and width: sint64 in mW / mV / mA / mHz. A connector
459
+ * forwards what the cluster reports without rescaling, which is the point — the earlier
460
+ * int32/uint32 fields used this schema's own scaling (whole watts, volts × 10, amps × 1000,
461
+ * Hz × 100) while their (matter_attribute) claimed to carry the Matter attribute, so every
462
+ * connector had to divide, every consumer trusting the annotation was wrong by 10× to 1000×,
463
+ * and sub-watt resolution was gone before the value reached the wire. In Matter's mW an
464
+ * int32 caps at ~2.1 kW, so the unit and the width had to move together.
465
+ *
466
+ * Signed throughout, matching the cluster: active_power and active_current go negative on
467
+ * export. sint64 rather than int64 because zigzag keeps negatives at 1-5 bytes instead of
468
+ * the fixed 10 that int64 spends on any negative value.
469
+ *
470
+ * Matter types these as nullable. This schema has no presence anywhere in properties, so 0
471
+ * still means "not reported" rather than "measured zero" — unchanged, and untidy for a
472
+ * quantity that can legitimately read zero. Treat 0 as absent for these four; introducing
473
+ * presence is a schema-wide decision, not a per-message one.
507
474
  *
508
475
  * @generated from message kusinta.iot.device.v1.EnergySensorProperties
509
476
  */
510
477
  export declare type EnergySensorProperties = Message<"kusinta.iot.device.v1.EnergySensorProperties"> & {
511
478
  /**
512
- * ActivePower (watts)
479
+ * Milliwatts, negative on export
513
480
  *
514
- * @generated from field: int32 active_power = 1;
481
+ * @generated from field: optional sint64 active_power = 5;
515
482
  */
516
- activePower: number;
483
+ activePower?: bigint | undefined;
517
484
 
518
485
  /**
519
- * RmsVoltage (volts × 10)
486
+ * Millivolts
520
487
  *
521
- * @generated from field: uint32 rms_voltage = 2;
488
+ * @generated from field: optional sint64 voltage = 6;
522
489
  */
523
- rmsVoltage: number;
490
+ voltage?: bigint | undefined;
524
491
 
525
492
  /**
526
- * RmsCurrent (amps × 1000)
493
+ * Milliamps, negative on export
527
494
  *
528
- * @generated from field: uint32 rms_current = 3;
495
+ * @generated from field: optional sint64 active_current = 7;
529
496
  */
530
- rmsCurrent: number;
497
+ activeCurrent?: bigint | undefined;
531
498
 
532
499
  /**
533
- * AcFrequency (Hz × 100)
500
+ * Millihertz
534
501
  *
535
- * @generated from field: uint32 ac_frequency = 4;
502
+ * @generated from field: optional sint64 frequency = 8;
536
503
  */
537
- acFrequency: number;
504
+ frequency?: bigint | undefined;
538
505
  };
539
506
 
540
507
  /**
@@ -544,32 +511,32 @@ export declare type EnergySensorProperties = Message<"kusinta.iot.device.v1.Ener
544
511
  export declare const EnergySensorPropertiesSchema: GenMessage<EnergySensorProperties>;
545
512
 
546
513
  /**
547
- * Matter Pressure Measurement cluster (0x0403) — device type 0x0305
514
+ * Matter Pressure Measurement cluster (0x0403)
548
515
  *
549
516
  * @generated from message kusinta.iot.device.v1.PressureSensorProperties
550
517
  */
551
518
  export declare type PressureSensorProperties = Message<"kusinta.iot.device.v1.PressureSensorProperties"> & {
552
519
  /**
553
- * MeasuredValue (kPa × 10)
520
+ * kPa × 10
554
521
  *
555
- * @generated from field: sint32 measured_value = 1;
522
+ * @generated from field: optional sint32 measured_value = 1;
556
523
  */
557
- measuredValue: number;
524
+ measuredValue?: number | undefined;
558
525
 
559
526
  /**
560
- * @generated from field: sint32 min_measured_value = 2;
527
+ * @generated from field: optional sint32 min_measured_value = 2;
561
528
  */
562
- minMeasuredValue: number;
529
+ minMeasuredValue?: number | undefined;
563
530
 
564
531
  /**
565
- * @generated from field: sint32 max_measured_value = 3;
532
+ * @generated from field: optional sint32 max_measured_value = 3;
566
533
  */
567
- maxMeasuredValue: number;
534
+ maxMeasuredValue?: number | undefined;
568
535
 
569
536
  /**
570
- * @generated from field: uint32 tolerance = 4;
537
+ * @generated from field: optional uint32 tolerance = 4;
571
538
  */
572
- tolerance: number;
539
+ tolerance?: number | undefined;
573
540
  };
574
541
 
575
542
  /**
@@ -3,12 +3,13 @@
3
3
  /* eslint-disable */
4
4
 
5
5
  import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
6
+ import { file_kusinta_iot_device_v1_matter_options } from "./matter_options_pb.js";
6
7
 
7
8
  /**
8
9
  * Describes the file kusinta/iot/device/v1/properties.proto.
9
10
  */
10
11
  export const file_kusinta_iot_device_v1_properties = /*@__PURE__*/
11
- fileDesc("CiZrdXNpbnRhL2lvdC9kZXZpY2UvdjEvcHJvcGVydGllcy5wcm90bxIVa3VzaW50YS5pb3QuZGV2aWNlLnYxItgCChRUaGVybW9zdGF0UHJvcGVydGllcxIZChFsb2NhbF90ZW1wZXJhdHVyZRgBIAEoERIhChlvY2N1cGllZF9oZWF0aW5nX3NldHBvaW50GAIgASgREiEKGW9jY3VwaWVkX2Nvb2xpbmdfc2V0cG9pbnQYAyABKBESHwoXbWluX2hlYXRfc2V0cG9pbnRfbGltaXQYBCABKBESHwoXbWF4X2hlYXRfc2V0cG9pbnRfbGltaXQYBSABKBESHwoXbWluX2Nvb2xfc2V0cG9pbnRfbGltaXQYBiABKBESHwoXbWF4X2Nvb2xfc2V0cG9pbnRfbGltaXQYByABKBESJQodY29udHJvbF9zZXF1ZW5jZV9vZl9vcGVyYXRpb24YCCABKA0SEwoLc3lzdGVtX21vZGUYCSABKA0SHwoXdGhlcm1vc3RhdF9ydW5uaW5nX21vZGUYCiABKA0igAEKG1RlbXBlcmF0dXJlU2Vuc29yUHJvcGVydGllcxIWCg5tZWFzdXJlZF92YWx1ZRgBIAEoERIaChJtaW5fbWVhc3VyZWRfdmFsdWUYAiABKBESGgoSbWF4X21lYXN1cmVkX3ZhbHVlGAMgASgREhEKCXRvbGVyYW5jZRgEIAEoDSJ9ChhIdW1pZGl0eVNlbnNvclByb3BlcnRpZXMSFgoObWVhc3VyZWRfdmFsdWUYASABKA0SGgoSbWluX21lYXN1cmVkX3ZhbHVlGAIgASgNEhoKEm1heF9tZWFzdXJlZF92YWx1ZRgDIAEoDRIRCgl0b2xlcmFuY2UYBCABKA0iswEKGU9jY3VwYW5jeVNlbnNvclByb3BlcnRpZXMSEQoJb2NjdXBhbmN5GAEgASgNEh0KFW9jY3VwYW5jeV9zZW5zb3JfdHlwZRgCIAEoDRIkChxvY2N1cGFuY3lfc2Vuc29yX3R5cGVfYml0bWFwGAMgASgNEh4KFnBpcl9vY2NfdG9fdW5vY2NfZGVsYXkYBCABKA0SHgoWcGlyX3Vub2NjX3RvX29jY19kZWxheRgFIAEoDSIuChdDb250YWN0U2Vuc29yUHJvcGVydGllcxITCgtzdGF0ZV92YWx1ZRgBIAEoCCKnAgoYV2luZG93Q292ZXJpbmdQcm9wZXJ0aWVzEhUKDWNvdmVyaW5nX3R5cGUYASABKA0SKwojY3VycmVudF9wb3NpdGlvbl9saWZ0X3BlcmNlbnQxMDB0aHMYAiABKA0SKwojY3VycmVudF9wb3NpdGlvbl90aWx0X3BlcmNlbnQxMDB0aHMYAyABKA0SKgoidGFyZ2V0X3Bvc2l0aW9uX2xpZnRfcGVyY2VudDEwMHRocxgEIAEoDRIqCiJ0YXJnZXRfcG9zaXRpb25fdGlsdF9wZXJjZW50MTAwdGhzGAUgASgNEhoKEm9wZXJhdGlvbmFsX3N0YXR1cxgGIAEoDRIYChBlbmRfcHJvZHVjdF90eXBlGAcgASgNEgwKBG1vZGUYCCABKA0igQEKEkRvb3JMb2NrUHJvcGVydGllcxISCgpsb2NrX3N0YXRlGAEgASgNEhEKCWxvY2tfdHlwZRgCIAEoDRIYChBhY3R1YXRvcl9lbmFibGVkGAMgASgIEhIKCmRvb3Jfc3RhdGUYBCABKA0SFgoOb3BlcmF0aW5nX21vZGUYBSABKA0ihQEKFE9uT2ZmTGlnaHRQcm9wZXJ0aWVzEg4KBm9uX29mZhgBIAEoCBIcChRnbG9iYWxfc2NlbmVfY29udHJvbBgCIAEoCBIPCgdvbl90aW1lGAMgASgNEhUKDW9mZl93YWl0X3RpbWUYBCABKA0SFwoPc3RhcnRfdXBfb25fb2ZmGAUgASgNIrABChdEaW1tYWJsZUxpZ2h0UHJvcGVydGllcxIOCgZvbl9vZmYYASABKAgSFQoNY3VycmVudF9sZXZlbBgCIAEoDRIRCgltaW5fbGV2ZWwYAyABKA0SEQoJbWF4X2xldmVsGAQgASgNEhAKCG9uX2xldmVsGAUgASgNEh4KFnN0YXJ0X3VwX2N1cnJlbnRfbGV2ZWwYBiABKA0SFgoOcmVtYWluaW5nX3RpbWUYByABKA0i+AEKH0NvbG9yVGVtcGVyYXR1cmVMaWdodFByb3BlcnRpZXMSDgoGb25fb2ZmGAEgASgIEhUKDWN1cnJlbnRfbGV2ZWwYAiABKA0SIAoYY29sb3JfdGVtcGVyYXR1cmVfbWlyZWRzGAMgASgNEiYKHmNvbG9yX3RlbXBfcGh5c2ljYWxfbWluX21pcmVkcxgEIAEoDRImCh5jb2xvcl90ZW1wX3BoeXNpY2FsX21heF9taXJlZHMYBSABKA0SKAogc3RhcnR1cF9jb2xvcl90ZW1wZXJhdHVyZV9taXJlZHMYBiABKA0SEgoKY29sb3JfbW9kZRgHIAEoDSJuChZFbmVyZ3lTZW5zb3JQcm9wZXJ0aWVzEhQKDGFjdGl2ZV9wb3dlchgBIAEoBRITCgtybXNfdm9sdGFnZRgCIAEoDRITCgtybXNfY3VycmVudBgDIAEoDRIUCgxhY19mcmVxdWVuY3kYBCABKA0ifQoYUHJlc3N1cmVTZW5zb3JQcm9wZXJ0aWVzEhYKDm1lYXN1cmVkX3ZhbHVlGAEgASgREhoKEm1pbl9tZWFzdXJlZF92YWx1ZRgCIAEoERIaChJtYXhfbWVhc3VyZWRfdmFsdWUYAyABKBESEQoJdG9sZXJhbmNlGAQgASgNQgJIAWIGcHJvdG8z");
12
+ fileDesc("CiZrdXNpbnRhL2lvdC9kZXZpY2UvdjEvcHJvcGVydGllcy5wcm90bxIVa3VzaW50YS5pb3QuZGV2aWNlLnYxItcHChRUaGVybW9zdGF0UHJvcGVydGllcxI5ChFsb2NhbF90ZW1wZXJhdHVyZRgBIAEoEUIZiLUYgQSStRgQTG9jYWxUZW1wZXJhdHVyZUgAiAEBEkgKGW9jY3VwaWVkX2hlYXRpbmdfc2V0cG9pbnQYAiABKBFCIIi1GIEEkrUYF09jY3VwaWVkSGVhdGluZ1NldHBvaW50SAGIAQESSAoZb2NjdXBpZWRfY29vbGluZ19zZXRwb2ludBgDIAEoEUIgiLUYgQSStRgXT2NjdXBpZWRDb29saW5nU2V0cG9pbnRIAogBARJDChdtaW5faGVhdF9zZXRwb2ludF9saW1pdBgEIAEoEUIdiLUYgQSStRgUTWluSGVhdFNldHBvaW50TGltaXRIA4gBARJDChdtYXhfaGVhdF9zZXRwb2ludF9saW1pdBgFIAEoEUIdiLUYgQSStRgUTWF4SGVhdFNldHBvaW50TGltaXRIBIgBARJDChdtaW5fY29vbF9zZXRwb2ludF9saW1pdBgGIAEoEUIdiLUYgQSStRgUTWluQ29vbFNldHBvaW50TGltaXRIBYgBARJDChdtYXhfY29vbF9zZXRwb2ludF9saW1pdBgHIAEoEUIdiLUYgQSStRgUTWF4Q29vbFNldHBvaW50TGltaXRIBogBARJPCh1jb250cm9sX3NlcXVlbmNlX29mX29wZXJhdGlvbhgIIAEoDUIjiLUYgQSStRgaQ29udHJvbFNlcXVlbmNlT2ZPcGVyYXRpb25IB4gBARItCgtzeXN0ZW1fbW9kZRgJIAEoDUITiLUYgQSStRgKU3lzdGVtTW9kZUgIiAEBEkQKF3RoZXJtb3N0YXRfcnVubmluZ19tb2RlGAogASgNQh6ItRiBBJK1GBVUaGVybW9zdGF0UnVubmluZ01vZGVICYgBAToGmrUYAoEGQhQKEl9sb2NhbF90ZW1wZXJhdHVyZUIcChpfb2NjdXBpZWRfaGVhdGluZ19zZXRwb2ludEIcChpfb2NjdXBpZWRfY29vbGluZ19zZXRwb2ludEIaChhfbWluX2hlYXRfc2V0cG9pbnRfbGltaXRCGgoYX21heF9oZWF0X3NldHBvaW50X2xpbWl0QhoKGF9taW5fY29vbF9zZXRwb2ludF9saW1pdEIaChhfbWF4X2Nvb2xfc2V0cG9pbnRfbGltaXRCIAoeX2NvbnRyb2xfc2VxdWVuY2Vfb2Zfb3BlcmF0aW9uQg4KDF9zeXN0ZW1fbW9kZUIaChhfdGhlcm1vc3RhdF9ydW5uaW5nX21vZGUizQIKG1RlbXBlcmF0dXJlU2Vuc29yUHJvcGVydGllcxIzCg5tZWFzdXJlZF92YWx1ZRgBIAEoEUIWiLUYggiStRgNTWVhc3VyZWRWYWx1ZUgAiAEBEjoKEm1pbl9tZWFzdXJlZF92YWx1ZRgCIAEoEUIZiLUYggiStRgQTWluTWVhc3VyZWRWYWx1ZUgBiAEBEjoKEm1heF9tZWFzdXJlZF92YWx1ZRgDIAEoEUIZiLUYggiStRgQTWF4TWVhc3VyZWRWYWx1ZUgCiAEBEioKCXRvbGVyYW5jZRgEIAEoDUISiLUYggiStRgJVG9sZXJhbmNlSAOIAQE6Bpq1GAKCBkIRCg9fbWVhc3VyZWRfdmFsdWVCFQoTX21pbl9tZWFzdXJlZF92YWx1ZUIVChNfbWF4X21lYXN1cmVkX3ZhbHVlQgwKCl90b2xlcmFuY2UiygIKGEh1bWlkaXR5U2Vuc29yUHJvcGVydGllcxIzCg5tZWFzdXJlZF92YWx1ZRgBIAEoDUIWiLUYhQiStRgNTWVhc3VyZWRWYWx1ZUgAiAEBEjoKEm1pbl9tZWFzdXJlZF92YWx1ZRgCIAEoDUIZiLUYhQiStRgQTWluTWVhc3VyZWRWYWx1ZUgBiAEBEjoKEm1heF9tZWFzdXJlZF92YWx1ZRgDIAEoDUIZiLUYhQiStRgQTWF4TWVhc3VyZWRWYWx1ZUgCiAEBEioKCXRvbGVyYW5jZRgEIAEoDUISiLUYhQiStRgJVG9sZXJhbmNlSAOIAQE6Bpq1GAKHBkIRCg9fbWVhc3VyZWRfdmFsdWVCFQoTX21pbl9tZWFzdXJlZF92YWx1ZUIVChNfbWF4X21lYXN1cmVkX3ZhbHVlQgwKCl90b2xlcmFuY2UizwQKGU9jY3VwYW5jeVNlbnNvclByb3BlcnRpZXMSKgoJb2NjdXBhbmN5GAEgASgNQhKItRiGCJK1GAlPY2N1cGFuY3lIAIgBARJAChVvY2N1cGFuY3lfc2Vuc29yX3R5cGUYAiABKA1CHIi1GIYIkrUYE09jY3VwYW5jeVNlbnNvclR5cGVIAYgBARJNChxvY2N1cGFuY3lfc2Vuc29yX3R5cGVfYml0bWFwGAMgASgNQiKItRiGCJK1GBlPY2N1cGFuY3lTZW5zb3JUeXBlQml0bWFwSAKIAQESVAogcGlyX29jY3VwaWVkX3RvX3Vub2NjdXBpZWRfZGVsYXkYBCABKA1CJYi1GIYIkrUYHFBJUk9jY3VwaWVkVG9Vbm9jY3VwaWVkRGVsYXlIA4gBARJUCiBwaXJfdW5vY2N1cGllZF90b19vY2N1cGllZF9kZWxheRgFIAEoDUIliLUYhgiStRgcUElSVW5vY2N1cGllZFRvT2NjdXBpZWREZWxheUgEiAEBOgaatRgChwJCDAoKX29jY3VwYW5jeUIYChZfb2NjdXBhbmN5X3NlbnNvcl90eXBlQh8KHV9vY2N1cGFuY3lfc2Vuc29yX3R5cGVfYml0bWFwQiMKIV9waXJfb2NjdXBpZWRfdG9fdW5vY2N1cGllZF9kZWxheUIjCiFfcGlyX3Vub2NjdXBpZWRfdG9fb2NjdXBpZWRfZGVsYXlSFnBpcl9vY2NfdG9fdW5vY2NfZGVsYXlSFnBpcl91bm9jY190b19vY2NfZGVsYXkiXgoXQ29udGFjdFNlbnNvclByb3BlcnRpZXMSLAoLc3RhdGVfdmFsdWUYASABKAhCEoi1GEWStRgKU3RhdGVWYWx1ZUgAiAEBOgWatRgBFUIOCgxfc3RhdGVfdmFsdWUiuQYKGFdpbmRvd0NvdmVyaW5nUHJvcGVydGllcxIpCg1jb3ZlcmluZ190eXBlGAEgASgNQg2ItRiCApK1GARUeXBlSACIAQESWwojY3VycmVudF9wb3NpdGlvbl9saWZ0X3BlcmNlbnQxMDB0aHMYAiABKA1CKYi1GIICkrUYIEN1cnJlbnRQb3NpdGlvbkxpZnRQZXJjZW50MTAwdGhzSAGIAQESWwojY3VycmVudF9wb3NpdGlvbl90aWx0X3BlcmNlbnQxMDB0aHMYAyABKA1CKYi1GIICkrUYIEN1cnJlbnRQb3NpdGlvblRpbHRQZXJjZW50MTAwdGhzSAKIAQESWQoidGFyZ2V0X3Bvc2l0aW9uX2xpZnRfcGVyY2VudDEwMHRocxgEIAEoDUIoiLUYggKStRgfVGFyZ2V0UG9zaXRpb25MaWZ0UGVyY2VudDEwMHRoc0gDiAEBElkKInRhcmdldF9wb3NpdGlvbl90aWx0X3BlcmNlbnQxMDB0aHMYBSABKA1CKIi1GIICkrUYH1RhcmdldFBvc2l0aW9uVGlsdFBlcmNlbnQxMDB0aHNIBIgBARI7ChJvcGVyYXRpb25hbF9zdGF0dXMYBiABKA1CGoi1GIICkrUYEU9wZXJhdGlvbmFsU3RhdHVzSAWIAQESNgoQZW5kX3Byb2R1Y3RfdHlwZRgHIAEoDUIXiLUYggKStRgORW5kUHJvZHVjdFR5cGVIBogBARIgCgRtb2RlGAggASgNQg2ItRiCApK1GARNb2RlSAeIAQE6Bpq1GAKCBEIQCg5fY292ZXJpbmdfdHlwZUImCiRfY3VycmVudF9wb3NpdGlvbl9saWZ0X3BlcmNlbnQxMDB0aHNCJgokX2N1cnJlbnRfcG9zaXRpb25fdGlsdF9wZXJjZW50MTAwdGhzQiUKI190YXJnZXRfcG9zaXRpb25fbGlmdF9wZXJjZW50MTAwdGhzQiUKI190YXJnZXRfcG9zaXRpb25fdGlsdF9wZXJjZW50MTAwdGhzQhUKE19vcGVyYXRpb25hbF9zdGF0dXNCEwoRX2VuZF9wcm9kdWN0X3R5cGVCBwoFX21vZGUi4gIKEkRvb3JMb2NrUHJvcGVydGllcxIrCgpsb2NrX3N0YXRlGAEgASgNQhKItRiBApK1GAlMb2NrU3RhdGVIAIgBARIpCglsb2NrX3R5cGUYAiABKA1CEYi1GIECkrUYCExvY2tUeXBlSAGIAQESNwoQYWN0dWF0b3JfZW5hYmxlZBgDIAEoCEIYiLUYgQKStRgPQWN0dWF0b3JFbmFibGVkSAKIAQESKwoKZG9vcl9zdGF0ZRgEIAEoDUISiLUYgQKStRgJRG9vclN0YXRlSAOIAQESMwoOb3BlcmF0aW5nX21vZGUYBSABKA1CFoi1GIECkrUYDU9wZXJhdGluZ01vZGVIBIgBAToFmrUYAQpCDQoLX2xvY2tfc3RhdGVCDAoKX2xvY2tfdHlwZUITChFfYWN0dWF0b3JfZW5hYmxlZEINCgtfZG9vcl9zdGF0ZUIRCg9fb3BlcmF0aW5nX21vZGUi4gIKFE9uT2ZmTGlnaHRQcm9wZXJ0aWVzEiIKBm9uX29mZhgBIAEoCEINiLUYBpK1GAVPbk9mZkgAiAEBEj0KFGdsb2JhbF9zY2VuZV9jb250cm9sGAIgASgIQhqItRgGkrUYEkdsb2JhbFNjZW5lQ29udHJvbEgBiAEBEiQKB29uX3RpbWUYAyABKA1CDoi1GAaStRgGT25UaW1lSAKIAQESLwoNb2ZmX3dhaXRfdGltZRgEIAEoDUITiLUYBpK1GAtPZmZXYWl0VGltZUgDiAEBEjIKD3N0YXJ0X3VwX29uX29mZhgFIAEoDUIUiLUYBpK1GAxTdGFydFVwT25PZmZIBIgBAToGmrUYAoACQgkKB19vbl9vZmZCFwoVX2dsb2JhbF9zY2VuZV9jb250cm9sQgoKCF9vbl90aW1lQhAKDl9vZmZfd2FpdF90aW1lQhIKEF9zdGFydF91cF9vbl9vZmYi3QMKF0RpbW1hYmxlTGlnaHRQcm9wZXJ0aWVzEiIKBm9uX29mZhgBIAEoCEINiLUYBpK1GAVPbk9mZkgAiAEBEjAKDWN1cnJlbnRfbGV2ZWwYAiABKA1CFIi1GAiStRgMQ3VycmVudExldmVsSAGIAQESKAoJbWluX2xldmVsGAMgASgNQhCItRgIkrUYCE1pbkxldmVsSAKIAQESKAoJbWF4X2xldmVsGAQgASgNQhCItRgIkrUYCE1heExldmVsSAOIAQESJgoIb25fbGV2ZWwYBSABKA1CD4i1GAiStRgHT25MZXZlbEgEiAEBEkAKFnN0YXJ0X3VwX2N1cnJlbnRfbGV2ZWwYBiABKA1CG4i1GAiStRgTU3RhcnRVcEN1cnJlbnRMZXZlbEgFiAEBEjIKDnJlbWFpbmluZ190aW1lGAcgASgNQhWItRgIkrUYDVJlbWFpbmluZ1RpbWVIBogBAToGmrUYAoECQgkKB19vbl9vZmZCEAoOX2N1cnJlbnRfbGV2ZWxCDAoKX21pbl9sZXZlbEIMCgpfbWF4X2xldmVsQgsKCV9vbl9sZXZlbEIZChdfc3RhcnRfdXBfY3VycmVudF9sZXZlbEIRCg9fcmVtYWluaW5nX3RpbWUiowUKH0NvbG9yVGVtcGVyYXR1cmVMaWdodFByb3BlcnRpZXMSIgoGb25fb2ZmGAEgASgIQg2ItRgGkrUYBU9uT2ZmSACIAQESMAoNY3VycmVudF9sZXZlbBgCIAEoDUIUiLUYCJK1GAxDdXJyZW50TGV2ZWxIAYgBARJGChhjb2xvcl90ZW1wZXJhdHVyZV9taXJlZHMYAyABKA1CH4i1GIAGkrUYFkNvbG9yVGVtcGVyYXR1cmVNaXJlZHNIAogBARJQCh5jb2xvcl90ZW1wX3BoeXNpY2FsX21pbl9taXJlZHMYBCABKA1CI4i1GIAGkrUYGkNvbG9yVGVtcFBoeXNpY2FsTWluTWlyZWRzSAOIAQESUAoeY29sb3JfdGVtcF9waHlzaWNhbF9tYXhfbWlyZWRzGAUgASgNQiOItRiABpK1GBpDb2xvclRlbXBQaHlzaWNhbE1heE1pcmVkc0gEiAEBElUKIHN0YXJ0dXBfY29sb3JfdGVtcGVyYXR1cmVfbWlyZWRzGAYgASgNQiaItRiABpK1GB1TdGFydFVwQ29sb3JUZW1wZXJhdHVyZU1pcmVkc0gFiAEBEisKCmNvbG9yX21vZGUYByABKA1CEoi1GIAGkrUYCUNvbG9yTW9kZUgGiAEBOgaatRgCjAJCCQoHX29uX29mZkIQCg5fY3VycmVudF9sZXZlbEIbChlfY29sb3JfdGVtcGVyYXR1cmVfbWlyZWRzQiEKH19jb2xvcl90ZW1wX3BoeXNpY2FsX21pbl9taXJlZHNCIQofX2NvbG9yX3RlbXBfcGh5c2ljYWxfbWF4X21pcmVkc0IjCiFfc3RhcnR1cF9jb2xvcl90ZW1wZXJhdHVyZV9taXJlZHNCDQoLX2NvbG9yX21vZGUi2AIKFkVuZXJneVNlbnNvclByb3BlcnRpZXMSLwoMYWN0aXZlX3Bvd2VyGAUgASgSQhSItRiQAZK1GAtBY3RpdmVQb3dlckgAiAEBEiYKB3ZvbHRhZ2UYBiABKBJCEIi1GJABkrUYB1ZvbHRhZ2VIAYgBARIzCg5hY3RpdmVfY3VycmVudBgHIAEoEkIWiLUYkAGStRgNQWN0aXZlQ3VycmVudEgCiAEBEioKCWZyZXF1ZW5jeRgIIAEoEkISiLUYkAGStRgJRnJlcXVlbmN5SAOIAQE6Bpq1GAKQCkIPCg1fYWN0aXZlX3Bvd2VyQgoKCF92b2x0YWdlQhEKD19hY3RpdmVfY3VycmVudEIMCgpfZnJlcXVlbmN5SgQIARACSgQIAhADSgQIAxAESgQIBBAFUgtybXNfdm9sdGFnZVILcm1zX2N1cnJlbnRSDGFjX2ZyZXF1ZW5jeSLKAgoYUHJlc3N1cmVTZW5zb3JQcm9wZXJ0aWVzEjMKDm1lYXN1cmVkX3ZhbHVlGAEgASgRQhaItRiDCJK1GA1NZWFzdXJlZFZhbHVlSACIAQESOgoSbWluX21lYXN1cmVkX3ZhbHVlGAIgASgRQhmItRiDCJK1GBBNaW5NZWFzdXJlZFZhbHVlSAGIAQESOgoSbWF4X21lYXN1cmVkX3ZhbHVlGAMgASgRQhmItRiDCJK1GBBNYXhNZWFzdXJlZFZhbHVlSAKIAQESKgoJdG9sZXJhbmNlGAQgASgNQhKItRiDCJK1GAlUb2xlcmFuY2VIA4gBAToGmrUYAoUGQhEKD19tZWFzdXJlZF92YWx1ZUIVChNfbWluX21lYXN1cmVkX3ZhbHVlQhUKE19tYXhfbWVhc3VyZWRfdmFsdWVCDAoKX3RvbGVyYW5jZUICSAFiBnByb3RvMw", [file_kusinta_iot_device_v1_matter_options]);
12
13
 
13
14
  /**
14
15
  * Describes the message kusinta.iot.device.v1.ThermostatProperties.
@@ -15,8 +15,41 @@ export declare const file_kusinta_iot_device_v1_property_update: GenFile;
15
15
  /**
16
16
  * PropertyUpdate carries a single attribute change from connector to gateway,
17
17
  * or from gateway to Flutter app.
18
- * attribute_name uses PascalCase Matter attribute naming (e.g. "OccupiedHeatingSetpoint").
19
- * cluster_id_hex is the Matter cluster ID as a 4-char hex string (e.g. "0201" for Thermostat).
18
+ *
19
+ * Resolution rule (normative)
20
+ *
21
+ * A consumer storing an update into device.v1.Device.properties resolves it in two
22
+ * steps, both by reading options off the descriptor. Neither step involves
23
+ * transforming a name.
24
+ *
25
+ * 1. Pick the properties message: the Device.properties case whose message type
26
+ * declares (matter_device_type) == DeviceDescriptor.matter_device_type_id.
27
+ * 2. Pick the field: the one field of that message whose (matter_cluster_id) equals
28
+ * cluster_id_hex parsed as a hex integer AND whose (matter_attribute) equals
29
+ * attribute_name.
30
+ *
31
+ * Writing the resolved field marks it present, which is how a snapshot distinguishes a
32
+ * reported zero from an attribute the device has never sent. A consumer assembling a
33
+ * snapshot MUST NOT pre-populate fields with defaults — see properties.proto.
34
+ *
35
+ * Both comparisons are exact. attribute_name is byte-for-byte equal to the Matter
36
+ * attribute's spec spelling; it is NOT derived from the proto field name and case- or
37
+ * separator-insensitive matching against field names is not a valid fallback —
38
+ * OccupancySensorProperties and WindowCoveringProperties both have fields that no such
39
+ * transformation reaches. See matter_options.proto.
40
+ *
41
+ * When either step resolves to nothing the update is not storable. A consumer MUST NOT
42
+ * silently drop it: log it at warning with device_id, cluster_id_hex and attribute_name,
43
+ * and count it. A miss means one of three things, all of which need to be visible —
44
+ * the device reports an attribute this schema does not model, the device type is not
45
+ * modelled at all (see device.proto), or a connector is sending a non-Matter name.
46
+ * Advancing Device.last_seen on a miss is correct; the update is still evidence of life.
47
+ *
48
+ * Producers: attribute_name uses the Matter attribute's own PascalCase, acronyms
49
+ * included (e.g. "OccupiedHeatingSetpoint", "PIROccupiedToUnoccupiedDelay").
50
+ * cluster_id_hex is the Matter cluster ID as a 4-char lowercase-or-uppercase hex string
51
+ * with no 0x prefix (e.g. "0201" for Thermostat). Both are required for resolution;
52
+ * an update carrying only one of them cannot be stored.
20
53
  *
21
54
  * @generated from message kusinta.iot.device.v1.PropertyUpdate
22
55
  */
@@ -14,37 +14,42 @@ export declare const file_kusinta_iot_vendor_homematic_v1_homematic: GenFile;
14
14
  * HomeMatic-specific thermostat properties not available in Matter Thermostat cluster.
15
15
  * Add new fields at the next available field number — never reuse a removed number.
16
16
  *
17
+ * Every field is `optional`, for the same reason as device/v1/properties.proto: these are
18
+ * assembled from a PropertyUpdate stream, and zero is a real reading here too — boost_mode
19
+ * false means not boosting, control_mode 0 is an HmIP ControlMode value. Absent means never
20
+ * reported; present means a reading, including zero.
21
+ *
17
22
  * @generated from message kusinta.iot.vendor.homematic.v1.HmThermostatProps
18
23
  */
19
24
  export declare type HmThermostatProps = Message<"kusinta.iot.vendor.homematic.v1.HmThermostatProps"> & {
20
25
  /**
21
- * @generated from field: bool boost_mode = 1;
26
+ * @generated from field: optional bool boost_mode = 1;
22
27
  */
23
- boostMode: boolean;
28
+ boostMode?: boolean | undefined;
24
29
 
25
30
  /**
26
31
  * minutes remaining in boost
27
32
  *
28
- * @generated from field: float boost_time_period = 2;
33
+ * @generated from field: optional float boost_time_period = 2;
29
34
  */
30
- boostTimePeriod: number;
35
+ boostTimePeriod?: number | undefined;
31
36
 
32
37
  /**
33
38
  * HmIP ControlMode enum
34
39
  *
35
- * @generated from field: uint32 control_mode = 3;
40
+ * @generated from field: optional uint32 control_mode = 3;
36
41
  */
37
- controlMode: number;
42
+ controlMode?: number | undefined;
38
43
 
39
44
  /**
40
- * @generated from field: bool frost_protection = 4;
45
+ * @generated from field: optional bool frost_protection = 4;
41
46
  */
42
- frostProtection: boolean;
47
+ frostProtection?: boolean | undefined;
43
48
 
44
49
  /**
45
- * @generated from field: float current_profile_period = 5;
50
+ * @generated from field: optional float current_profile_period = 5;
46
51
  */
47
- currentProfilePeriod: number;
52
+ currentProfilePeriod?: number | undefined;
48
53
  };
49
54
 
50
55
  /**
@@ -8,7 +8,7 @@ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
8
8
  * Describes the file kusinta/iot/vendor/homematic/v1/homematic.proto.
9
9
  */
10
10
  export const file_kusinta_iot_vendor_homematic_v1_homematic = /*@__PURE__*/
11
- fileDesc("Ci9rdXNpbnRhL2lvdC92ZW5kb3IvaG9tZW1hdGljL3YxL2hvbWVtYXRpYy5wcm90bxIfa3VzaW50YS5pb3QudmVuZG9yLmhvbWVtYXRpYy52MSKSAQoRSG1UaGVybW9zdGF0UHJvcHMSEgoKYm9vc3RfbW9kZRgBIAEoCBIZChFib29zdF90aW1lX3BlcmlvZBgCIAEoAhIUCgxjb250cm9sX21vZGUYAyABKA0SGAoQZnJvc3RfcHJvdGVjdGlvbhgEIAEoCBIeChZjdXJyZW50X3Byb2ZpbGVfcGVyaW9kGAUgASgCIq0BChhIb21lbWF0aWNWZW5kb3JFeHRlbnNpb24SGQoRaG9tZW1hdGljX2FkZHJlc3MYASABKAkSFgoOaG9tZW1hdGljX3R5cGUYAiABKAkSSwoNaG1fdGhlcm1vc3RhdBgKIAEoCzIyLmt1c2ludGEuaW90LnZlbmRvci5ob21lbWF0aWMudjEuSG1UaGVybW9zdGF0UHJvcHNIAEIRCg9ob21lbWF0aWNfcHJvcHNCAkgBYgZwcm90bzM");
11
+ fileDesc("Ci9rdXNpbnRhL2lvdC92ZW5kb3IvaG9tZW1hdGljL3YxL2hvbWVtYXRpYy5wcm90bxIfa3VzaW50YS5pb3QudmVuZG9yLmhvbWVtYXRpYy52MSKRAgoRSG1UaGVybW9zdGF0UHJvcHMSFwoKYm9vc3RfbW9kZRgBIAEoCEgAiAEBEh4KEWJvb3N0X3RpbWVfcGVyaW9kGAIgASgCSAGIAQESGQoMY29udHJvbF9tb2RlGAMgASgNSAKIAQESHQoQZnJvc3RfcHJvdGVjdGlvbhgEIAEoCEgDiAEBEiMKFmN1cnJlbnRfcHJvZmlsZV9wZXJpb2QYBSABKAJIBIgBAUINCgtfYm9vc3RfbW9kZUIUChJfYm9vc3RfdGltZV9wZXJpb2RCDwoNX2NvbnRyb2xfbW9kZUITChFfZnJvc3RfcHJvdGVjdGlvbkIZChdfY3VycmVudF9wcm9maWxlX3BlcmlvZCKtAQoYSG9tZW1hdGljVmVuZG9yRXh0ZW5zaW9uEhkKEWhvbWVtYXRpY19hZGRyZXNzGAEgASgJEhYKDmhvbWVtYXRpY190eXBlGAIgASgJEksKDWhtX3RoZXJtb3N0YXQYCiABKAsyMi5rdXNpbnRhLmlvdC52ZW5kb3IuaG9tZW1hdGljLnYxLkhtVGhlcm1vc3RhdFByb3BzSABCEQoPaG9tZW1hdGljX3Byb3BzQgJIAWIGcHJvdG8z");
12
12
 
13
13
  /**
14
14
  * Describes the message kusinta.iot.vendor.homematic.v1.HmThermostatProps.