tigertag 1.0.5 → 1.0.6

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/CHANGELOG.md CHANGED
@@ -3,6 +3,33 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
+ ## [1.0.6] — 2026-05-22
7
+
8
+ ### Fixed
9
+ - `toRawDict()` — `color_r2/g2/b2` and `color_r3/g3/b3` are forced to `0` when
10
+ `num_colors < 2/3`. Consumers always receive clean, zero-padded values for inactive
11
+ color slots; EEPROM garbage from the chip can never leak through to callers of
12
+ `toRawDict()`.
13
+ - Playground `SDK Input` — `color2R/G/B` and `color3R/G/B` are omitted from the
14
+ `TigerTag.create()` call when the aspect indicates fewer than 2 or 3 active colors.
15
+ The SDK's natural default of `0` handles the zeroing; no spurious color bytes are
16
+ passed.
17
+ - `_baseUnitFields()` — unrecognised `id_unit` values now return
18
+ `{ measure_gr: 0, measure_available_gr: 0 }` instead of `{}`. Consumers always receive a
19
+ defined, zero-safe value; chips with corrupt or unknown units no longer propagate garbage
20
+ weight values.
21
+
22
+ ### Added
23
+ - `create()` now validates required fields and throws a descriptive `Error` listing every
24
+ missing field: `idMaterial`, `idAspect1`, `idType`, `idBrand`, `color1R`, `color1G`,
25
+ `color1B`, `color1A`, `measure`, `idUnit`. Validation checks **presence only** — any value
26
+ including `0` is accepted once the field is explicitly provided.
27
+ - `toRawDict()` exposes two new fields derived from the aspect DB:
28
+ - `num_colors` — number of active color slots (1 for Basic/Silk/etc., 2 for Bicolor, 3 for
29
+ Tricolor/Rainbow). Aspect 2 is checked first; falls back to Aspect 1.
30
+ - `color_list` — `string[]` of `#RRGGBB` hex strings, one per active slot only. Consumers
31
+ no longer need to filter inactive slots themselves.
32
+
6
33
  ## [1.0.5] — 2026-05-22
7
34
 
8
35
  ### Added
package/README.md CHANGED
@@ -268,6 +268,9 @@ tag.toDict(db) // → object JSON-serializable, all la
268
268
  // .measure includes measure_gr/ml/mm/mm2 + measure_available_*
269
269
  tag.toRawDict() // → object raw protocol fields, no resolution
270
270
  // includes measure_gr/ml/mm/mm2 + measure_available_* (base-unit)
271
+ // color_r2/g2/b2 and color_r3/g3/b3 are zeroed for inactive slots
272
+ // num_colors — active color slot count from aspect DB (1/2/3)
273
+ // color_list — string[] of #RRGGBB for active slots only
271
274
  tag.toBytes(includeSignature = false) // → Buffer re-serialize to chip bytes
272
275
  tag.validate() // → string[] sanity check — list of warnings
273
276
  tag.verify(db) // → SignatureResult
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tigertag",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "JavaScript SDK for TigerTag RFID material identification",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/tag.js CHANGED
@@ -424,17 +424,17 @@ class TigerTag {
424
424
  static create({
425
425
  productId = MAKER_PRODUCT_ID,
426
426
  uid = null,
427
- idMaterial = 0,
428
- idAspect1 = 0,
427
+ idMaterial = undefined, // required
428
+ idAspect1 = undefined, // required
429
429
  idAspect2 = 0,
430
- idType = 0,
430
+ idType = undefined, // required
431
431
  idDiameter = 0,
432
- idBrand = 0,
433
- color1R = 0, color1G = 0, color1B = 0, color1A = 255,
432
+ idBrand = undefined, // required
433
+ color1R = undefined, color1G = undefined, color1B = undefined, color1A = undefined, // required
434
434
  color2R = 0, color2G = 0, color2B = 0,
435
435
  color3R = 0, color3G = 0, color3B = 0,
436
- measure = 0,
437
- idUnit = 0,
436
+ measure = undefined, // required
437
+ idUnit = undefined, // required
438
438
  nozzleTempMin = 0,
439
439
  nozzleTempMax = 0,
440
440
  dryTemp = 0,
@@ -455,6 +455,24 @@ class TigerTag {
455
455
  productId = MAKER_PRODUCT_ID;
456
456
  }
457
457
 
458
+ // ── Required field validation ────────────────────────────────────────────
459
+ // Check presence only — any value (including 0) is accepted once provided.
460
+ const _missing = [];
461
+ if (idMaterial === undefined) _missing.push('idMaterial');
462
+ if (idAspect1 === undefined) _missing.push('idAspect1');
463
+ if (idType === undefined) _missing.push('idType');
464
+ if (idBrand === undefined) _missing.push('idBrand');
465
+ if (measure === undefined) _missing.push('measure');
466
+ if (idUnit === undefined) _missing.push('idUnit');
467
+ if (color1R === undefined) _missing.push('color1R');
468
+ if (color1G === undefined) _missing.push('color1G');
469
+ if (color1B === undefined) _missing.push('color1B');
470
+ if (color1A === undefined) _missing.push('color1A');
471
+ if (_missing.length > 0) {
472
+ throw new Error(
473
+ `TigerTag.create() — missing required field(s): ${_missing.join(', ')}`
474
+ );
475
+ }
458
476
  if (timestamp == null) {
459
477
  timestamp = Math.max(0, Math.floor((Date.now() - _TIGERTAG_EPOCH_MS) / 1000));
460
478
  }
@@ -1007,7 +1025,9 @@ class TigerTag {
1007
1025
  };
1008
1026
  }
1009
1027
 
1010
- return {};
1028
+ // Unknown unit — no conversion available; return zero base-unit fields so
1029
+ // consumers always get a defined, safe value instead of undefined/garbage.
1030
+ return { measure_gr: 0, measure_available_gr: 0 };
1011
1031
  }
1012
1032
 
1013
1033
  /**
@@ -1016,6 +1036,14 @@ class TigerTag {
1016
1036
  * @returns {object}
1017
1037
  */
1018
1038
  toRawDict() {
1039
+ // Active color count: aspect2 takes priority for multi-color modes
1040
+ // (Bicolor → 2, Tricolor/Rainbow → 3). Falls back to aspect1 (Basic → 1).
1041
+ const _db = this.db;
1042
+ const _a2cc = (_db.aspect(this.idAspect2) || {}).color_count || 0;
1043
+ const _a1cc = (_db.aspect(this.idAspect1) || {}).color_count || 1;
1044
+ const numColors = _a2cc > 0 ? _a2cc : _a1cc;
1045
+ const colorList = [this.color1Hex, this.color2Hex, this.color3Hex].slice(0, numColors);
1046
+
1019
1047
  return {
1020
1048
  id_tigertag: this.idTigertag,
1021
1049
  id_product: this.idProduct,
@@ -1038,16 +1066,18 @@ class TigerTag {
1038
1066
  bed_min: this.bedTempMin,
1039
1067
  bed_max: this.bedTempMax,
1040
1068
  timestamp: this.timestamp,
1041
- color_r2: this.color2R,
1042
- color_g2: this.color2G,
1043
- color_b2: this.color2B,
1044
- color_r3: this.color3R,
1045
- color_g3: this.color3G,
1046
- color_b3: this.color3B,
1069
+ color_r2: numColors >= 2 ? this.color2R : 0,
1070
+ color_g2: numColors >= 2 ? this.color2G : 0,
1071
+ color_b2: numColors >= 2 ? this.color2B : 0,
1072
+ color_r3: numColors >= 3 ? this.color3R : 0,
1073
+ color_g3: numColors >= 3 ? this.color3G : 0,
1074
+ color_b3: numColors >= 3 ? this.color3B : 0,
1047
1075
  td_raw: this.tdRaw,
1048
1076
  message: this.customMessage,
1049
1077
  measure_available: this.measureAvailable,
1050
1078
  ...TigerTag._baseUnitFields(this.measure, this.measureAvailable, this.idUnit),
1079
+ num_colors: numColors,
1080
+ color_list: colorList,
1051
1081
  uid: this.uidHex,
1052
1082
  product_page_url: this.productPageUrl,
1053
1083
  api_url: this.apiUrl,