@zwave-js/cc 10.19.0 → 10.21.0

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 (56) hide show
  1. package/build/cc/BarrierOperatorCC.d.ts +2 -1
  2. package/build/cc/BarrierOperatorCC.d.ts.map +1 -1
  3. package/build/cc/BarrierOperatorCC.js +76 -15
  4. package/build/cc/BarrierOperatorCC.js.map +1 -1
  5. package/build/cc/BasicCC.d.ts +5 -1
  6. package/build/cc/BasicCC.d.ts.map +1 -1
  7. package/build/cc/BasicCC.js +52 -48
  8. package/build/cc/BasicCC.js.map +1 -1
  9. package/build/cc/BinarySwitchCC.d.ts +2 -1
  10. package/build/cc/BinarySwitchCC.d.ts.map +1 -1
  11. package/build/cc/BinarySwitchCC.js +43 -46
  12. package/build/cc/BinarySwitchCC.js.map +1 -1
  13. package/build/cc/ColorSwitchCC.js +3 -3
  14. package/build/cc/ColorSwitchCC.js.map +1 -1
  15. package/build/cc/ConfigurationCC.d.ts +48 -37
  16. package/build/cc/ConfigurationCC.d.ts.map +1 -1
  17. package/build/cc/ConfigurationCC.js +244 -165
  18. package/build/cc/ConfigurationCC.js.map +1 -1
  19. package/build/cc/EnergyProductionCC.d.ts +7 -1
  20. package/build/cc/EnergyProductionCC.d.ts.map +1 -1
  21. package/build/cc/EnergyProductionCC.js +19 -5
  22. package/build/cc/EnergyProductionCC.js.map +1 -1
  23. package/build/cc/IndicatorCC.d.ts +3 -0
  24. package/build/cc/IndicatorCC.d.ts.map +1 -1
  25. package/build/cc/IndicatorCC.js +3 -0
  26. package/build/cc/IndicatorCC.js.map +1 -1
  27. package/build/cc/IrrigationCC.d.ts +7 -0
  28. package/build/cc/IrrigationCC.d.ts.map +1 -1
  29. package/build/cc/IrrigationCC.js +7 -0
  30. package/build/cc/IrrigationCC.js.map +1 -1
  31. package/build/cc/MeterCC.d.ts +6 -0
  32. package/build/cc/MeterCC.d.ts.map +1 -1
  33. package/build/cc/MeterCC.js +6 -0
  34. package/build/cc/MeterCC.js.map +1 -1
  35. package/build/cc/MultilevelSwitchCC.d.ts +13 -1
  36. package/build/cc/MultilevelSwitchCC.d.ts.map +1 -1
  37. package/build/cc/MultilevelSwitchCC.js +83 -76
  38. package/build/cc/MultilevelSwitchCC.js.map +1 -1
  39. package/build/cc/ScheduleEntryLockCC.d.ts +1 -0
  40. package/build/cc/ScheduleEntryLockCC.d.ts.map +1 -1
  41. package/build/cc/ScheduleEntryLockCC.js.map +1 -1
  42. package/build/cc/WindowCoveringCC.d.ts +28 -78
  43. package/build/cc/WindowCoveringCC.d.ts.map +1 -1
  44. package/build/cc/WindowCoveringCC.js +136 -188
  45. package/build/cc/WindowCoveringCC.js.map +1 -1
  46. package/build/cc/ZWavePlusCC.d.ts +1 -2
  47. package/build/cc/ZWavePlusCC.d.ts.map +1 -1
  48. package/build/cc/ZWavePlusCC.js +68 -15
  49. package/build/cc/ZWavePlusCC.js.map +1 -1
  50. package/build/lib/API.d.ts +18 -2
  51. package/build/lib/API.d.ts.map +1 -1
  52. package/build/lib/API.js +13 -4
  53. package/build/lib/API.js.map +1 -1
  54. package/build/lib/Values.d.ts +2 -0
  55. package/build/lib/Values.d.ts.map +1 -1
  56. package/package.json +6 -6
@@ -817,10 +817,29 @@ let ConfigurationCCAPI = class ConfigurationCCAPI extends API_1.CCAPI {
817
817
  values: allParams.map((v) => v.value),
818
818
  handshake: true,
819
819
  });
820
- return this.applHost.sendCommand(cc, this.commandOptions);
820
+ // The handshake flag is set, so we expect a BulkReport in response
821
+ const result = await this.applHost.sendCommand(cc, this.commandOptions);
822
+ // If we did receive a response, we also received the updated parameters,
823
+ // so if any one was not accepted, we know by looking at the values.
824
+ // Translate the result into a SupervisionResult by comparing the values
825
+ if (result) {
826
+ const sentValues = cc.values;
827
+ const receivedValues = [...result.values.values()];
828
+ const success = sentValues.length === receivedValues.length &&
829
+ sentValues.every((v, i) => v === receivedValues[i]);
830
+ return {
831
+ status: success
832
+ ? safe_1.SupervisionStatus.Success
833
+ : safe_1.SupervisionStatus.Fail,
834
+ };
835
+ }
836
+ else {
837
+ return undefined;
838
+ }
821
839
  }
822
840
  else {
823
841
  this.assertSupportsCommand(_Types_1.ConfigurationCommand, _Types_1.ConfigurationCommand.Set);
842
+ const supervisionResults = [];
824
843
  for (const { parameter, value, valueSize, valueFormat, } of allParams) {
825
844
  const cc = new ConfigurationCCSet(this.applHost, {
826
845
  nodeId: this.endpoint.nodeId,
@@ -830,9 +849,9 @@ let ConfigurationCCAPI = class ConfigurationCCAPI extends API_1.CCAPI {
830
849
  valueSize,
831
850
  valueFormat,
832
851
  });
833
- // TODO: handle intermediate errors
834
- await this.applHost.sendCommand(cc, this.commandOptions);
852
+ supervisionResults.push(await this.applHost.sendCommand(cc, this.commandOptions));
835
853
  }
854
+ return (0, safe_1.mergeSupervisionResults)(supervisionResults);
836
855
  }
837
856
  }
838
857
  /**
@@ -1033,6 +1052,7 @@ let ConfigurationCC = class ConfigurationCC extends CommandClass_1.CommandClass
1033
1052
  });
1034
1053
  this.deserializeParamInformationFromConfig(applHost, paramInfo);
1035
1054
  }
1055
+ const documentedParamNumbers = new Set(Array.from(paramInfo?.keys() ?? []).map((k) => k.parameter));
1036
1056
  if (this.version >= 3) {
1037
1057
  applHost.controllerLog.logNode(node.id, {
1038
1058
  endpoint: this.endpointIndex,
@@ -1067,14 +1087,16 @@ let ConfigurationCC = class ConfigurationCC extends CommandClass_1.CommandClass
1067
1087
  direction: "outbound",
1068
1088
  });
1069
1089
  // Query properties and the next param
1070
- const props = await api.getProperties(param);
1090
+ const props = await api.getProperties(param).catch(
1091
+ // If querying the properties fails, don't abort the entire interview
1092
+ () => undefined);
1071
1093
  if (!props) {
1072
1094
  applHost.controllerLog.logNode(node.id, {
1073
1095
  endpoint: this.endpointIndex,
1074
- message: `Querying parameter #${param} information timed out, skipping interview...`,
1096
+ message: `Querying parameter #${param} information timed out, skipping scan...`,
1075
1097
  level: "warn",
1076
1098
  });
1077
- return;
1099
+ break;
1078
1100
  }
1079
1101
  const { nextParameter, ...properties } = props;
1080
1102
  let logMessage;
@@ -1082,14 +1104,21 @@ let ConfigurationCC = class ConfigurationCC extends CommandClass_1.CommandClass
1082
1104
  logMessage = `Parameter #${param} is unsupported. Next parameter: ${nextParameter}`;
1083
1105
  }
1084
1106
  else {
1085
- // Query name and info only if the parameter is supported, but skip the query for bugged devices
1086
1107
  let name;
1087
- if (!deviceConfig?.compat?.skipConfigurationNameQuery) {
1088
- name = await api.getName(param);
1089
- }
1090
- // Skip the info query for bugged devices
1091
- if (!deviceConfig?.compat?.skipConfigurationInfoQuery) {
1092
- await api.getInfo(param);
1108
+ // Query the name and info for parameters that are NOT defined in a config file
1109
+ if (!documentedParamNumbers.has(param)) {
1110
+ // Skip the name query for bugged devices
1111
+ if (!deviceConfig?.compat?.skipConfigurationNameQuery) {
1112
+ name = await api.getName(param).catch(
1113
+ // If querying the name fails, don't abort the entire interview
1114
+ () => undefined);
1115
+ }
1116
+ // Skip the info query for bugged devices
1117
+ if (!deviceConfig?.compat?.skipConfigurationInfoQuery) {
1118
+ await api.getInfo(param).catch(
1119
+ // If querying the info fails, don't abort the entire interview
1120
+ () => undefined);
1121
+ }
1093
1122
  }
1094
1123
  logMessage = `received information for parameter #${param}:`;
1095
1124
  if (name) {
@@ -1368,30 +1397,38 @@ exports.ConfigurationCC = ConfigurationCC;
1368
1397
  let ConfigurationCCReport = class ConfigurationCCReport extends ConfigurationCC {
1369
1398
  constructor(host, options) {
1370
1399
  super(host, options);
1371
- // All fields must be present
1372
- (0, safe_1.validatePayload)(this.payload.length > 2);
1373
- this._parameter = this.payload[0];
1374
- this._valueSize = this.payload[1] & 0b111;
1375
- // Ensure we received a valid report
1376
- (0, safe_1.validatePayload)(this._valueSize >= 1, this._valueSize <= 4, this.payload.length >= 2 + this._valueSize);
1377
- // Default to parsing the value as SignedInteger, like the specs say.
1378
- // We try to re-interpret the value in persistValues()
1379
- this._value = parseValue(this.payload.slice(2), this._valueSize, safe_1.ConfigValueFormat.SignedInteger);
1400
+ if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
1401
+ // All fields must be present
1402
+ (0, safe_1.validatePayload)(this.payload.length > 2);
1403
+ this.parameter = this.payload[0];
1404
+ this.valueSize = this.payload[1] & 0b111;
1405
+ // Ensure we received a valid report
1406
+ (0, safe_1.validatePayload)(this.valueSize >= 1, this.valueSize <= 4, this.payload.length >= 2 + this.valueSize);
1407
+ // Default to parsing the value as SignedInteger, like the specs say.
1408
+ // We try to re-interpret the value in persistValues()
1409
+ this.value = parseValue(this.payload.slice(2), this.valueSize, safe_1.ConfigValueFormat.SignedInteger);
1410
+ }
1411
+ else {
1412
+ this.parameter = options.parameter;
1413
+ this.value = options.value;
1414
+ this.valueSize = options.valueSize;
1415
+ this.valueFormat = options.valueFormat;
1416
+ }
1380
1417
  }
1381
1418
  persistValues(applHost) {
1382
1419
  if (!super.persistValues(applHost))
1383
1420
  return false;
1384
1421
  const valueDB = this.getValueDB(applHost);
1385
1422
  // Check if the initial assumption of SignedInteger holds true
1386
- const oldParamInformation = this.getParamInformation(applHost, this._parameter);
1423
+ const oldParamInformation = this.getParamInformation(applHost, this.parameter);
1387
1424
  if (oldParamInformation.format != undefined &&
1388
1425
  oldParamInformation.format !== safe_1.ConfigValueFormat.SignedInteger) {
1389
1426
  // Re-interpret the value with the new format
1390
- this._value = reInterpretSignedValue(this._value, this._valueSize, oldParamInformation.format);
1427
+ this.value = reInterpretSignedValue(this.value, this.valueSize, oldParamInformation.format);
1391
1428
  }
1392
1429
  // Store the parameter size and value
1393
- this.extendParamInformation(applHost, this._parameter, undefined, {
1394
- valueSize: this._valueSize,
1430
+ this.extendParamInformation(applHost, this.parameter, undefined, {
1431
+ valueSize: this.valueSize,
1395
1432
  type: oldParamInformation.format === safe_1.ConfigValueFormat.BitField
1396
1433
  ? "number[]"
1397
1434
  : "number",
@@ -1402,19 +1439,19 @@ let ConfigurationCCReport = class ConfigurationCCReport extends ConfigurationCC
1402
1439
  oldParamInformation.max == undefined) {
1403
1440
  const isSigned = oldParamInformation.format == undefined ||
1404
1441
  oldParamInformation.format === safe_1.ConfigValueFormat.SignedInteger;
1405
- this.extendParamInformation(applHost, this._parameter, undefined, (0, safe_1.getIntegerLimits)(this._valueSize, isSigned));
1442
+ this.extendParamInformation(applHost, this.parameter, undefined, (0, safe_1.getIntegerLimits)(this.valueSize, isSigned));
1406
1443
  }
1407
1444
  // And store the value itself
1408
1445
  // If we have partial config params defined, we need to split the value
1409
- const partialParams = this.getPartialParamInfos(applHost, this._parameter);
1446
+ const partialParams = this.getPartialParamInfos(applHost, this.parameter);
1410
1447
  if (partialParams.length > 0) {
1411
1448
  for (const param of partialParams) {
1412
1449
  if (typeof param.propertyKey === "number") {
1413
1450
  valueDB.setValue({
1414
1451
  commandClass: this.ccId,
1415
- property: this._parameter,
1452
+ property: this.parameter,
1416
1453
  propertyKey: param.propertyKey,
1417
- }, (0, safe_1.parsePartial)(this._value, param.propertyKey, isSignedPartial(param.propertyKey, param.metadata.format)));
1454
+ }, (0, safe_1.parsePartial)(this.value, param.propertyKey, isSignedPartial(param.propertyKey, param.metadata.format)));
1418
1455
  }
1419
1456
  }
1420
1457
  }
@@ -1422,19 +1459,21 @@ let ConfigurationCCReport = class ConfigurationCCReport extends ConfigurationCC
1422
1459
  // This is a single param
1423
1460
  valueDB.setValue({
1424
1461
  commandClass: this.ccId,
1425
- property: this._parameter,
1426
- }, this._value);
1462
+ property: this.parameter,
1463
+ }, this.value);
1427
1464
  }
1428
1465
  return true;
1429
1466
  }
1430
- get parameter() {
1431
- return this._parameter;
1432
- }
1433
- get value() {
1434
- return this._value;
1435
- }
1436
- get valueSize() {
1437
- return this._valueSize;
1467
+ serialize() {
1468
+ this.payload = Buffer.concat([
1469
+ Buffer.from([this.parameter, this.valueSize & 0b111]),
1470
+ Buffer.allocUnsafe(this.valueSize),
1471
+ ]);
1472
+ const valueFormat = typeof this.value === "number"
1473
+ ? this.valueFormat ?? safe_1.ConfigValueFormat.SignedInteger
1474
+ : safe_1.ConfigValueFormat.BitField;
1475
+ serializeValue(this.payload, 2, this.valueSize, valueFormat, this.value);
1476
+ return super.serialize();
1438
1477
  }
1439
1478
  toLogEntry(applHost) {
1440
1479
  return {
@@ -1459,8 +1498,9 @@ let ConfigurationCCGet = class ConfigurationCCGet extends ConfigurationCC {
1459
1498
  constructor(host, options) {
1460
1499
  super(host, options);
1461
1500
  if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
1462
- // TODO: Deserialize payload
1463
- throw new safe_1.ZWaveError(`${this.constructor.name}: deserialization not implemented`, safe_1.ZWaveErrorCodes.Deserialization_NotImplemented);
1501
+ (0, safe_1.validatePayload)(this.payload.length >= 1);
1502
+ this.parameter = this.payload[0];
1503
+ this.allowUnexpectedResponse = false;
1464
1504
  }
1465
1505
  else {
1466
1506
  this.parameter = options.parameter;
@@ -1488,8 +1528,14 @@ let ConfigurationCCSet = class ConfigurationCCSet extends ConfigurationCC {
1488
1528
  constructor(host, options) {
1489
1529
  super(host, options);
1490
1530
  if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
1491
- // TODO: Deserialize payload
1492
- throw new safe_1.ZWaveError(`${this.constructor.name}: deserialization not implemented`, safe_1.ZWaveErrorCodes.Deserialization_NotImplemented);
1531
+ (0, safe_1.validatePayload)(this.payload.length >= 2);
1532
+ this.parameter = this.payload[0];
1533
+ this.resetToDefault = !!(this.payload[1] & 128);
1534
+ this.valueSize = this.payload[1] & 0b111;
1535
+ // Ensure we received a valid report
1536
+ (0, safe_1.validatePayload)(this.valueSize >= 1, this.valueSize <= 4, this.payload.length >= 2 + this.valueSize);
1537
+ // Parse the value as signed integer. We don't know the format here.
1538
+ this.value = parseValue(this.payload.slice(2), this.valueSize, safe_1.ConfigValueFormat.SignedInteger);
1493
1539
  }
1494
1540
  else {
1495
1541
  this.parameter = options.parameter;
@@ -1809,6 +1855,7 @@ let ConfigurationCCNameReport = class ConfigurationCCNameReport extends Configur
1809
1855
  return false;
1810
1856
  this.extendParamInformation(applHost, this.parameter, undefined, {
1811
1857
  name: this.name,
1858
+ label: this.name,
1812
1859
  });
1813
1860
  return true;
1814
1861
  }
@@ -1879,44 +1926,51 @@ exports.ConfigurationCCNameGet = ConfigurationCCNameGet;
1879
1926
  let ConfigurationCCInfoReport = class ConfigurationCCInfoReport extends ConfigurationCC {
1880
1927
  constructor(host, options) {
1881
1928
  super(host, options);
1882
- // Parameter and # of reports must be present
1883
- (0, safe_1.validatePayload)(this.payload.length >= 3);
1884
- this._parameter = this.payload.readUInt16BE(0);
1885
- this._reportsToFollow = this.payload[2];
1886
- if (this._reportsToFollow > 0) {
1887
- // If more reports follow, the info must at least be one byte
1888
- (0, safe_1.validatePayload)(this.payload.length >= 4);
1929
+ if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
1930
+ // Parameter and # of reports must be present
1931
+ (0, safe_1.validatePayload)(this.payload.length >= 3);
1932
+ this.parameter = this.payload.readUInt16BE(0);
1933
+ this.reportsToFollow = this.payload[2];
1934
+ if (this.reportsToFollow > 0) {
1935
+ // If more reports follow, the info must at least be one byte
1936
+ (0, safe_1.validatePayload)(this.payload.length >= 4);
1937
+ }
1938
+ this.info = this.payload.slice(3).toString("utf8");
1939
+ }
1940
+ else {
1941
+ this.parameter = options.parameter;
1942
+ this.info = options.info;
1943
+ this.reportsToFollow = options.reportsToFollow;
1889
1944
  }
1890
- this._info = this.payload.slice(3).toString("utf8");
1891
1945
  }
1892
1946
  persistValues(applHost) {
1893
1947
  if (!super.persistValues(applHost))
1894
1948
  return false;
1895
- this.extendParamInformation(applHost, this._parameter, undefined, {
1896
- info: this._info,
1949
+ this.extendParamInformation(applHost, this.parameter, undefined, {
1950
+ info: this.info,
1951
+ description: this.info,
1897
1952
  });
1898
1953
  return true;
1899
1954
  }
1900
- get parameter() {
1901
- return this._parameter;
1902
- }
1903
- get info() {
1904
- return this._info;
1905
- }
1906
- get reportsToFollow() {
1907
- return this._reportsToFollow;
1955
+ serialize() {
1956
+ const infoBuffer = Buffer.from(this.info, "utf8");
1957
+ this.payload = Buffer.allocUnsafe(3 + infoBuffer.length);
1958
+ this.payload.writeUInt16BE(this.parameter, 0);
1959
+ this.payload[2] = this.reportsToFollow;
1960
+ infoBuffer.copy(this.payload, 3);
1961
+ return super.serialize();
1908
1962
  }
1909
1963
  getPartialCCSessionId() {
1910
1964
  // Distinguish sessions by the parameter number
1911
- return { parameter: this._parameter };
1965
+ return { parameter: this.parameter };
1912
1966
  }
1913
1967
  expectMoreMessages() {
1914
- return this._reportsToFollow > 0;
1968
+ return this.reportsToFollow > 0;
1915
1969
  }
1916
1970
  mergePartialCCs(applHost, partials) {
1917
1971
  // Concat the info
1918
- this._info = [...partials, this]
1919
- .map((report) => report._info)
1972
+ this.info = [...partials, this]
1973
+ .map((report) => report.info)
1920
1974
  .reduce((prev, cur) => prev + cur, "");
1921
1975
  }
1922
1976
  toLogEntry(applHost) {
@@ -1938,8 +1992,8 @@ let ConfigurationCCInfoGet = class ConfigurationCCInfoGet extends ConfigurationC
1938
1992
  constructor(host, options) {
1939
1993
  super(host, options);
1940
1994
  if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
1941
- // TODO: Deserialize payload
1942
- throw new safe_1.ZWaveError(`${this.constructor.name}: deserialization not implemented`, safe_1.ZWaveErrorCodes.Deserialization_NotImplemented);
1995
+ (0, safe_1.validatePayload)(this.payload.length >= 2);
1996
+ this.parameter = this.payload.readUInt16BE(0);
1943
1997
  }
1944
1998
  else {
1945
1999
  this.parameter = options.parameter;
@@ -1965,128 +2019,153 @@ exports.ConfigurationCCInfoGet = ConfigurationCCInfoGet;
1965
2019
  let ConfigurationCCPropertiesReport = class ConfigurationCCPropertiesReport extends ConfigurationCC {
1966
2020
  constructor(host, options) {
1967
2021
  super(host, options);
1968
- (0, safe_1.validatePayload)(this.payload.length >= 3);
1969
- this._parameter = this.payload.readUInt16BE(0);
1970
- this._valueFormat = (this.payload[2] & 0b111000) >>> 3;
1971
- this._valueSize = this.payload[2] & 0b111;
1972
- // GH#1309 Some devices don't tell us the first parameter if we query #0
1973
- // Instead, they contain 0x000000
1974
- if (this._valueSize === 0 && this.payload.length < 5) {
1975
- this._nextParameter = 0;
1976
- return;
1977
- }
1978
- // Ensure the payload contains the two bytes for next parameter
1979
- const nextParameterOffset = 3 + 3 * this._valueSize;
1980
- (0, safe_1.validatePayload)(this.payload.length >= nextParameterOffset + 2);
1981
- if (this.valueSize > 0) {
1982
- if (this._valueFormat !== safe_1.ConfigValueFormat.BitField) {
1983
- this._minValue = parseValue(this.payload.slice(3), this._valueSize, this._valueFormat);
2022
+ if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
2023
+ (0, safe_1.validatePayload)(this.payload.length >= 3);
2024
+ this.parameter = this.payload.readUInt16BE(0);
2025
+ this.valueFormat = (this.payload[2] & 0b111000) >>> 3;
2026
+ this.valueSize = this.payload[2] & 0b111;
2027
+ // GH#1309 Some devices don't tell us the first parameter if we query #0
2028
+ // Instead, they contain 0x000000
2029
+ if (this.valueSize === 0 && this.payload.length < 5) {
2030
+ this.nextParameter = 0;
2031
+ return;
2032
+ }
2033
+ // Ensure the payload contains the two bytes for next parameter
2034
+ const nextParameterOffset = 3 + 3 * this.valueSize;
2035
+ (0, safe_1.validatePayload)(this.payload.length >= nextParameterOffset + 2);
2036
+ if (this.valueSize > 0) {
2037
+ if (this.valueFormat !== safe_1.ConfigValueFormat.BitField) {
2038
+ this.minValue = parseValue(this.payload.slice(3), this.valueSize, this.valueFormat);
2039
+ }
2040
+ this.maxValue = parseValue(this.payload.slice(3 + this.valueSize), this.valueSize, this.valueFormat);
2041
+ this.defaultValue = parseValue(this.payload.slice(3 + 2 * this.valueSize), this.valueSize, this.valueFormat);
2042
+ }
2043
+ if (this.version < 4) {
2044
+ // Read the last 2 bytes to work around nodes not omitting min/max value when their size is 0
2045
+ this.nextParameter = this.payload.readUInt16BE(this.payload.length - 2);
2046
+ }
2047
+ else {
2048
+ this.nextParameter =
2049
+ this.payload.readUInt16BE(nextParameterOffset);
2050
+ // Ensure the payload contains a byte for the 2nd option flags
2051
+ (0, safe_1.validatePayload)(this.payload.length >= nextParameterOffset + 3);
2052
+ const options1 = this.payload[2];
2053
+ const options2 = this.payload[3 + 3 * this.valueSize + 2];
2054
+ this.altersCapabilities = !!(options1 & 128);
2055
+ this.isReadonly = !!(options1 & 64);
2056
+ this.isAdvanced = !!(options2 & 0b1);
2057
+ this.noBulkSupport = !!(options2 & 0b10);
1984
2058
  }
1985
- this._maxValue = parseValue(this.payload.slice(3 + this._valueSize), this._valueSize, this._valueFormat);
1986
- this._defaultValue = parseValue(this.payload.slice(3 + 2 * this._valueSize), this._valueSize, this._valueFormat);
1987
- }
1988
- if (this.version < 4) {
1989
- // Read the last 2 bytes to work around nodes not omitting min/max value when their size is 0
1990
- this._nextParameter = this.payload.readUInt16BE(this.payload.length - 2);
1991
2059
  }
1992
2060
  else {
1993
- this._nextParameter =
1994
- this.payload.readUInt16BE(nextParameterOffset);
1995
- // Ensure the payload contains a byte for the 2nd option flags
1996
- (0, safe_1.validatePayload)(this.payload.length >= nextParameterOffset + 3);
1997
- const options1 = this.payload[2];
1998
- const options2 = this.payload[3 + 3 * this.valueSize + 2];
1999
- this._altersCapabilities = !!(options1 & 128);
2000
- this._isReadonly = !!(options1 & 64);
2001
- this._isAdvanced = !!(options2 & 0b1);
2002
- this._noBulkSupport = !!(options2 & 0b10);
2061
+ this.parameter = options.parameter;
2062
+ this.valueSize = options.valueSize;
2063
+ this.valueFormat = options.valueFormat;
2064
+ if (this.valueSize > 0) {
2065
+ if (options.minValue == undefined) {
2066
+ throw new safe_1.ZWaveError("The minimum value must be set when the value size is non-zero", safe_1.ZWaveErrorCodes.Argument_Invalid);
2067
+ }
2068
+ else if (options.maxValue == undefined) {
2069
+ throw new safe_1.ZWaveError("The maximum value must be set when the value size is non-zero", safe_1.ZWaveErrorCodes.Argument_Invalid);
2070
+ }
2071
+ else if (options.defaultValue == undefined) {
2072
+ throw new safe_1.ZWaveError("The default value must be set when the value size is non-zero", safe_1.ZWaveErrorCodes.Argument_Invalid);
2073
+ }
2074
+ this.minValue = options.minValue;
2075
+ this.maxValue = options.maxValue;
2076
+ this.defaultValue = options.defaultValue;
2077
+ }
2078
+ this.nextParameter = options.nextParameter;
2079
+ this.altersCapabilities = options.altersCapabilities;
2080
+ this.isReadonly = options.isReadonly;
2081
+ this.isAdvanced = options.isAdvanced;
2082
+ this.noBulkSupport = options.noBulkSupport;
2003
2083
  }
2004
2084
  }
2005
2085
  persistValues(applHost) {
2006
2086
  if (!super.persistValues(applHost))
2007
2087
  return false;
2008
2088
  // If we actually received parameter info, store it
2009
- if (this._valueSize > 0) {
2010
- const valueType = this._valueFormat === safe_1.ConfigValueFormat.SignedInteger ||
2011
- this._valueFormat === safe_1.ConfigValueFormat.UnsignedInteger
2089
+ if (this.valueSize > 0) {
2090
+ const valueType = this.valueFormat === safe_1.ConfigValueFormat.SignedInteger ||
2091
+ this.valueFormat === safe_1.ConfigValueFormat.UnsignedInteger
2012
2092
  ? "number"
2013
2093
  : "number[]";
2014
2094
  const paramInfo = (0, safe_1.stripUndefined)({
2015
2095
  type: valueType,
2016
- valueFormat: this._valueFormat,
2017
- valueSize: this._valueSize,
2018
- minValue: this._minValue,
2019
- maxValue: this._maxValue,
2020
- defaultValue: this._defaultValue,
2021
- requiresReInclusion: this._altersCapabilities,
2022
- writeable: !this._isReadonly,
2023
- isAdvanced: this._isAdvanced,
2024
- noBulkSupport: this._noBulkSupport,
2096
+ format: this.valueFormat,
2097
+ valueSize: this.valueSize,
2098
+ min: this.minValue,
2099
+ max: this.maxValue,
2100
+ default: this.defaultValue,
2101
+ requiresReInclusion: this.altersCapabilities,
2102
+ readable: true,
2103
+ writeable: !this.isReadonly,
2104
+ allowManualEntry: true,
2105
+ isAdvanced: this.isAdvanced,
2106
+ noBulkSupport: this.noBulkSupport,
2107
+ isFromConfig: false,
2025
2108
  });
2026
- this.extendParamInformation(applHost, this._parameter, undefined, paramInfo);
2109
+ this.extendParamInformation(applHost, this.parameter, undefined, paramInfo);
2027
2110
  }
2028
2111
  return true;
2029
2112
  }
2030
- get parameter() {
2031
- return this._parameter;
2032
- }
2033
- get valueSize() {
2034
- return this._valueSize;
2035
- }
2036
- get valueFormat() {
2037
- return this._valueFormat;
2038
- }
2039
- get minValue() {
2040
- return this._minValue;
2041
- }
2042
- get maxValue() {
2043
- return this._maxValue;
2044
- }
2045
- get defaultValue() {
2046
- return this._defaultValue;
2047
- }
2048
- get nextParameter() {
2049
- return this._nextParameter;
2050
- }
2051
- get altersCapabilities() {
2052
- return this._altersCapabilities;
2053
- }
2054
- get isReadonly() {
2055
- return this._isReadonly;
2056
- }
2057
- get isAdvanced() {
2058
- return this._isAdvanced;
2059
- }
2060
- get noBulkSupport() {
2061
- return this._noBulkSupport;
2113
+ serialize() {
2114
+ this.payload = Buffer.allocUnsafe(3 + // preamble
2115
+ 3 * this.valueSize + // min, max, default value
2116
+ 2);
2117
+ this.payload.writeUInt16BE(this.parameter, 0);
2118
+ const options1 = (this.altersCapabilities ? 128 : 0) |
2119
+ (this.isReadonly ? 64 : 0) |
2120
+ ((this.valueFormat & 0b111) << 3) |
2121
+ (this.valueSize & 0b111);
2122
+ this.payload[2] = options1;
2123
+ let offset = 3;
2124
+ if (this.valueSize > 0) {
2125
+ serializeValue(this.payload, offset, this.valueSize, this.valueFormat, this.minValue);
2126
+ offset += this.valueSize;
2127
+ serializeValue(this.payload, offset, this.valueSize, this.valueFormat, this.maxValue);
2128
+ offset += this.valueSize;
2129
+ serializeValue(this.payload, offset, this.valueSize, this.valueFormat, this.defaultValue);
2130
+ offset += this.valueSize;
2131
+ }
2132
+ this.payload.writeUInt16BE(this.nextParameter, offset);
2133
+ if (this.version >= 4) {
2134
+ const options2 = (this.isAdvanced ? 0b1 : 0) | (this.noBulkSupport ? 0b10 : 0);
2135
+ this.payload = Buffer.concat([
2136
+ this.payload,
2137
+ Buffer.from([options2]),
2138
+ ]);
2139
+ }
2140
+ return super.serialize();
2062
2141
  }
2063
2142
  toLogEntry(applHost) {
2064
2143
  const message = {
2065
- "parameter #": this._parameter,
2066
- "next param #": this._nextParameter,
2067
- "value size": this._valueSize,
2068
- "value format": (0, safe_2.getEnumMemberName)(safe_1.ConfigValueFormat, this._valueFormat),
2144
+ "parameter #": this.parameter,
2145
+ "next param #": this.nextParameter,
2146
+ "value size": this.valueSize,
2147
+ "value format": (0, safe_2.getEnumMemberName)(safe_1.ConfigValueFormat, this.valueFormat),
2069
2148
  };
2070
- if (this._minValue != undefined) {
2071
- message["min value"] = configValueToString(this._minValue);
2149
+ if (this.minValue != undefined) {
2150
+ message["min value"] = configValueToString(this.minValue);
2072
2151
  }
2073
- if (this._maxValue != undefined) {
2074
- message["max value"] = configValueToString(this._maxValue);
2152
+ if (this.maxValue != undefined) {
2153
+ message["max value"] = configValueToString(this.maxValue);
2075
2154
  }
2076
- if (this._defaultValue != undefined) {
2077
- message["default value"] = configValueToString(this._defaultValue);
2155
+ if (this.defaultValue != undefined) {
2156
+ message["default value"] = configValueToString(this.defaultValue);
2078
2157
  }
2079
- if (this._altersCapabilities != undefined) {
2080
- message["alters capabilities"] = this._altersCapabilities;
2158
+ if (this.altersCapabilities != undefined) {
2159
+ message["alters capabilities"] = this.altersCapabilities;
2081
2160
  }
2082
- if (this._isReadonly != undefined) {
2083
- message.readonly = this._isReadonly;
2161
+ if (this.isReadonly != undefined) {
2162
+ message.readonly = this.isReadonly;
2084
2163
  }
2085
- if (this._isAdvanced != undefined) {
2086
- message.advanced = this._isAdvanced;
2164
+ if (this.isAdvanced != undefined) {
2165
+ message.advanced = this.isAdvanced;
2087
2166
  }
2088
- if (this._noBulkSupport != undefined) {
2089
- message["bulk support"] = !this._noBulkSupport;
2167
+ if (this.noBulkSupport != undefined) {
2168
+ message["bulk support"] = !this.noBulkSupport;
2090
2169
  }
2091
2170
  return {
2092
2171
  ...super.toLogEntry(applHost),
@@ -2102,8 +2181,8 @@ let ConfigurationCCPropertiesGet = class ConfigurationCCPropertiesGet extends Co
2102
2181
  constructor(host, options) {
2103
2182
  super(host, options);
2104
2183
  if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
2105
- // TODO: Deserialize payload
2106
- throw new safe_1.ZWaveError(`${this.constructor.name}: deserialization not implemented`, safe_1.ZWaveErrorCodes.Deserialization_NotImplemented);
2184
+ (0, safe_1.validatePayload)(this.payload.length >= 2);
2185
+ this.parameter = this.payload.readUInt16BE(0);
2107
2186
  }
2108
2187
  else {
2109
2188
  this.parameter = options.parameter;