@camstack/types 1.2.416 → 1.2.417

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/addon.js +1 -1
  2. package/dist/addon.mjs +1 -1
  3. package/dist/capabilities/air-quality-sensor.cap.d.ts +2 -8
  4. package/dist/capabilities/ambient-light-sensor.cap.d.ts +3 -14
  5. package/dist/capabilities/battery.cap.d.ts +9 -2
  6. package/dist/capabilities/binary.cap.d.ts +0 -5
  7. package/dist/capabilities/capability-definition.d.ts +6 -6
  8. package/dist/capabilities/consumables.cap.d.ts +30 -41
  9. package/dist/capabilities/control.cap.d.ts +3 -25
  10. package/dist/capabilities/core-blocks.cap.d.ts +1 -0
  11. package/dist/capabilities/customize-catalog.d.ts +0 -8
  12. package/dist/capabilities/customize-spec.d.ts +2 -3
  13. package/dist/capabilities/device-manager.cap.d.ts +79 -0
  14. package/dist/capabilities/device-provider.cap.d.ts +36 -0
  15. package/dist/capabilities/enum-sensor.cap.d.ts +5 -17
  16. package/dist/capabilities/humidity-sensor.cap.d.ts +3 -14
  17. package/dist/capabilities/index.d.ts +1 -1
  18. package/dist/capabilities/motion.cap.d.ts +1 -1
  19. package/dist/capabilities/numeric-sensor.cap.d.ts +8 -16
  20. package/dist/capabilities/pet-feeder.cap.d.ts +1 -1
  21. package/dist/capabilities/power-meter.cap.d.ts +0 -11
  22. package/dist/capabilities/pressure-sensor.cap.d.ts +3 -9
  23. package/dist/capabilities/running-state.cap.d.ts +1 -2
  24. package/dist/capabilities/runtime-field-unit.d.ts +1 -0
  25. package/dist/capabilities/runtime-field-units.d.ts +8 -0
  26. package/dist/capabilities/switch.cap.d.ts +0 -5
  27. package/dist/capabilities/temperature-sensor.cap.d.ts +5 -20
  28. package/dist/capabilities/weather.cap.d.ts +4 -13
  29. package/dist/client.d.ts +2 -1
  30. package/dist/client.js +54 -5
  31. package/dist/client.mjs +52 -6
  32. package/dist/composition/composition-report.d.ts +8 -3
  33. package/dist/composition/state-fields.d.ts +1 -1
  34. package/dist/composition/validate-composition.d.ts +3 -2
  35. package/dist/device/cap-vocabulary/types.d.ts +2 -2
  36. package/dist/device/schema-fields.d.ts +3 -0
  37. package/dist/device/source-info.d.ts +12 -6
  38. package/dist/generated/addon-cap-facts.d.ts +1 -1
  39. package/dist/generated/customize-catalog.d.ts +11 -87
  40. package/dist/generated/history-catalog.d.ts +1 -1
  41. package/dist/index.d.ts +3 -1
  42. package/dist/index.js +755 -490
  43. package/dist/index.mjs +738 -490
  44. package/dist/{sleep-BErAxhul.mjs → sleep-CARd6wZF.mjs} +161 -128
  45. package/dist/{sleep-BPQ2ZyaI.js → sleep-gtskVoMw.js} +214 -127
  46. package/dist/units/convert.d.ts +5 -0
  47. package/dist/units/format-reading.d.ts +15 -0
  48. package/dist/units/index.d.ts +8 -1
  49. package/dist/units/ingest-reading.d.ts +21 -0
  50. package/dist/units/quantity.d.ts +47 -0
  51. package/dist/units/threshold.d.ts +6 -0
  52. package/dist/units/unit-table.d.ts +2 -228
  53. package/package.json +1 -1
  54. package/dist/capabilities/advanced-parameters.d.ts +0 -17
@@ -5112,6 +5112,134 @@ function makeInMemoryRecords(owner = "spec", options = {}) {
5112
5112
  }
5113
5113
  };
5114
5114
  }
5115
+ var READING_QUANTITIES = [
5116
+ "temperature",
5117
+ "pressure",
5118
+ "speed",
5119
+ "precipitation",
5120
+ "precipitation-rate",
5121
+ "length",
5122
+ "area",
5123
+ "illuminance",
5124
+ "irradiance",
5125
+ "power",
5126
+ "energy",
5127
+ "voltage",
5128
+ "current",
5129
+ "apparent-power",
5130
+ "humidity",
5131
+ "percentage",
5132
+ "concentration-volume",
5133
+ "concentration-mass",
5134
+ "concentration-ppb",
5135
+ "volume",
5136
+ "duration",
5137
+ "duration-ms",
5138
+ "information",
5139
+ "sound-level",
5140
+ "signal-level",
5141
+ "colour-temperature",
5142
+ "angle",
5143
+ "bitrate",
5144
+ "rate",
5145
+ "mass",
5146
+ "index",
5147
+ "ratio",
5148
+ "count",
5149
+ "none",
5150
+ "device"
5151
+ ];
5152
+ var ReadingQuantitySchema = zod.z.enum(READING_QUANTITIES);
5153
+ var QUANTITY_SET = new Set(READING_QUANTITIES);
5154
+ function isReadingQuantity(value) {
5155
+ return typeof value === "string" && QUANTITY_SET.has(value);
5156
+ }
5157
+ /**
5158
+ * Stored unit symbol for a quantity. `none` means the number is dimensionless
5159
+ * (or an index / ratio / count). `device` means the cap has no single unit.
5160
+ */
5161
+ var QUANTITY_BASE = {
5162
+ temperature: "°C",
5163
+ pressure: "hPa",
5164
+ speed: "m/s",
5165
+ precipitation: "mm",
5166
+ "precipitation-rate": "mm/h",
5167
+ length: "m",
5168
+ area: "m²",
5169
+ illuminance: "lx",
5170
+ irradiance: "W/m²",
5171
+ power: "W",
5172
+ energy: "kWh",
5173
+ voltage: "V",
5174
+ current: "A",
5175
+ "apparent-power": "VA",
5176
+ humidity: "%",
5177
+ percentage: "%",
5178
+ "concentration-volume": "ppm",
5179
+ "concentration-mass": "µg/m³",
5180
+ "concentration-ppb": "ppb",
5181
+ volume: "L",
5182
+ duration: "s",
5183
+ "duration-ms": "ms",
5184
+ information: "B",
5185
+ "sound-level": "dBFS",
5186
+ "signal-level": "dBm",
5187
+ "colour-temperature": "mired",
5188
+ angle: "°",
5189
+ bitrate: "kbps",
5190
+ rate: "fps",
5191
+ mass: "kg",
5192
+ index: "none",
5193
+ ratio: "none",
5194
+ count: "none",
5195
+ none: "none",
5196
+ device: "device"
5197
+ };
5198
+ /** The stored unit, or `undefined` when the quantity has no unit symbol. */
5199
+ function baseUnitOf(quantity) {
5200
+ const symbol = QUANTITY_BASE[quantity];
5201
+ if (symbol === "none" || symbol === "device") return void 0;
5202
+ return symbol;
5203
+ }
5204
+ /**
5205
+ * History catalog label for a quantity. Index and ratio keep the labels the
5206
+ * series already used (`count`, `ratio`). A polymorphic reading has no
5207
+ * single label.
5208
+ */
5209
+ function historyUnitFor(quantity) {
5210
+ if (quantity === "index" || quantity === "count") return "count";
5211
+ if (quantity === "ratio") return "ratio";
5212
+ return baseUnitOf(quantity);
5213
+ }
5214
+ function readingMeta(quantity, extras) {
5215
+ return {
5216
+ quantity,
5217
+ ...extras?.precision !== void 0 ? { precision: extras.precision } : {},
5218
+ ...extras?.label !== void 0 ? { label: extras.label } : {}
5219
+ };
5220
+ }
5221
+ /** Imperial display symbol when it differs from the stored base. */
5222
+ var IMPERIAL_DISPLAY = {
5223
+ temperature: "°F",
5224
+ pressure: "inHg",
5225
+ speed: "mph",
5226
+ precipitation: "in",
5227
+ "precipitation-rate": "in/h",
5228
+ length: "ft",
5229
+ volume: "gal"
5230
+ };
5231
+ var DISPLAY_PREFERENCES = ["metric", "imperial"];
5232
+ var DEFAULT_DISPLAY_PREFERENCE = "metric";
5233
+ /** Display symbol for a preference. Duration and information are scaled by the formatter. */
5234
+ function displayUnitFor(quantity, preference) {
5235
+ const base = baseUnitOf(quantity);
5236
+ if (base === void 0) return void 0;
5237
+ if (preference === "imperial") {
5238
+ const imperial = IMPERIAL_DISPLAY[quantity];
5239
+ if (imperial !== void 0) return imperial;
5240
+ }
5241
+ return base;
5242
+ }
5115
5243
  //#endregion
5116
5244
  //#region src/capabilities/schemas/streaming-shared.ts
5117
5245
  /** Shared Zod schemas used across streaming capabilities. */
@@ -5147,8 +5275,8 @@ var CamStreamKindSchema = zod.z.enum([
5147
5275
  "derived"
5148
5276
  ]);
5149
5277
  var CamStreamResolutionSchema = zod.z.object({
5150
- width: zod.z.number().int().positive(),
5151
- height: zod.z.number().int().positive()
5278
+ width: zod.z.number().int().positive().meta(readingMeta("none")),
5279
+ height: zod.z.number().int().positive().meta(readingMeta("none"))
5152
5280
  });
5153
5281
  var CameraStreamSchema = zod.z.object({
5154
5282
  /** Stable, provider-assigned id unique within the (deviceId) scope. */
@@ -6003,7 +6131,7 @@ zod.z.object({
6003
6131
  });
6004
6132
  /** The default applied to a `runtimeState` cap that declares no `durability`. */
6005
6133
  var DEFAULT_RUNTIME_STATE_DURABILITY = "session";
6006
- /** Display label per {@link HistoryUnit} (only `'ug/m3'` differs from its id). */
6134
+ /** Display label per {@link HistoryUnit}. */
6007
6135
  var HISTORY_UNIT_LABELS = {
6008
6136
  "%": "%",
6009
6137
  dBFS: "dBFS",
@@ -6017,7 +6145,7 @@ var HISTORY_UNIT_LABELS = {
6017
6145
  lx: "lx",
6018
6146
  ppm: "ppm",
6019
6147
  ppb: "ppb",
6020
- "ug/m3": "µg/m³",
6148
+ "µg/m³": "µg/m³",
6021
6149
  hPa: "hPa",
6022
6150
  count: "count",
6023
6151
  ratio: "ratio",
@@ -6026,7 +6154,8 @@ var HISTORY_UNIT_LABELS = {
6026
6154
  days: "days",
6027
6155
  bytes: "bytes",
6028
6156
  kbps: "kbps",
6029
- fps: "fps"
6157
+ fps: "fps",
6158
+ "m/s": "m/s"
6030
6159
  };
6031
6160
  /** The catalog field path of an item field: `<itemsPath>[].<field>` (`items[].level`). */
6032
6161
  function historyItemFieldPath(itemsPath, field) {
@@ -6714,14 +6843,6 @@ var CAP_STATE_LEAVES = Object.freeze({
6714
6843
  {
6715
6844
  "path": "aqi",
6716
6845
  "valueType": "number"
6717
- },
6718
- {
6719
- "path": "unit",
6720
- "valueType": "string"
6721
- },
6722
- {
6723
- "path": "precision",
6724
- "valueType": "number"
6725
6846
  }
6726
6847
  ],
6727
6848
  "alarm-panel": [
@@ -6757,20 +6878,10 @@ var CAP_STATE_LEAVES = Object.freeze({
6757
6878
  "valueType": "boolean"
6758
6879
  }
6759
6880
  ],
6760
- "ambient-light-sensor": [
6761
- {
6762
- "path": "lux",
6763
- "valueType": "number"
6764
- },
6765
- {
6766
- "path": "unit",
6767
- "valueType": "string"
6768
- },
6769
- {
6770
- "path": "precision",
6771
- "valueType": "number"
6772
- }
6773
- ],
6881
+ "ambient-light-sensor": [{
6882
+ "path": "lux",
6883
+ "valueType": "number"
6884
+ }],
6774
6885
  "audio-metrics": [
6775
6886
  {
6776
6887
  "path": "ts",
@@ -6850,6 +6961,10 @@ var CAP_STATE_LEAVES = Object.freeze({
6850
6961
  "path": "lastUpdated",
6851
6962
  "valueType": "number"
6852
6963
  },
6964
+ {
6965
+ "path": "volts",
6966
+ "valueType": "number"
6967
+ },
6853
6968
  {
6854
6969
  "path": "lastContactAt",
6855
6970
  "valueType": "number"
@@ -7092,10 +7207,6 @@ var CAP_STATE_LEAVES = Object.freeze({
7092
7207
  "datetime"
7093
7208
  ]
7094
7209
  },
7095
- {
7096
- "path": "unit",
7097
- "valueType": "string"
7098
- },
7099
7210
  {
7100
7211
  "path": "min",
7101
7212
  "valueType": "number"
@@ -7107,19 +7218,6 @@ var CAP_STATE_LEAVES = Object.freeze({
7107
7218
  {
7108
7219
  "path": "step",
7109
7220
  "valueType": "number"
7110
- },
7111
- {
7112
- "path": "precision",
7113
- "valueType": "number"
7114
- },
7115
- {
7116
- "path": "format",
7117
- "valueType": "enum",
7118
- "enumValues": [
7119
- "date",
7120
- "time",
7121
- "datetime"
7122
- ]
7123
7221
  }
7124
7222
  ],
7125
7223
  "cover": [
@@ -7360,13 +7458,8 @@ var CAP_STATE_LEAVES = Object.freeze({
7360
7458
  "path": "value",
7361
7459
  "valueType": "string"
7362
7460
  }, {
7363
- "path": "format",
7364
- "valueType": "enum",
7365
- "enumValues": [
7366
- "date",
7367
- "time",
7368
- "datetime"
7369
- ]
7461
+ "path": "timestamp",
7462
+ "valueType": "boolean"
7370
7463
  }],
7371
7464
  "event-emitter": [
7372
7465
  {
@@ -7473,20 +7566,10 @@ var CAP_STATE_LEAVES = Object.freeze({
7473
7566
  "valueType": "number"
7474
7567
  }
7475
7568
  ],
7476
- "humidity-sensor": [
7477
- {
7478
- "path": "percent",
7479
- "valueType": "number"
7480
- },
7481
- {
7482
- "path": "unit",
7483
- "valueType": "string"
7484
- },
7485
- {
7486
- "path": "precision",
7487
- "valueType": "number"
7488
- }
7489
- ],
7569
+ "humidity-sensor": [{
7570
+ "path": "percent",
7571
+ "valueType": "number"
7572
+ }],
7490
7573
  "image": [{
7491
7574
  "path": "url",
7492
7575
  "valueType": "string"
@@ -7825,20 +7908,10 @@ var CAP_STATE_LEAVES = Object.freeze({
7825
7908
  "valueType": "boolean"
7826
7909
  }
7827
7910
  ],
7828
- "numeric-sensor": [
7829
- {
7830
- "path": "value",
7831
- "valueType": "number"
7832
- },
7833
- {
7834
- "path": "unit",
7835
- "valueType": "string"
7836
- },
7837
- {
7838
- "path": "precision",
7839
- "valueType": "number"
7840
- }
7841
- ],
7911
+ "numeric-sensor": [{
7912
+ "path": "value",
7913
+ "valueType": "number"
7914
+ }],
7842
7915
  "pet-feeder": [
7843
7916
  {
7844
7917
  "path": "foodLevel",
@@ -7930,14 +8003,6 @@ var CAP_STATE_LEAVES = Object.freeze({
7930
8003
  {
7931
8004
  "path": "powerFactor",
7932
8005
  "valueType": "number"
7933
- },
7934
- {
7935
- "path": "unit",
7936
- "valueType": "string"
7937
- },
7938
- {
7939
- "path": "precision",
7940
- "valueType": "number"
7941
8006
  }
7942
8007
  ],
7943
8008
  "presence": [
@@ -7966,20 +8031,10 @@ var CAP_STATE_LEAVES = Object.freeze({
7966
8031
  "valueType": "number"
7967
8032
  }
7968
8033
  ],
7969
- "pressure-sensor": [
7970
- {
7971
- "path": "hpa",
7972
- "valueType": "number"
7973
- },
7974
- {
7975
- "path": "unit",
7976
- "valueType": "string"
7977
- },
7978
- {
7979
- "path": "precision",
7980
- "valueType": "number"
7981
- }
7982
- ],
8034
+ "pressure-sensor": [{
8035
+ "path": "hpa",
8036
+ "valueType": "number"
8037
+ }],
7983
8038
  "privacy-mask": [{
7984
8039
  "path": "enabled",
7985
8040
  "valueType": "boolean"
@@ -8290,20 +8345,10 @@ var CAP_STATE_LEAVES = Object.freeze({
8290
8345
  "path": "tampered",
8291
8346
  "valueType": "boolean"
8292
8347
  }],
8293
- "temperature-sensor": [
8294
- {
8295
- "path": "celsius",
8296
- "valueType": "number"
8297
- },
8298
- {
8299
- "path": "unit",
8300
- "valueType": "string"
8301
- },
8302
- {
8303
- "path": "precision",
8304
- "valueType": "number"
8305
- }
8306
- ],
8348
+ "temperature-sensor": [{
8349
+ "path": "celsius",
8350
+ "valueType": "number"
8351
+ }],
8307
8352
  "update": [
8308
8353
  {
8309
8354
  "path": "currentVersion",
@@ -8414,10 +8459,6 @@ var CAP_STATE_LEAVES = Object.freeze({
8414
8459
  "path": "temperature",
8415
8460
  "valueType": "number"
8416
8461
  },
8417
- {
8418
- "path": "temperatureUnit",
8419
- "valueType": "string"
8420
- },
8421
8462
  {
8422
8463
  "path": "humidity",
8423
8464
  "valueType": "number"
@@ -8426,18 +8467,10 @@ var CAP_STATE_LEAVES = Object.freeze({
8426
8467
  "path": "pressure",
8427
8468
  "valueType": "number"
8428
8469
  },
8429
- {
8430
- "path": "pressureUnit",
8431
- "valueType": "string"
8432
- },
8433
8470
  {
8434
8471
  "path": "windSpeed",
8435
8472
  "valueType": "number"
8436
8473
  },
8437
- {
8438
- "path": "windSpeedUnit",
8439
- "valueType": "string"
8440
- },
8441
8474
  {
8442
8475
  "path": "windBearing",
8443
8476
  "valueType": "number"
@@ -10285,6 +10318,12 @@ Object.defineProperty(exports, "DATAPLANE_SECRET_HEADER", {
10285
10318
  return DATAPLANE_SECRET_HEADER;
10286
10319
  }
10287
10320
  });
10321
+ Object.defineProperty(exports, "DEFAULT_DISPLAY_PREFERENCE", {
10322
+ enumerable: true,
10323
+ get: function() {
10324
+ return DEFAULT_DISPLAY_PREFERENCE;
10325
+ }
10326
+ });
10288
10327
  Object.defineProperty(exports, "DEFAULT_RUNTIME_STATE_DURABILITY", {
10289
10328
  enumerable: true,
10290
10329
  get: function() {
@@ -10321,6 +10360,12 @@ Object.defineProperty(exports, "DEVICE_STATUS_METHOD", {
10321
10360
  return DEVICE_STATUS_METHOD;
10322
10361
  }
10323
10362
  });
10363
+ Object.defineProperty(exports, "DISPLAY_PREFERENCES", {
10364
+ enumerable: true,
10365
+ get: function() {
10366
+ return DISPLAY_PREFERENCES;
10367
+ }
10368
+ });
10324
10369
  Object.defineProperty(exports, "DeclarationRefusedError", {
10325
10370
  enumerable: true,
10326
10371
  get: function() {
@@ -10489,6 +10534,12 @@ Object.defineProperty(exports, "ProfileSlotStatusSchema", {
10489
10534
  return ProfileSlotStatusSchema;
10490
10535
  }
10491
10536
  });
10537
+ Object.defineProperty(exports, "QUANTITY_BASE", {
10538
+ enumerable: true,
10539
+ get: function() {
10540
+ return QUANTITY_BASE;
10541
+ }
10542
+ });
10492
10543
  Object.defineProperty(exports, "RECORDS_ERROR_CODES", {
10493
10544
  enumerable: true,
10494
10545
  get: function() {
@@ -10621,6 +10672,12 @@ Object.defineProperty(exports, "ReadinessTimeoutError", {
10621
10672
  return ReadinessTimeoutError;
10622
10673
  }
10623
10674
  });
10675
+ Object.defineProperty(exports, "ReadingQuantitySchema", {
10676
+ enumerable: true,
10677
+ get: function() {
10678
+ return ReadingQuantitySchema;
10679
+ }
10680
+ });
10624
10681
  Object.defineProperty(exports, "RecordFieldPathSchema", {
10625
10682
  enumerable: true,
10626
10683
  get: function() {
@@ -10843,6 +10900,12 @@ Object.defineProperty(exports, "audioChunkBytesPerSample", {
10843
10900
  return audioChunkBytesPerSample;
10844
10901
  }
10845
10902
  });
10903
+ Object.defineProperty(exports, "baseUnitOf", {
10904
+ enumerable: true,
10905
+ get: function() {
10906
+ return baseUnitOf;
10907
+ }
10908
+ });
10846
10909
  Object.defineProperty(exports, "buildSecretRef", {
10847
10910
  enumerable: true,
10848
10911
  get: function() {
@@ -11023,6 +11086,12 @@ Object.defineProperty(exports, "deviceOpsCapability", {
11023
11086
  return deviceOpsCapability;
11024
11087
  }
11025
11088
  });
11089
+ Object.defineProperty(exports, "displayUnitFor", {
11090
+ enumerable: true,
11091
+ get: function() {
11092
+ return displayUnitFor;
11093
+ }
11094
+ });
11026
11095
  Object.defineProperty(exports, "emitDownForOwnedCaps", {
11027
11096
  enumerable: true,
11028
11097
  get: function() {
@@ -11089,6 +11158,12 @@ Object.defineProperty(exports, "historyItemFieldPath", {
11089
11158
  return historyItemFieldPath;
11090
11159
  }
11091
11160
  });
11161
+ Object.defineProperty(exports, "historyUnitFor", {
11162
+ enumerable: true,
11163
+ get: function() {
11164
+ return historyUnitFor;
11165
+ }
11166
+ });
11092
11167
  Object.defineProperty(exports, "hydrateSchema", {
11093
11168
  enumerable: true,
11094
11169
  get: function() {
@@ -11131,6 +11206,12 @@ Object.defineProperty(exports, "isKeychainStoredField", {
11131
11206
  return isKeychainStoredField;
11132
11207
  }
11133
11208
  });
11209
+ Object.defineProperty(exports, "isReadingQuantity", {
11210
+ enumerable: true,
11211
+ get: function() {
11212
+ return isReadingQuantity;
11213
+ }
11214
+ });
11134
11215
  Object.defineProperty(exports, "isSecretClear", {
11135
11216
  enumerable: true,
11136
11217
  get: function() {
@@ -11329,6 +11410,12 @@ Object.defineProperty(exports, "readinessKey", {
11329
11410
  return readinessKey;
11330
11411
  }
11331
11412
  });
11413
+ Object.defineProperty(exports, "readingMeta", {
11414
+ enumerable: true,
11415
+ get: function() {
11416
+ return readingMeta;
11417
+ }
11418
+ });
11332
11419
  Object.defineProperty(exports, "recordArrayItemPath", {
11333
11420
  enumerable: true,
11334
11421
  get: function() {
@@ -46,4 +46,9 @@ export declare function canConvertUnit(from: string, to: string): boolean;
46
46
  * Every known unit spelling in a dimension (table insertion order — canonical
47
47
  * unit first). Powers the UI's same-dimension unit picker.
48
48
  */
49
+ /**
50
+ * Convert a difference, not a reading. Affine units (°F) shift an absolute
51
+ * value by their offset; a step of 1°F is 5/9°C, so the offset is cancelled.
52
+ */
53
+ export declare function tryConvertDelta(value: number, from: string, to: string): number | undefined;
49
54
  export declare function unitsForDimension(dimension: UnitDimension): readonly string[];
@@ -0,0 +1,15 @@
1
+ import { type DisplayPreference, type ReadingQuantity } from './quantity.js';
2
+ export interface FormatReadingInput {
3
+ readonly value: number;
4
+ readonly quantity: ReadingQuantity;
5
+ readonly preference?: DisplayPreference;
6
+ readonly precision?: number;
7
+ /** Concrete quantity when `quantity` is `device`. */
8
+ readonly deviceQuantity?: ReadingQuantity;
9
+ }
10
+ export interface FormattedReading {
11
+ readonly text: string;
12
+ readonly unit: string;
13
+ readonly value: number;
14
+ }
15
+ export declare function formatReading(input: FormatReadingInput): FormattedReading;
@@ -4,5 +4,12 @@
4
4
  */
5
5
  export { UNIT_TABLE } from './unit-table.js';
6
6
  export type { UnitDimension, UnitSpec, KnownUnit } from './unit-table.js';
7
- export { UnitConversionError, unitDimension, convertUnit, tryConvertUnit, canConvertUnit, unitsForDimension, } from './convert.js';
7
+ export { UnitConversionError, unitDimension, convertUnit, tryConvertUnit, tryConvertDelta, canConvertUnit, unitsForDimension, } from './convert.js';
8
8
  export type { UnitConversionReason } from './convert.js';
9
+ export { DEFAULT_DISPLAY_PREFERENCE, DISPLAY_PREFERENCES, QUANTITY_BASE, ReadingQuantitySchema, baseUnitOf, displayUnitFor, historyUnitFor, isReadingQuantity, readingMeta, } from './quantity.js';
10
+ export type { DisplayPreference, ReadingMeta, ReadingQuantity } from './quantity.js';
11
+ export { thresholdToBase, thresholdToDisplay } from './threshold.js';
12
+ export { formatReading } from './format-reading.js';
13
+ export type { FormatReadingInput, FormattedReading } from './format-reading.js';
14
+ export { ingestReading, quantityFromUnit } from './ingest-reading.js';
15
+ export type { IngestReadingInput, IngestReadingResult, IngestRefusal } from './ingest-reading.js';
@@ -0,0 +1,21 @@
1
+ import { type ReadingQuantity } from './quantity.js';
2
+ export type IngestRefusal = 'non-finite' | 'unknown-unit' | 'cross-dimension';
3
+ export interface IngestReadingInput {
4
+ readonly value: number;
5
+ readonly rawUnit: string | undefined;
6
+ readonly quantity: ReadingQuantity;
7
+ }
8
+ export type IngestReadingResult = {
9
+ readonly ok: true;
10
+ readonly value: number;
11
+ } | {
12
+ readonly ok: false;
13
+ readonly reason: IngestRefusal;
14
+ };
15
+ /**
16
+ * Quantity implied by a unit symbol. `ppb` and `ms` are the two symbols
17
+ * whose stored base is not the dimension's canonical unit. `mm` is length;
18
+ * precipitation is chosen by the caller (a device class), not by the symbol.
19
+ */
20
+ export declare function quantityFromUnit(rawUnit: string | undefined): ReadingQuantity | undefined;
21
+ export declare function ingestReading(input: IngestReadingInput): IngestReadingResult;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * A numeric reading is stored in the base unit of its quantity (D944 §4).
3
+ * The base symbol lives here — never as a sibling field on the device slice.
4
+ *
5
+ * `energy` is stored in kWh even though `UNIT_TABLE`'s linear origin is Wh:
6
+ * history, Matter and the field name already count kilowatt-hours.
7
+ * `concentration-ppb` is separate so VOC parts-per-billion are not divided
8
+ * by 1000 into ppm. `device` is a polymorphic reading (numeric-sensor,
9
+ * numeric control): the quantity is chosen once, on the device, at adopt.
10
+ */
11
+ import { z } from 'zod';
12
+ declare const READING_QUANTITY_VALUES: readonly ['temperature', 'pressure', 'speed', 'precipitation', 'precipitation-rate', 'length', 'area', 'illuminance', 'irradiance', 'power', 'energy', 'voltage', 'current', 'apparent-power', 'humidity', 'percentage', 'concentration-volume', 'concentration-mass', 'concentration-ppb', 'volume', 'duration', 'duration-ms', 'information', 'sound-level', 'signal-level', 'colour-temperature', 'angle', 'bitrate', 'rate', 'mass', 'index', 'ratio', 'count', 'none', 'device'];
13
+ export declare const READING_QUANTITIES: typeof READING_QUANTITY_VALUES;
14
+ export type ReadingQuantity = (typeof READING_QUANTITIES)[number];
15
+ export declare const ReadingQuantitySchema: z.ZodType<ReadingQuantity>;
16
+ export declare function isReadingQuantity(value: unknown): value is ReadingQuantity;
17
+ /**
18
+ * Stored unit symbol for a quantity. `none` means the number is dimensionless
19
+ * (or an index / ratio / count). `device` means the cap has no single unit.
20
+ */
21
+ export declare const QUANTITY_BASE: Readonly<Record<ReadingQuantity, string>>;
22
+ /** The stored unit, or `undefined` when the quantity has no unit symbol. */
23
+ export declare function baseUnitOf(quantity: ReadingQuantity): string | undefined;
24
+ /**
25
+ * History catalog label for a quantity. Index and ratio keep the labels the
26
+ * series already used (`count`, `ratio`). A polymorphic reading has no
27
+ * single label.
28
+ */
29
+ export declare function historyUnitFor(quantity: ReadingQuantity): string | undefined;
30
+ /** Zod `.meta()` bag for a numeric reading. Precision is a display hint. */
31
+ export type ReadingMeta = {
32
+ readonly [key: string]: unknown;
33
+ readonly quantity: ReadingQuantity;
34
+ readonly precision?: number;
35
+ readonly label?: string;
36
+ };
37
+ export declare function readingMeta(quantity: ReadingQuantity, extras?: {
38
+ readonly precision?: number;
39
+ readonly label?: string;
40
+ }): ReadingMeta;
41
+ declare const DISPLAY_PREFERENCE_VALUES: readonly ['metric', 'imperial'];
42
+ export declare const DISPLAY_PREFERENCES: typeof DISPLAY_PREFERENCE_VALUES;
43
+ export type DisplayPreference = (typeof DISPLAY_PREFERENCES)[number];
44
+ export declare const DEFAULT_DISPLAY_PREFERENCE: DisplayPreference;
45
+ /** Display symbol for a preference. Duration and information are scaled by the formatter. */
46
+ export declare function displayUnitFor(quantity: ReadingQuantity, preference: DisplayPreference): string | undefined;
47
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Move a threshold between the unit the operator sees and the stored base.
3
+ * A failed conversion leaves the number unchanged — the recipe stays serialisable.
4
+ */
5
+ export declare function thresholdToBase(value: number, displayUnit: string, baseUnit: string): number;
6
+ export declare function thresholdToDisplay(value: number, baseUnit: string, displayUnit: string): number;