mclimate-payload-helper 1.2.19 → 1.2.21

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 (177) hide show
  1. package/README.md +21 -0
  2. package/dist/decoders/payloadParsers/multisensorPayloadParser.d.ts.map +1 -1
  3. package/dist/decoders/payloadParsers/multisensorPayloadParser.js +80 -33
  4. package/dist/decoders/payloadParsers/multisensorPayloadParser.js.map +1 -1
  5. package/dist/encoders/ButtonCommands.test.d.ts +2 -0
  6. package/dist/encoders/ButtonCommands.test.d.ts.map +1 -0
  7. package/dist/encoders/ButtonCommands.test.js +20 -0
  8. package/dist/encoders/ButtonCommands.test.js.map +1 -0
  9. package/dist/encoders/ChildLockCommands.test.d.ts +2 -0
  10. package/dist/encoders/ChildLockCommands.test.d.ts.map +1 -0
  11. package/dist/encoders/ChildLockCommands.test.js +17 -0
  12. package/dist/encoders/ChildLockCommands.test.js.map +1 -0
  13. package/dist/encoders/Co2DisplayCommands.test.d.ts +2 -0
  14. package/dist/encoders/Co2DisplayCommands.test.d.ts.map +1 -0
  15. package/dist/encoders/Co2DisplayCommands.test.js +18 -0
  16. package/dist/encoders/Co2DisplayCommands.test.js.map +1 -0
  17. package/dist/encoders/Co2DisplayCommonCommands.d.ts +4 -0
  18. package/dist/encoders/Co2DisplayCommonCommands.d.ts.map +1 -1
  19. package/dist/encoders/Co2DisplayCommonCommands.js +38 -0
  20. package/dist/encoders/Co2DisplayCommonCommands.js.map +1 -1
  21. package/dist/encoders/Co2DisplayLiteCommands.test.d.ts +2 -0
  22. package/dist/encoders/Co2DisplayLiteCommands.test.d.ts.map +1 -0
  23. package/dist/encoders/Co2DisplayLiteCommands.test.js +21 -0
  24. package/dist/encoders/Co2DisplayLiteCommands.test.js.map +1 -0
  25. package/dist/encoders/Co2PirLiteCommands.test.d.ts +2 -0
  26. package/dist/encoders/Co2PirLiteCommands.test.d.ts.map +1 -0
  27. package/dist/encoders/Co2PirLiteCommands.test.js +23 -0
  28. package/dist/encoders/Co2PirLiteCommands.test.js.map +1 -0
  29. package/dist/encoders/Co2SensorCommands.test.d.ts +2 -0
  30. package/dist/encoders/Co2SensorCommands.test.d.ts.map +1 -0
  31. package/dist/encoders/Co2SensorCommands.test.js +55 -0
  32. package/dist/encoders/Co2SensorCommands.test.js.map +1 -0
  33. package/dist/encoders/DisplayCommands.test.d.ts +2 -0
  34. package/dist/encoders/DisplayCommands.test.d.ts.map +1 -0
  35. package/dist/encoders/DisplayCommands.test.js +26 -0
  36. package/dist/encoders/DisplayCommands.test.js.map +1 -0
  37. package/dist/encoders/DskDeviceCommands.test.d.ts +2 -0
  38. package/dist/encoders/DskDeviceCommands.test.d.ts.map +1 -0
  39. package/dist/encoders/DskDeviceCommands.test.js +20 -0
  40. package/dist/encoders/DskDeviceCommands.test.js.map +1 -0
  41. package/dist/encoders/FanCoilThermostatCommands.test.d.ts +2 -0
  42. package/dist/encoders/FanCoilThermostatCommands.test.d.ts.map +1 -0
  43. package/dist/encoders/FanCoilThermostatCommands.test.js +117 -0
  44. package/dist/encoders/FanCoilThermostatCommands.test.js.map +1 -0
  45. package/dist/encoders/GeneralCommands.test.d.ts +2 -0
  46. package/dist/encoders/GeneralCommands.test.d.ts.map +1 -0
  47. package/dist/encoders/GeneralCommands.test.js +26 -0
  48. package/dist/encoders/GeneralCommands.test.js.map +1 -0
  49. package/dist/encoders/HTDisplayLiteCommands.test.d.ts +2 -0
  50. package/dist/encoders/HTDisplayLiteCommands.test.d.ts.map +1 -0
  51. package/dist/encoders/HTDisplayLiteCommands.test.js +20 -0
  52. package/dist/encoders/HTDisplayLiteCommands.test.js.map +1 -0
  53. package/dist/encoders/HTPirLiteCommands.test.d.ts +2 -0
  54. package/dist/encoders/HTPirLiteCommands.test.d.ts.map +1 -0
  55. package/dist/encoders/HTPirLiteCommands.test.js +23 -0
  56. package/dist/encoders/HTPirLiteCommands.test.js.map +1 -0
  57. package/dist/encoders/HTSensorCommands.test.d.ts +2 -0
  58. package/dist/encoders/HTSensorCommands.test.d.ts.map +1 -0
  59. package/dist/encoders/HTSensorCommands.test.js +17 -0
  60. package/dist/encoders/HTSensorCommands.test.js.map +1 -0
  61. package/dist/encoders/MelissaCommands.test.d.ts +2 -0
  62. package/dist/encoders/MelissaCommands.test.d.ts.map +1 -0
  63. package/dist/encoders/MelissaCommands.test.js +14 -0
  64. package/dist/encoders/MelissaCommands.test.js.map +1 -0
  65. package/dist/encoders/MultiSensorCommands.test.d.ts +2 -0
  66. package/dist/encoders/MultiSensorCommands.test.d.ts.map +1 -0
  67. package/dist/encoders/MultiSensorCommands.test.js +41 -0
  68. package/dist/encoders/MultiSensorCommands.test.js.map +1 -0
  69. package/dist/encoders/OpenCloseSensorCommands.test.d.ts +2 -0
  70. package/dist/encoders/OpenCloseSensorCommands.test.d.ts.map +1 -0
  71. package/dist/encoders/OpenCloseSensorCommands.test.js +14 -0
  72. package/dist/encoders/OpenCloseSensorCommands.test.js.map +1 -0
  73. package/dist/encoders/PIRCommands.test.d.ts +2 -0
  74. package/dist/encoders/PIRCommands.test.d.ts.map +1 -0
  75. package/dist/encoders/PIRCommands.test.js +29 -0
  76. package/dist/encoders/PIRCommands.test.js.map +1 -0
  77. package/dist/encoders/Relay16Commands.test.d.ts +2 -0
  78. package/dist/encoders/Relay16Commands.test.d.ts.map +1 -0
  79. package/dist/encoders/Relay16Commands.test.js +44 -0
  80. package/dist/encoders/Relay16Commands.test.js.map +1 -0
  81. package/dist/encoders/Relay16DryCommands.test.d.ts +2 -0
  82. package/dist/encoders/Relay16DryCommands.test.d.ts.map +1 -0
  83. package/dist/encoders/Relay16DryCommands.test.js +32 -0
  84. package/dist/encoders/Relay16DryCommands.test.js.map +1 -0
  85. package/dist/encoders/SetAqiLedCommands.test.d.ts +2 -0
  86. package/dist/encoders/SetAqiLedCommands.test.d.ts.map +1 -0
  87. package/dist/encoders/SetAqiLedCommands.test.js +20 -0
  88. package/dist/encoders/SetAqiLedCommands.test.js.map +1 -0
  89. package/dist/encoders/TFloodCommands.test.d.ts +2 -0
  90. package/dist/encoders/TFloodCommands.test.d.ts.map +1 -0
  91. package/dist/encoders/TFloodCommands.test.js +23 -0
  92. package/dist/encoders/TFloodCommands.test.js.map +1 -0
  93. package/dist/encoders/TRingThermostatCommands.test.d.ts +2 -0
  94. package/dist/encoders/TRingThermostatCommands.test.d.ts.map +1 -0
  95. package/dist/encoders/TRingThermostatCommands.test.js +16 -0
  96. package/dist/encoders/TRingThermostatCommands.test.js.map +1 -0
  97. package/dist/encoders/TValveCommands.test.d.ts +2 -0
  98. package/dist/encoders/TValveCommands.test.d.ts.map +1 -0
  99. package/dist/encoders/TValveCommands.test.js +56 -0
  100. package/dist/encoders/TValveCommands.test.js.map +1 -0
  101. package/dist/encoders/TemperatureCommonCommands.test.d.ts +2 -0
  102. package/dist/encoders/TemperatureCommonCommands.test.d.ts.map +1 -0
  103. package/dist/encoders/TemperatureCommonCommands.test.js +14 -0
  104. package/dist/encoders/TemperatureCommonCommands.test.js.map +1 -0
  105. package/dist/encoders/VickiCommands.test.d.ts +2 -0
  106. package/dist/encoders/VickiCommands.test.d.ts.map +1 -0
  107. package/dist/encoders/VickiCommands.test.js +156 -0
  108. package/dist/encoders/VickiCommands.test.js.map +1 -0
  109. package/dist/encoders/WirelessThermostatCommands.test.d.ts +2 -0
  110. package/dist/encoders/WirelessThermostatCommands.test.d.ts.map +1 -0
  111. package/dist/encoders/WirelessThermostatCommands.test.js +41 -0
  112. package/dist/encoders/WirelessThermostatCommands.test.js.map +1 -0
  113. package/dist/test/payloadDecoders.test.js +34 -34
  114. package/dist/test/payloadDecoders.test.js.map +1 -1
  115. package/package.json +1 -1
  116. package/src/decoders/payloadParsers/multisensorPayloadParser.ts +96 -34
  117. package/src/encoders/ButtonCommands.test.ts +26 -0
  118. package/src/encoders/ChildLockCommands.test.ts +22 -0
  119. package/src/encoders/Co2DisplayCommands.test.ts +26 -0
  120. package/src/encoders/Co2DisplayLiteCommands.test.ts +30 -0
  121. package/src/encoders/Co2PirLiteCommands.test.ts +32 -0
  122. package/src/encoders/Co2SensorCommands.test.ts +79 -0
  123. package/src/encoders/DisplayCommands.test.ts +40 -0
  124. package/src/encoders/DskDeviceCommands.test.ts +26 -0
  125. package/src/encoders/FanCoilThermostatCommands.test.ts +204 -0
  126. package/src/encoders/GeneralCommands.test.ts +38 -0
  127. package/src/encoders/HTDisplayLiteCommands.test.ts +28 -0
  128. package/src/encoders/HTPirLiteCommands.test.ts +32 -0
  129. package/src/encoders/HTSensorCommands.test.ts +24 -0
  130. package/src/encoders/MelissaCommands.test.ts +16 -0
  131. package/src/encoders/MultiSensorCommands.test.ts +68 -0
  132. package/src/encoders/OpenCloseSensorCommands.test.ts +16 -0
  133. package/src/encoders/PIRCommands.test.ts +46 -0
  134. package/src/encoders/Relay16Commands.test.ts +76 -0
  135. package/src/encoders/Relay16DryCommands.test.ts +52 -0
  136. package/src/encoders/SetAqiLedCommands.test.ts +18 -0
  137. package/src/encoders/TFloodCommands.test.ts +34 -0
  138. package/src/encoders/TRingThermostatCommands.test.ts +23 -0
  139. package/src/encoders/TValveCommands.test.ts +98 -0
  140. package/src/encoders/TemperatureCommonCommands.test.ts +16 -0
  141. package/src/encoders/VickiCommands.test.ts +275 -0
  142. package/src/encoders/WirelessThermostatCommands.test.ts +70 -0
  143. package/src/test/payloadDecoders.test.ts +34 -34
  144. package/src/test.txt +1 -0
  145. package/dist/encoders/FanCoilThermostat.d.ts +0 -61
  146. package/dist/encoders/FanCoilThermostat.d.ts.map +0 -1
  147. package/dist/encoders/FanCoilThermostat.js +0 -719
  148. package/dist/encoders/FanCoilThermostat.js.map +0 -1
  149. package/dist/encoders/SetAqiLed.d.ts +0 -6
  150. package/dist/encoders/SetAqiLed.d.ts.map +0 -1
  151. package/dist/encoders/SetAqiLed.js +0 -46
  152. package/dist/encoders/SetAqiLed.js.map +0 -1
  153. package/dist/encoders/types/enumValidation.d.ts +0 -6
  154. package/dist/encoders/types/enumValidation.d.ts.map +0 -1
  155. package/dist/encoders/types/enumValidation.js +0 -50
  156. package/dist/encoders/types/enumValidation.js.map +0 -1
  157. package/dist/encoders/types/schemaValidatedEnums.d.ts +0 -40
  158. package/dist/encoders/types/schemaValidatedEnums.d.ts.map +0 -1
  159. package/dist/encoders/types/schemaValidatedEnums.js +0 -181
  160. package/dist/encoders/types/schemaValidatedEnums.js.map +0 -1
  161. package/dist/types/deviceTypes.d.ts +0 -19
  162. package/dist/types/deviceTypes.d.ts.map +0 -1
  163. package/dist/types/deviceTypes.js +0 -23
  164. package/dist/types/deviceTypes.js.map +0 -1
  165. package/dist/types/index.d.ts +0 -2
  166. package/dist/types/index.d.ts.map +0 -1
  167. package/dist/types/index.js +0 -18
  168. package/dist/types/index.js.map +0 -1
  169. package/dist/types/types.d.ts +0 -13
  170. package/dist/types/types.d.ts.map +0 -1
  171. package/dist/types/types.js +0 -9
  172. package/dist/types/types.js.map +0 -1
  173. package/dist/validation.d.ts +0 -3
  174. package/dist/validation.d.ts.map +0 -1
  175. package/dist/validation.js +0 -8
  176. package/dist/validation.js.map +0 -1
  177. package/src/test/payloadEncoders.test.ts +0 -850
@@ -0,0 +1,204 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('FanCoilThermostatCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('fan_coil_thermostat')
6
+
7
+ test('SetTargetTemperatureStep encodes step *10', () => {
8
+ expect(commandBuilder.build('SetTargetTemperatureStep', { value: 0.5 })).toStrictEqual(
9
+ new BaseCommand('SetTargetTemperatureStep', 0x03, '05'),
10
+ )
11
+ })
12
+
13
+ test('SetKeysLock encodes lock value', () => {
14
+ expect(commandBuilder.build('SetKeysLock', { value: 3 })).toStrictEqual(new BaseCommand('SetKeysLock', 0x07, '03'))
15
+ })
16
+
17
+ test('SetTargetTemperature encodes temperature *10 as 2 bytes', () => {
18
+ expect(commandBuilder.build('SetTargetTemperature', { targetTemperature: 20 })).toStrictEqual(
19
+ new BaseCommand('SetTargetTemperature', 0x2e, '00C8'),
20
+ )
21
+ })
22
+
23
+ test('SetFctOperationalMode encodes mode', () => {
24
+ expect(commandBuilder.build('SetFctOperationalMode', { value: 2 })).toStrictEqual(
25
+ new BaseCommand('SetFctOperationalMode', 0x52, '02'),
26
+ )
27
+ })
28
+
29
+ test('SetValveOpenCloseTime encodes time', () => {
30
+ expect(commandBuilder.build('SetValveOpenCloseTime', { value: 15 })).toStrictEqual(
31
+ new BaseCommand('SetValveOpenCloseTime', 0x31, '0F'),
32
+ )
33
+ })
34
+
35
+ test('SetExtAutomaticTemperatureControl encodes toggle', () => {
36
+ expect(commandBuilder.build('SetExtAutomaticTemperatureControl', { value: 1 })).toStrictEqual(
37
+ new BaseCommand('SetExtAutomaticTemperatureControl', 0x35, '01'),
38
+ )
39
+ })
40
+
41
+ test('SetFanSpeed encodes speed', () => {
42
+ expect(commandBuilder.build('SetFanSpeed', { value: 4 })).toStrictEqual(new BaseCommand('SetFanSpeed', 0x44, '04'))
43
+ })
44
+
45
+ test('SetFanSpeedLimit encodes limit', () => {
46
+ expect(commandBuilder.build('SetFanSpeedLimit', { value: 2 })).toStrictEqual(
47
+ new BaseCommand('SetFanSpeedLimit', 0x46, '02'),
48
+ )
49
+ })
50
+
51
+ test('SetEcmVoltageRange encodes min/max *10', () => {
52
+ expect(commandBuilder.build('SetEcmVoltageRange', { min: 5, max: 8 })).toStrictEqual(
53
+ new BaseCommand('SetEcmVoltageRange', 0x48, '32', '50'),
54
+ )
55
+ })
56
+
57
+ test('SetEcmStartUpTime encodes start-up time', () => {
58
+ expect(commandBuilder.build('SetEcmStartUpTime', { value: 7 })).toStrictEqual(
59
+ new BaseCommand('SetEcmStartUpTime', 0x4a, '07'),
60
+ )
61
+ })
62
+
63
+ test('SetEcmRelay encodes relay toggle', () => {
64
+ expect(commandBuilder.build('SetEcmRelay', { value: 1 })).toStrictEqual(new BaseCommand('SetEcmRelay', 0x4c, '01'))
65
+ })
66
+
67
+ test('SetFrostProtection encodes protection toggle', () => {
68
+ expect(commandBuilder.build('SetFrostProtection', { value: 1 })).toStrictEqual(
69
+ new BaseCommand('SetFrostProtection', 0x4e, '01'),
70
+ )
71
+ })
72
+
73
+ test('SetFrostProtectionSettings encodes threshold and setpoint', () => {
74
+ expect(commandBuilder.build('SetFrostProtectionSettings', { threshold: 6, setpoint: 8 })).toStrictEqual(
75
+ new BaseCommand('SetFrostProtectionSettings', 0x50, '06', '08'),
76
+ )
77
+ })
78
+
79
+ test('SetAllowedOperationalModes encodes allowed modes', () => {
80
+ expect(commandBuilder.build('SetAllowedOperationalModes', { value: 1 })).toStrictEqual(
81
+ new BaseCommand('SetAllowedOperationalModes', 0x54, '01'),
82
+ )
83
+ })
84
+
85
+ test('SetCoolingSetpointNotOccupied encodes setpoint', () => {
86
+ expect(commandBuilder.build('SetCoolingSetpointNotOccupied', { value: 18 })).toStrictEqual(
87
+ new BaseCommand('SetCoolingSetpointNotOccupied', 0x56, '12'),
88
+ )
89
+ })
90
+
91
+ test('SetHeatingSetpointNotOccupied encodes setpoint', () => {
92
+ expect(commandBuilder.build('SetHeatingSetpointNotOccupied', { value: 19 })).toStrictEqual(
93
+ new BaseCommand('SetHeatingSetpointNotOccupied', 0x58, '13'),
94
+ )
95
+ })
96
+
97
+ test('SetTempSensorCompensation encodes compensation and absolute temperature *10', () => {
98
+ expect(commandBuilder.build('SetTempSensorCompensation', { compensation: 1, temperature: -1.5 })).toStrictEqual(
99
+ new BaseCommand('SetTempSensorCompensation', 0x5a, '01', '0F'),
100
+ )
101
+ })
102
+
103
+ test('SetFanSpeedNotOccupied encodes speed option', () => {
104
+ expect(commandBuilder.build('SetFanSpeedNotOccupied', { value: 2 })).toStrictEqual(
105
+ new BaseCommand('SetFanSpeedNotOccupied', 0x5c, '02'),
106
+ )
107
+ })
108
+
109
+ test('SetAutomaticChangeover encodes toggle', () => {
110
+ expect(commandBuilder.build('SetAutomaticChangeover', { value: 1 })).toStrictEqual(
111
+ new BaseCommand('SetAutomaticChangeover', 0x5e, '01'),
112
+ )
113
+ })
114
+
115
+ test('SetWiringDiagram encodes diagram value', () => {
116
+ expect(commandBuilder.build('SetWiringDiagram', { value: 3 })).toStrictEqual(
117
+ new BaseCommand('SetWiringDiagram', 0x60, '03'),
118
+ )
119
+ })
120
+
121
+ test('SetOccFunction encodes occupancy function', () => {
122
+ expect(commandBuilder.build('SetOccFunction', { value: 5 })).toStrictEqual(
123
+ new BaseCommand('SetOccFunction', 0x62, '05'),
124
+ )
125
+ })
126
+
127
+ test('SetAutomaticChangeoverThreshold encodes cooling/heating thresholds', () => {
128
+ expect(
129
+ commandBuilder.build('SetAutomaticChangeoverThreshold', { coolingThreshold: 10, heatingThreshold: 40 }),
130
+ ).toStrictEqual(new BaseCommand('SetAutomaticChangeoverThreshold', 0x64, '0A', '28'))
131
+ })
132
+
133
+ test('SetDeviceStatus encodes on/off', () => {
134
+ expect(commandBuilder.build('SetDeviceStatus', { value: 1 })).toStrictEqual(
135
+ new BaseCommand('SetDeviceStatus', 0x66, '01'),
136
+ )
137
+ })
138
+
139
+ test('SetReturnOfPowerOperation encodes behavior', () => {
140
+ expect(commandBuilder.build('SetReturnOfPowerOperation', { value: 2 })).toStrictEqual(
141
+ new BaseCommand('SetReturnOfPowerOperation', 0x68, '02'),
142
+ )
143
+ })
144
+
145
+ test('SetDeltaTemperature1 encodes delta *10', () => {
146
+ expect(commandBuilder.build('SetDeltaTemperature1', { value: 1.5 })).toStrictEqual(
147
+ new BaseCommand('SetDeltaTemperature1', 0x6a, '0F'),
148
+ )
149
+ })
150
+
151
+ test('SetDeltaTemperature2and3 encodes both deltas *10', () => {
152
+ expect(
153
+ commandBuilder.build('SetDeltaTemperature2and3', { deltaTemperature2: 2, deltaTemperature3: 2.5 }),
154
+ ).toStrictEqual(new BaseCommand('SetDeltaTemperature2and3', 0x6c, '14', '19'))
155
+ })
156
+
157
+ test('SetHeatingCoolingTargetTempRanges encodes min/max values', () => {
158
+ expect(
159
+ commandBuilder.build('SetHeatingCoolingTargetTempRanges', {
160
+ heatingTempMin: 10,
161
+ heatingTempMax: 20,
162
+ coolingTempMin: 15,
163
+ coolingTempMax: 25,
164
+ }),
165
+ ).toStrictEqual(new BaseCommand('SetHeatingCoolingTargetTempRanges', 0x16, '0A', '14', '0F', '19'))
166
+ })
167
+
168
+ test('SetHeatingCoolingTargetTempRangesUnoccupied encodes min/max values', () => {
169
+ expect(
170
+ commandBuilder.build('SetHeatingCoolingTargetTempRangesUnoccupied', {
171
+ heatingTempMin: 11,
172
+ heatingTempMax: 21,
173
+ coolingTempMin: 16,
174
+ coolingTempMax: 22,
175
+ }),
176
+ ).toStrictEqual(new BaseCommand('SetHeatingCoolingTargetTempRangesUnoccupied', 0x76, '0B', '15', '10', '16'))
177
+ })
178
+
179
+ test('SetFanOffDelayTime encodes delay time', () => {
180
+ expect(commandBuilder.build('SetFanOffDelayTime', { time: 30 })).toStrictEqual(
181
+ new BaseCommand('SetFanOffDelayTime', 0x78, '1E'),
182
+ )
183
+ })
184
+
185
+ test('SetAdditionalFanMode encodes mode', () => {
186
+ expect(commandBuilder.build('SetAdditionalFanMode', { mode: 2 })).toStrictEqual(
187
+ new BaseCommand('SetAdditionalFanMode', 0x7a, '02'),
188
+ )
189
+ })
190
+
191
+ test('SetUserInterfaceLanguage encodes language option', () => {
192
+ expect(commandBuilder.build('SetUserInterfaceLanguage', { value: 3 })).toStrictEqual(
193
+ new BaseCommand('SetUserInterfaceLanguage', 0x9a, '03'),
194
+ )
195
+ })
196
+
197
+ test('RestartDevice emits restart command', () => {
198
+ expect(commandBuilder.build('RestartDevice')).toStrictEqual(new BaseCommand('RestartDevice', 0xa5))
199
+ })
200
+
201
+ test('Invalid SetTargetTemperatureStep throws validation error', () => {
202
+ expect(() => commandBuilder.build('SetTargetTemperatureStep', { value: 0 })).toThrow(CustomError)
203
+ })
204
+ })
@@ -0,0 +1,38 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('GeneralCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('vicki')
6
+
7
+ test('SendCustomHexCommand forwards raw hex', () => {
8
+ expect(commandBuilder.build('SendCustomHexCommand', { command: '0412' })).toStrictEqual(
9
+ new BaseCommand('SendCustomHexCommand', '0412'),
10
+ )
11
+ })
12
+
13
+ test('SetKeepAlive encodes keepalive time', () => {
14
+ expect(commandBuilder.build('SetKeepAlive', { time: 5 })).toStrictEqual(new BaseCommand('SetKeepAlive', 0x02, '05'))
15
+ })
16
+
17
+ test('SetJoinRetryPeriod scales minutes before encoding', () => {
18
+ expect(commandBuilder.build('SetJoinRetryPeriod', { period: 10 })).toStrictEqual(
19
+ new BaseCommand('SetJoinRetryPeriod', 0x10, '78'),
20
+ )
21
+ })
22
+
23
+ test('SetUplinkType passes uplink type', () => {
24
+ expect(commandBuilder.build('SetUplinkType', { type: '01' })).toStrictEqual(
25
+ new BaseCommand('SetUplinkType', 0x11, '01'),
26
+ )
27
+ })
28
+
29
+ test('SetWatchDogParams encodes confirmed/unconfirmed uplinks', () => {
30
+ expect(commandBuilder.build('SetWatchDogParams', { confirmedUplinks: 2, unconfirmedUplinks: 3 })).toStrictEqual(
31
+ new BaseCommand('SetWatchDogParams', 0x1c, '02', '03'),
32
+ )
33
+ })
34
+
35
+ test('Invalid SendCustomHexCommand params throw validation error', () => {
36
+ expect(() => commandBuilder.build('SendCustomHexCommand', { command: 'ZZZ' })).toThrow(CustomError)
37
+ })
38
+ })
@@ -0,0 +1,28 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('HTDisplayLiteCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('ht_display_lite')
6
+
7
+ test('SetDisplayRefreshPeriod encodes period', () => {
8
+ expect(commandBuilder.build('SetDisplayRefreshPeriod', { period: 4 })).toStrictEqual(
9
+ new BaseCommand('SetDisplayRefreshPeriod', 0x33, '04'),
10
+ )
11
+ })
12
+
13
+ test('SetHumidityVisibility encodes toggle', () => {
14
+ expect(commandBuilder.build('SetHumidityVisibility', { state: 1 })).toStrictEqual(
15
+ new BaseCommand('SetHumidityVisibility', 0x42, '01'),
16
+ )
17
+ })
18
+
19
+ test('SetCurrentTemperatureVisibility encodes toggle', () => {
20
+ expect(commandBuilder.build('SetCurrentTemperatureVisibility', { state: 0 })).toStrictEqual(
21
+ new BaseCommand('SetCurrentTemperatureVisibility', 0x40, '00'),
22
+ )
23
+ })
24
+
25
+ test('Invalid SetDisplayRefreshPeriod throws validation error', () => {
26
+ expect(() => commandBuilder.build('SetDisplayRefreshPeriod', { period: 0 })).toThrow(CustomError)
27
+ })
28
+ })
@@ -0,0 +1,32 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('HTPirLiteCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('ht_pir_lite')
6
+
7
+ test('SetPIRSensorState encodes enabled flag', () => {
8
+ expect(commandBuilder.build('SetPIRSensorState', { state: 1 })).toStrictEqual(
9
+ new BaseCommand('SetPIRSensorState', 0x36, '01'),
10
+ )
11
+ })
12
+
13
+ test('SetPIRSensorSensitivity encodes sensitivity value', () => {
14
+ expect(commandBuilder.build('SetPIRSensorSensitivity', { sensitivity: 64 })).toStrictEqual(
15
+ new BaseCommand('SetPIRSensorSensitivity', 0x3e, '40'),
16
+ )
17
+ })
18
+
19
+ test('SetOccupancyTimeout encodes timeout into two bytes', () => {
20
+ expect(commandBuilder.build('SetOccupancyTimeout', { timeout: 120 })).toStrictEqual(
21
+ new BaseCommand('SetOccupancyTimeout', 0x38, '0078'),
22
+ )
23
+ })
24
+
25
+ test('RestartDevice emits restart command', () => {
26
+ expect(commandBuilder.build('RestartDevice')).toStrictEqual(new BaseCommand('RestartDevice', 0xa5))
27
+ })
28
+
29
+ test('Invalid SetPIRSensorState throws validation error', () => {
30
+ expect(() => commandBuilder.build('SetPIRSensorState', { state: 2 })).toThrow(CustomError)
31
+ })
32
+ })
@@ -0,0 +1,24 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('HTSensorCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('ht_sensor')
6
+
7
+ test('SetTemperatureCompensation encodes sign flag and compensation *10', () => {
8
+ expect(
9
+ commandBuilder.build('SetTemperatureCompensation', { negativeCompensation: true, compensation: 0.3 }),
10
+ ).toStrictEqual(new BaseCommand('SetTemperatureCompensation', 0x31, '01', '03'))
11
+ })
12
+
13
+ test('SetHumidityCompensation encodes sign flag and compensation', () => {
14
+ expect(
15
+ commandBuilder.build('SetHumidityCompensation', { negativeCompensation: false, compensation: 3 }),
16
+ ).toStrictEqual(new BaseCommand('SetHumidityCompensation', 0x33, '00', '03'))
17
+ })
18
+
19
+ test('Invalid SetTemperatureCompensation throws validation error', () => {
20
+ expect(() =>
21
+ commandBuilder.build('SetTemperatureCompensation', { negativeCompensation: true, compensation: -1 }),
22
+ ).toThrow(CustomError)
23
+ })
24
+ })
@@ -0,0 +1,16 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('MelissaCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('melissa_lorawan')
6
+
7
+ test('SetIrCodeRecording encodes time and position', () => {
8
+ expect(commandBuilder.build('SetIrCodeRecording', { time: 10, position: 2 })).toStrictEqual(
9
+ new BaseCommand('SetIrCodeRecording', 0x09, '0A', '02'),
10
+ )
11
+ })
12
+
13
+ test('Invalid SetIrCodeRecording throws validation error', () => {
14
+ expect(() => commandBuilder.build('SetIrCodeRecording', { time: -1, position: 1 })).toThrow(CustomError)
15
+ })
16
+ })
@@ -0,0 +1,68 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('MultiSensorCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('multisensor')
6
+
7
+ test('SetLightState encodes boolean to flag', () => {
8
+ expect(commandBuilder.build('SetLightState', { enabled: true })).toStrictEqual(
9
+ new BaseCommand('SetLightState', 0x1e, '01'),
10
+ )
11
+ })
12
+
13
+ test('SetHallState encodes boolean to flag', () => {
14
+ expect(commandBuilder.build('SetHallState', { enabled: false })).toStrictEqual(
15
+ new BaseCommand('SetHallState', 0x20, '00'),
16
+ )
17
+ })
18
+
19
+ test('SetHallBlindPeriod encodes period as 2 bytes', () => {
20
+ expect(commandBuilder.build('SetHallBlindPeriod', { period: 300 })).toStrictEqual(
21
+ new BaseCommand('SetHallBlindPeriod', 0x22, '012C'),
22
+ )
23
+ })
24
+
25
+ test('SetMicrophoneState encodes boolean to flag', () => {
26
+ expect(commandBuilder.build('SetMicrophoneState', { enabled: true })).toStrictEqual(
27
+ new BaseCommand('SetMicrophoneState', 0x24, '01'),
28
+ )
29
+ })
30
+
31
+ test('SetMicrophoneSamplingPeriod encodes period as 2 bytes', () => {
32
+ expect(commandBuilder.build('SetMicrophoneSamplingPeriod', { period: 120 })).toStrictEqual(
33
+ new BaseCommand('SetMicrophoneSamplingPeriod', 0x26, '0078'),
34
+ )
35
+ })
36
+
37
+ test('SetGasState encodes boolean to flag', () => {
38
+ expect(commandBuilder.build('SetGasState', { enabled: true })).toStrictEqual(
39
+ new BaseCommand('SetGasState', 0x28, '01'),
40
+ )
41
+ })
42
+
43
+ test('SetGasMeasurementPeriod encodes minutes', () => {
44
+ expect(commandBuilder.build('SetGasMeasurementPeriod', { minutes: 15 })).toStrictEqual(
45
+ new BaseCommand('SetGasMeasurementPeriod', 0x2a, '0F'),
46
+ )
47
+ })
48
+
49
+ test('SetPirState encodes boolean to flag', () => {
50
+ expect(commandBuilder.build('SetPirState', { enabled: true })).toStrictEqual(
51
+ new BaseCommand('SetPirState', 0x2c, '01'),
52
+ )
53
+ })
54
+
55
+ test('SetPirActiveReportingPeriod encodes time as 2 bytes', () => {
56
+ expect(commandBuilder.build('SetPirActiveReportingPeriod', { time: 45 })).toStrictEqual(
57
+ new BaseCommand('SetPirActiveReportingPeriod', 0x2e, '002D'),
58
+ )
59
+ })
60
+
61
+ test('Restart emits restart command', () => {
62
+ expect(commandBuilder.build('Restart')).toStrictEqual(new BaseCommand('Restart', 0xa5))
63
+ })
64
+
65
+ test('Invalid SetHallBlindPeriod throws validation error', () => {
66
+ expect(() => commandBuilder.build('SetHallBlindPeriod', { period: -1 })).toThrow(CustomError)
67
+ })
68
+ })
@@ -0,0 +1,16 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('OpenCloseSensorCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('open_close_sensor')
6
+
7
+ test('SetNotificationBlindTime encodes time', () => {
8
+ expect(commandBuilder.build('SetNotificationBlindTime', { time: 10 })).toStrictEqual(
9
+ new BaseCommand('SetNotificationBlindTime', 0x1e, '0A'),
10
+ )
11
+ })
12
+
13
+ test('Invalid SetNotificationBlindTime throws validation error', () => {
14
+ expect(() => commandBuilder.build('SetNotificationBlindTime', { time: -1 })).toThrow(CustomError)
15
+ })
16
+ })
@@ -0,0 +1,46 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('PIRCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('co2_display')
6
+
7
+ test('SetPIRSensorStatus encodes state', () => {
8
+ expect(commandBuilder.build('SetPIRSensorStatus', { state: 1 })).toStrictEqual(
9
+ new BaseCommand('SetPIRSensorStatus', 0x3c, '01'),
10
+ )
11
+ })
12
+
13
+ test('SetPIRSensorSensitivity encodes sensitivity', () => {
14
+ expect(commandBuilder.build('SetPIRSensorSensitivity', { sensitivity: 12 })).toStrictEqual(
15
+ new BaseCommand('SetPIRSensorSensitivity', 0x3e, '0C'),
16
+ )
17
+ })
18
+
19
+ test('SetPIRInitPeriod encodes time', () => {
20
+ expect(commandBuilder.build('SetPIRInitPeriod', { time: 5 })).toStrictEqual(
21
+ new BaseCommand('SetPIRInitPeriod', 0x46, '05'),
22
+ )
23
+ })
24
+
25
+ test('SetPIRMeasurementPeriod encodes time', () => {
26
+ expect(commandBuilder.build('SetPIRMeasurementPeriod', { time: 15 })).toStrictEqual(
27
+ new BaseCommand('SetPIRMeasurementPeriod', 0x48, '0F'),
28
+ )
29
+ })
30
+
31
+ test('SetPIRCheckPeriod encodes 2-byte time', () => {
32
+ expect(commandBuilder.build('SetPIRCheckPeriod', { time: 500 })).toStrictEqual(
33
+ new BaseCommand('SetPIRCheckPeriod', 0x4a, '01F4'),
34
+ )
35
+ })
36
+
37
+ test('SetPIRBlindPeriod encodes 2-byte time', () => {
38
+ expect(commandBuilder.build('SetPIRBlindPeriod', { time: 300 })).toStrictEqual(
39
+ new BaseCommand('SetPIRBlindPeriod', 0x4c, '012C'),
40
+ )
41
+ })
42
+
43
+ test('Invalid SetPIRSensorStatus throws validation error', () => {
44
+ expect(() => commandBuilder.build('SetPIRSensorStatus', { state: 2 })).toThrow(CustomError)
45
+ })
46
+ })
@@ -0,0 +1,76 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('Relay16Commands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('relay_16')
6
+
7
+ test('SetOverheatingThresholds encodes trigger and recovery', () => {
8
+ expect(commandBuilder.build('SetOverheatingThresholds', { trigger: 45, recovery: 60 })).toStrictEqual(
9
+ new BaseCommand('SetOverheatingThresholds', 0x1e, '2D', '3C'),
10
+ )
11
+ })
12
+
13
+ test('SetOverheatingThresholds matches doc example values', () => {
14
+ expect(commandBuilder.build('SetOverheatingThresholds', { trigger: 90, recovery: 60 })).toStrictEqual(
15
+ new BaseCommand('SetOverheatingThresholds', 0x1e, '5A', '3C'),
16
+ )
17
+ })
18
+
19
+ test('SetOvervoltageThresholds encodes trigger and recovery', () => {
20
+ expect(commandBuilder.build('SetOvervoltageThresholds', { trigger: 230, recovery: 150 })).toStrictEqual(
21
+ new BaseCommand('SetOvervoltageThresholds', 0x20, '00E6', '96'),
22
+ )
23
+ })
24
+
25
+ test('SetOvercurrentThreshold encodes current value', () => {
26
+ expect(commandBuilder.build('SetOvercurrentThreshold', { current: 12 })).toStrictEqual(
27
+ new BaseCommand('SetOvercurrentThreshold', 0x22, '0C'),
28
+ )
29
+ })
30
+
31
+ test('SetOverpowerThreshold encodes power value', () => {
32
+ expect(commandBuilder.build('SetOverpowerThreshold', { power: 1500 })).toStrictEqual(
33
+ new BaseCommand('SetOverpowerThreshold', 0x24, '05DC'),
34
+ )
35
+ })
36
+
37
+ test('SetAfterOverheatingProtectionRecovery encodes state flag', () => {
38
+ expect(commandBuilder.build('SetAfterOverheatingProtectionRecovery', { state: 1 })).toStrictEqual(
39
+ new BaseCommand('SetAfterOverheatingProtectionRecovery', 0x59, '01'),
40
+ )
41
+ })
42
+
43
+ test('SetLedIndicationMode encodes mode flag', () => {
44
+ expect(commandBuilder.build('SetLedIndicationMode', { mode: 1 })).toStrictEqual(
45
+ new BaseCommand('SetLedIndicationMode', 0x5b, '01'),
46
+ )
47
+ })
48
+
49
+ test('SetRelayRecoveryState encodes relay recovery state', () => {
50
+ expect(commandBuilder.build('SetRelayRecoveryState', { state: 2 })).toStrictEqual(
51
+ new BaseCommand('SetRelayRecoveryState', 0x5e, '02'),
52
+ )
53
+ })
54
+
55
+ test('SetRelayState maps boolean to relay flag', () => {
56
+ expect(commandBuilder.build('SetRelayState', { state: false })).toStrictEqual(
57
+ new BaseCommand('SetRelayState', 0xc1, '00'),
58
+ )
59
+ })
60
+
61
+ test('SetRelayTimerInMilliseconds encodes state and time', () => {
62
+ expect(commandBuilder.build('SetRelayTimerInMilliseconds', { state: 1, time: 1200 })).toStrictEqual(
63
+ new BaseCommand('SetRelayTimerInMilliseconds', 0x55, '01', '04B0'),
64
+ )
65
+ })
66
+
67
+ test('SetRelayTimerInSeconds encodes state and time', () => {
68
+ expect(commandBuilder.build('SetRelayTimerInSeconds', { state: 0, time: 90 })).toStrictEqual(
69
+ new BaseCommand('SetRelayTimerInSeconds', 0x57, '00', '005A'),
70
+ )
71
+ })
72
+
73
+ test('Invalid parameter triggers validation error', () => {
74
+ expect(() => commandBuilder.build('SetOverpowerThreshold', { power: 4000 })).toThrow(CustomError)
75
+ })
76
+ })
@@ -0,0 +1,52 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('Relay16DryCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('relay_16_dry')
6
+
7
+ test('SetRelayState maps boolean to relay flag', () => {
8
+ expect(commandBuilder.build('SetRelayState', { state: true })).toStrictEqual(
9
+ new BaseCommand('SetRelayState', 0xc1, '01'),
10
+ )
11
+ })
12
+
13
+ test('SetRelayTimerInMilliseconds encodes state and time', () => {
14
+ expect(commandBuilder.build('SetRelayTimerInMilliseconds', { state: 0, time: 500 })).toStrictEqual(
15
+ new BaseCommand('SetRelayTimerInMilliseconds', 0x55, '00', '01F4'),
16
+ )
17
+ })
18
+
19
+ test('SetRelayTimerInSeconds encodes state and time', () => {
20
+ expect(commandBuilder.build('SetRelayTimerInSeconds', { state: 1, time: 3 })).toStrictEqual(
21
+ new BaseCommand('SetRelayTimerInSeconds', 0x57, '01', '0003'),
22
+ )
23
+ })
24
+
25
+ test('SetOverheatingThresholds encodes trigger and recovery', () => {
26
+ expect(commandBuilder.build('SetOverheatingThresholds', { trigger: 40, recovery: 60 })).toStrictEqual(
27
+ new BaseCommand('SetOverheatingThresholds', 0x1e, '28', '3C'),
28
+ )
29
+ })
30
+
31
+ test('SetAfterOverheatingProtectionRecovery encodes state', () => {
32
+ expect(commandBuilder.build('SetAfterOverheatingProtectionRecovery', { state: 1 })).toStrictEqual(
33
+ new BaseCommand('SetAfterOverheatingProtectionRecovery', 0x59, '01'),
34
+ )
35
+ })
36
+
37
+ test('SetLedIndicationMode encodes mode', () => {
38
+ expect(commandBuilder.build('SetLedIndicationMode', { mode: 1 })).toStrictEqual(
39
+ new BaseCommand('SetLedIndicationMode', 0x5b, '01'),
40
+ )
41
+ })
42
+
43
+ test('SetRelayRecoveryState encodes state', () => {
44
+ expect(commandBuilder.build('SetRelayRecoveryState', { state: 2 })).toStrictEqual(
45
+ new BaseCommand('SetRelayRecoveryState', 0x5e, '02'),
46
+ )
47
+ })
48
+
49
+ test('Invalid SetRelayTimerInSeconds throws validation error', () => {
50
+ expect(() => commandBuilder.build('SetRelayTimerInSeconds', { state: 0, time: 70000 })).toThrow(CustomError)
51
+ })
52
+ })
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '@/encoders'
2
+ import { SetAqiLedCommands } from '@/encoders/SetAqiLedCommands'
3
+
4
+ describe('SetAqiLedCommands payload encoder', () => {
5
+ test('SetAqiLed encodes behaviors and durations', () => {
6
+ const command = new SetAqiLedCommands({
7
+ redBehavior: 1,
8
+ redDuration: 20,
9
+ greenBehavior: 2,
10
+ greenDuration: 30,
11
+ blueBehavior: 3,
12
+ blueDuration: 40,
13
+ commandNumber: '05',
14
+ })
15
+ expect(command).toBeInstanceOf(BaseCommand)
16
+ expect(command.toHex()).toBe('05224364')
17
+ })
18
+ })
@@ -0,0 +1,34 @@
1
+ import { BaseCommand, CommandBuilder } from '@/encoders'
2
+ import { CustomError } from '@/utils'
3
+
4
+ describe('TFloodCommands payload encoder', () => {
5
+ const commandBuilder = new CommandBuilder('t_flood')
6
+
7
+ test('SetFloodAlarmTime encodes alarm time', () => {
8
+ expect(commandBuilder.build('SetFloodAlarmTime', { time: 10 })).toStrictEqual(
9
+ new BaseCommand('SetFloodAlarmTime', 0x04, 'a'),
10
+ )
11
+ })
12
+
13
+ test('SetKeepAlive encodes keepalive seconds as 2 bytes', () => {
14
+ expect(commandBuilder.build('SetKeepAlive', { time: 120 })).toStrictEqual(
15
+ new BaseCommand('SetKeepAlive', 0x05, '0078'),
16
+ )
17
+ })
18
+
19
+ test('SetFloodEventSendTime encodes send time', () => {
20
+ expect(commandBuilder.build('SetFloodEventSendTime', { time: 30 })).toStrictEqual(
21
+ new BaseCommand('SetFloodEventSendTime', 0x08, '1e'),
22
+ )
23
+ })
24
+
25
+ test('SetFloodEventUplinkType encodes uplink type', () => {
26
+ expect(commandBuilder.build('SetFloodEventUplinkType', { type: '01' })).toStrictEqual(
27
+ new BaseCommand('SetFloodEventUplinkType', 0x13, '01'),
28
+ )
29
+ })
30
+
31
+ test('Invalid SetFloodAlarmTime throws validation error', () => {
32
+ expect(() => commandBuilder.build('SetFloodAlarmTime', { time: -1 })).toThrow(CustomError)
33
+ })
34
+ })