mclimate-payload-helper 1.2.7 → 1.2.8
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/dist/decoders/commandsReadingHelper.d.ts.map +1 -1
- package/dist/decoders/commandsReadingHelper.js +36 -0
- package/dist/decoders/commandsReadingHelper.js.map +1 -1
- package/dist/decoders/payloadParsers/co2PirLitePayloadParser.d.ts.map +1 -1
- package/dist/decoders/payloadParsers/co2PirLitePayloadParser.js +25 -23
- package/dist/decoders/payloadParsers/co2PirLitePayloadParser.js.map +1 -1
- package/dist/decoders/payloadParsers/htPirLitePayloadParser.d.ts.map +1 -1
- package/dist/decoders/payloadParsers/htPirLitePayloadParser.js +20 -20
- package/dist/decoders/payloadParsers/htPirLitePayloadParser.js.map +1 -1
- package/dist/encoders/Co2DisplayCommonCommands.d.ts +4 -0
- package/dist/encoders/Co2DisplayCommonCommands.d.ts.map +1 -1
- package/dist/encoders/Co2DisplayCommonCommands.js +38 -0
- package/dist/encoders/Co2DisplayCommonCommands.js.map +1 -1
- package/dist/encoders/Co2PirLiteCommands.d.ts +6 -2
- package/dist/encoders/Co2PirLiteCommands.d.ts.map +1 -1
- package/dist/encoders/Co2PirLiteCommands.js +66 -13
- package/dist/encoders/Co2PirLiteCommands.js.map +1 -1
- package/dist/encoders/HTPirLiteCommands.d.ts +6 -2
- package/dist/encoders/HTPirLiteCommands.d.ts.map +1 -1
- package/dist/encoders/HTPirLiteCommands.js +67 -12
- package/dist/encoders/HTPirLiteCommands.js.map +1 -1
- package/dist/encoders/types/schemas.d.ts +80 -170
- package/dist/encoders/types/schemas.d.ts.map +1 -1
- package/dist/encoders/types/schemas.js +29 -7
- package/dist/encoders/types/schemas.js.map +1 -1
- package/dist/test/payloadDecoders.test.js +26 -21
- package/dist/test/payloadDecoders.test.js.map +1 -1
- package/dist/test/payloadEncoders.test.js +8 -14
- package/dist/test/payloadEncoders.test.js.map +1 -1
- package/package.json +1 -1
- package/src/decoders/commandsReadingHelper.ts +34 -0
- package/src/decoders/payloadParsers/co2PirLitePayloadParser.ts +28 -23
- package/src/decoders/payloadParsers/htPirLitePayloadParser.ts +22 -20
- package/src/encoders/Co2PirLiteCommands.ts +66 -14
- package/src/encoders/HTPirLiteCommands.ts +67 -13
- package/src/encoders/types/schemas.ts +50 -12
- package/src/test/payloadDecoders.test.ts +26 -26
- package/src/test/payloadEncoders.test.ts +12 -22
- package/dist/encoders/FanCoilThermostat.d.ts +0 -61
- package/dist/encoders/FanCoilThermostat.d.ts.map +0 -1
- package/dist/encoders/FanCoilThermostat.js +0 -719
- package/dist/encoders/FanCoilThermostat.js.map +0 -1
- package/dist/encoders/SetAqiLed.d.ts +0 -6
- package/dist/encoders/SetAqiLed.d.ts.map +0 -1
- package/dist/encoders/SetAqiLed.js +0 -46
- package/dist/encoders/SetAqiLed.js.map +0 -1
- package/dist/encoders/types/enumValidation.d.ts +0 -6
- package/dist/encoders/types/enumValidation.d.ts.map +0 -1
- package/dist/encoders/types/enumValidation.js +0 -50
- package/dist/encoders/types/enumValidation.js.map +0 -1
- package/dist/encoders/types/schemaValidatedEnums.d.ts +0 -40
- package/dist/encoders/types/schemaValidatedEnums.d.ts.map +0 -1
- package/dist/encoders/types/schemaValidatedEnums.js +0 -181
- package/dist/encoders/types/schemaValidatedEnums.js.map +0 -1
- package/dist/types/deviceTypes.d.ts +0 -19
- package/dist/types/deviceTypes.d.ts.map +0 -1
- package/dist/types/deviceTypes.js +0 -23
- package/dist/types/deviceTypes.js.map +0 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -18
- package/dist/types/index.js.map +0 -1
- package/dist/types/types.d.ts +0 -13
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types/types.js +0 -9
- package/dist/types/types.js.map +0 -1
- package/dist/validation.d.ts +0 -3
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -8
- package/dist/validation.js.map +0 -1
package/package.json
CHANGED
|
@@ -1162,6 +1162,23 @@ export const commandsReadingHelper = (hexData: string, payloadLength: number, de
|
|
|
1162
1162
|
}
|
|
1163
1163
|
}
|
|
1164
1164
|
break
|
|
1165
|
+
case '37':
|
|
1166
|
+
{
|
|
1167
|
+
try {
|
|
1168
|
+
command_len = 1
|
|
1169
|
+
const data = { pirSensorState: parseInt(commands[i + 1], 16) }
|
|
1170
|
+
Object.assign(resultToPass, { ...resultToPass }, { ...data })
|
|
1171
|
+
} catch (e) {
|
|
1172
|
+
throw new CustomError({
|
|
1173
|
+
message: `Failed to process command '37'`,
|
|
1174
|
+
hexData,
|
|
1175
|
+
command,
|
|
1176
|
+
deviceType,
|
|
1177
|
+
originalError: e as Error,
|
|
1178
|
+
})
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
break
|
|
1165
1182
|
case '38':
|
|
1166
1183
|
{
|
|
1167
1184
|
try {
|
|
@@ -1179,6 +1196,23 @@ export const commandsReadingHelper = (hexData: string, payloadLength: number, de
|
|
|
1179
1196
|
}
|
|
1180
1197
|
}
|
|
1181
1198
|
break
|
|
1199
|
+
case '39':
|
|
1200
|
+
{
|
|
1201
|
+
try {
|
|
1202
|
+
command_len = 2
|
|
1203
|
+
const data = { occupancyTimeout: (parseInt(commands[i + 1], 16) << 8) | parseInt(commands[i + 2], 16)}
|
|
1204
|
+
Object.assign(resultToPass, { ...resultToPass }, { ...data })
|
|
1205
|
+
} catch (e) {
|
|
1206
|
+
throw new CustomError({
|
|
1207
|
+
message: `Failed to process command '39'`,
|
|
1208
|
+
hexData,
|
|
1209
|
+
command,
|
|
1210
|
+
deviceType,
|
|
1211
|
+
originalError: e as Error,
|
|
1212
|
+
})
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
break
|
|
1182
1216
|
case '3a':
|
|
1183
1217
|
{
|
|
1184
1218
|
try {
|
|
@@ -8,6 +8,7 @@ interface CO2PirLiteData {
|
|
|
8
8
|
relativeHumidity?: number
|
|
9
9
|
batteryVoltage?: number
|
|
10
10
|
CO2?: number
|
|
11
|
+
pirTriggerCount?: number
|
|
11
12
|
pir?: boolean
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -17,33 +18,37 @@ export const co2PirLitePayloadParser = (hexData: string) => {
|
|
|
17
18
|
try {
|
|
18
19
|
const handleKeepAliveData = (bytes: number[]) => {
|
|
19
20
|
const keepaliveData: CO2PirLiteData = {}
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
|
|
22
|
+
// Byte 1 bit 2: PIR flag
|
|
23
|
+
keepaliveData.pir = ((bytes[1] & 0x04) >> 2) === 1
|
|
24
|
+
|
|
25
|
+
// Byte 1 (bits 1:0) and Byte 2: Internal temperature sensor data
|
|
26
|
+
// Formula: t[°C] = (T[9:0] - 400) / 10
|
|
27
|
+
// Extract bits 1:0 from byte 1 for the higher bits (bits 9:8)
|
|
28
|
+
const tempHighBits = (bytes[1] & 0x03) << 8
|
|
29
|
+
// Use all bits from byte 2 for the lower bits (bits 7:0)
|
|
30
|
+
const tempLowBits = bytes[2]
|
|
31
|
+
// Combine to get the full 10-bit temperature value
|
|
32
|
+
const tempValue = tempHighBits | tempLowBits
|
|
33
|
+
keepaliveData.sensorTemperature = Number(((tempValue - 400) / 10).toFixed(2))
|
|
26
34
|
|
|
27
35
|
// Byte 3: Relative Humidity data
|
|
28
|
-
// Formula: RH[%] = (XX*100)/256
|
|
36
|
+
// Formula: RH[%] = (XX * 100) / 256
|
|
29
37
|
keepaliveData.relativeHumidity = Number(((bytes[3] * 100) / 256).toFixed(2))
|
|
30
38
|
|
|
31
|
-
//
|
|
32
|
-
// Battery voltage [mV]
|
|
33
|
-
|
|
34
|
-
const batteryLsb = bytes[5] // bits 7:0
|
|
35
|
-
keepaliveData.batteryVoltage = Number((((batteryMsb << 8) | batteryLsb) / 1000).toFixed(2))
|
|
39
|
+
// Byte 4: Device battery voltage data
|
|
40
|
+
// Battery voltage [mV] = ((XX * 2200) / 255) + 1600
|
|
41
|
+
keepaliveData.batteryVoltage = Number(((((bytes[4] * 2200) / 255) + 1600) / 1000).toFixed(2))
|
|
36
42
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
// Bytes 5-6: CO2 value in ppm
|
|
44
|
+
// Byte 5: CO2 value lower bits [7:0]
|
|
45
|
+
// Byte 6 bits 7:3: CO2 value higher bits [12:8]
|
|
46
|
+
const co2LowBits = bytes[5]
|
|
47
|
+
const co2HighBits = ((bytes[6] & 0xF8) >> 3) << 8 // Mask upper 5 bits, shift right by 3 to get bits in position, then shift left by 8
|
|
48
|
+
keepaliveData.CO2 = co2HighBits | co2LowBits
|
|
41
49
|
|
|
42
|
-
// Byte
|
|
43
|
-
|
|
44
|
-
// 1 - Motion detected
|
|
45
|
-
const pirValue = bytes[8] & 0x01 // Extract only the last bit
|
|
46
|
-
keepaliveData.pir = pirValue === 1
|
|
50
|
+
// Byte 7: PIR trigger count
|
|
51
|
+
keepaliveData.pirTriggerCount = bytes[7]
|
|
47
52
|
Object.assign(deviceData, { ...deviceData }, { ...keepaliveData })
|
|
48
53
|
}
|
|
49
54
|
|
|
@@ -52,7 +57,7 @@ export const co2PirLitePayloadParser = (hexData: string) => {
|
|
|
52
57
|
if (!byteArray) return
|
|
53
58
|
|
|
54
59
|
// Route the message based on the command byte
|
|
55
|
-
if (byteArray[0] ==
|
|
60
|
+
if (byteArray[0] == 81) {
|
|
56
61
|
// This is a keepalive message
|
|
57
62
|
handleKeepAliveData(byteArray)
|
|
58
63
|
} else {
|
|
@@ -69,7 +74,7 @@ export const co2PirLitePayloadParser = (hexData: string) => {
|
|
|
69
74
|
// Handle the remaining keepalive data if present
|
|
70
75
|
if (shouldKeepAlive) {
|
|
71
76
|
// Extract the last 9 bytes which contain keepalive data for CO2-PIR-Lite
|
|
72
|
-
const keepaliveData = hexData.slice(-
|
|
77
|
+
const keepaliveData = hexData.slice(-16) // 8 bytes = 16 hex chars
|
|
73
78
|
const dataToPass = byteArrayParser(keepaliveData)
|
|
74
79
|
if (!dataToPass) return
|
|
75
80
|
handleKeepAliveData(dataToPass)
|
|
@@ -7,6 +7,7 @@ interface HTPirLiteData {
|
|
|
7
7
|
sensorTemperature?: number
|
|
8
8
|
relativeHumidity?: number
|
|
9
9
|
batteryVoltage?: number
|
|
10
|
+
pirTriggerCount?: number
|
|
10
11
|
pir?: boolean
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -17,28 +18,29 @@ export const htPirLitePayloadParser = (hexData: string) => {
|
|
|
17
18
|
const handleKeepAliveData = (bytes: number[]) => {
|
|
18
19
|
const keepaliveData: HTPirLiteData = {}
|
|
19
20
|
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
// Byte 1 bit 2: Occupied flag
|
|
22
|
+
keepaliveData.pir = ((bytes[1] & 0x04) >> 2) === 1
|
|
23
|
+
|
|
24
|
+
// Byte 1 (bits 1:0) and Byte 2: Internal temperature sensor data
|
|
25
|
+
// Formula: t[°C] = (T[9:0] - 400) / 10
|
|
26
|
+
// Extract bits 1:0 from byte 1 for the higher bits (bits 9:8)
|
|
27
|
+
const tempHighBits = (bytes[1] & 0x03) << 8
|
|
28
|
+
// Use all bits from byte 2 for the lower bits (bits 7:0)
|
|
29
|
+
const tempLowBits = bytes[2]
|
|
30
|
+
// Combine to get the full 10-bit temperature value
|
|
31
|
+
const tempValue = tempHighBits | tempLowBits
|
|
32
|
+
keepaliveData.sensorTemperature = Number(((tempValue - 400) / 10).toFixed(2))
|
|
26
33
|
|
|
27
34
|
// Byte 3: Relative Humidity data
|
|
28
|
-
// Formula: RH[%] = (XX*100)/256
|
|
35
|
+
// Formula: RH[%] = (XX * 100) / 256
|
|
29
36
|
keepaliveData.relativeHumidity = Number(((bytes[3] * 100) / 256).toFixed(2))
|
|
30
37
|
|
|
31
|
-
//
|
|
32
|
-
// Battery voltage [mV]
|
|
33
|
-
|
|
34
|
-
const batteryLsb = bytes[5] // bits 7:0
|
|
35
|
-
keepaliveData.batteryVoltage = Number((((batteryMsb << 8) | batteryLsb) / 1000).toFixed(2))
|
|
38
|
+
// Byte 4: Device battery voltage data
|
|
39
|
+
// Battery voltage [mV] = ((XX * 2200) / 255) + 1600
|
|
40
|
+
keepaliveData.batteryVoltage = Number(((((bytes[4] * 2200) / 255) + 1600) / 1000).toFixed(2))
|
|
36
41
|
|
|
37
|
-
// Byte
|
|
38
|
-
|
|
39
|
-
// 1 - Motion detected
|
|
40
|
-
const pirValue = bytes[6] & 0x01 // Extract only the last bit
|
|
41
|
-
keepaliveData.pir = pirValue === 1
|
|
42
|
+
// Byte 5: PIR trigger count
|
|
43
|
+
keepaliveData.pirTriggerCount = bytes[5]
|
|
42
44
|
|
|
43
45
|
Object.assign(deviceData, { ...deviceData }, { ...keepaliveData })
|
|
44
46
|
}
|
|
@@ -48,7 +50,7 @@ export const htPirLitePayloadParser = (hexData: string) => {
|
|
|
48
50
|
if (!byteArray) return
|
|
49
51
|
|
|
50
52
|
// Route the message based on the command byte
|
|
51
|
-
if (byteArray[0] ==
|
|
53
|
+
if (byteArray[0] == 81) {
|
|
52
54
|
// This is a keepalive message
|
|
53
55
|
handleKeepAliveData(byteArray)
|
|
54
56
|
} else {
|
|
@@ -64,8 +66,8 @@ export const htPirLitePayloadParser = (hexData: string) => {
|
|
|
64
66
|
|
|
65
67
|
// Handle the remaining keepalive data if present
|
|
66
68
|
if (shouldKeepAlive) {
|
|
67
|
-
// Extract the last
|
|
68
|
-
const keepaliveData = hexData.slice(-
|
|
69
|
+
// Extract the last 6 bytes which contain keepalive data for HT-PIR-Lite
|
|
70
|
+
const keepaliveData = hexData.slice(-12) // 6 bytes = 12 hex chars
|
|
69
71
|
const dataToPass = byteArrayParser(keepaliveData)
|
|
70
72
|
if (!dataToPass) return
|
|
71
73
|
handleKeepAliveData(dataToPass)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GeneralCommands,
|
|
1
|
+
import { GeneralCommands, CO2SensorCommands } from '@/encoders'
|
|
2
2
|
import { applyMixins, delMethods } from '@/utils'
|
|
3
3
|
import { Co2PirLiteCommandTypes, DeviceCommandSchemas } from '@/encoders/types'
|
|
4
4
|
import { BaseCommand } from '@/encoders'
|
|
@@ -7,30 +7,84 @@ import { CustomError } from '@/utils'
|
|
|
7
7
|
import { decToHex } from '@/utils'
|
|
8
8
|
|
|
9
9
|
export class Co2PirLiteCommands extends GeneralCommands {
|
|
10
|
-
|
|
10
|
+
static setPIRSensorState(params: Co2PirLiteCommandTypes.SetPIRSensorStateParams) {
|
|
11
11
|
try {
|
|
12
|
-
DeviceCommandSchemas.Co2PirLiteCommandSchemas.
|
|
13
|
-
const {
|
|
14
|
-
return new BaseCommand('
|
|
12
|
+
DeviceCommandSchemas.Co2PirLiteCommandSchemas.setPIRSensorState.parse(params)
|
|
13
|
+
const { state } = params
|
|
14
|
+
return new BaseCommand('SetPIRSensorState', 0x36, decToHex(state))
|
|
15
15
|
} catch (e) {
|
|
16
16
|
if (e instanceof ZodError) {
|
|
17
17
|
throw new CustomError({
|
|
18
|
-
message: 'Zod validation error during
|
|
19
|
-
command: '
|
|
18
|
+
message: 'Zod validation error during SetPIRSensorState execution',
|
|
19
|
+
command: 'SetPIRSensorState',
|
|
20
20
|
originalError: e,
|
|
21
21
|
})
|
|
22
22
|
} else {
|
|
23
23
|
throw new CustomError({
|
|
24
|
-
message: 'Error during
|
|
25
|
-
command: '
|
|
24
|
+
message: 'Error during SetPIRSensorState execution',
|
|
25
|
+
command: 'SetPIRSensorState',
|
|
26
|
+
originalError: e as Error,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
static getPIRSensorState() {
|
|
32
|
+
return new BaseCommand('GetPIRSensorState', 0x37)
|
|
33
|
+
}
|
|
34
|
+
static setPIRSensorSensitivity(params: Co2PirLiteCommandTypes.SetPIRSensorSensitivityParams) {
|
|
35
|
+
try {
|
|
36
|
+
DeviceCommandSchemas.Co2PirLiteCommandSchemas.setPIRSensorSensitivity.parse(params)
|
|
37
|
+
const { sensitivity } = params
|
|
38
|
+
return new BaseCommand('SetPIRSensorSensitivity', 0x3e, decToHex(sensitivity))
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (e instanceof ZodError) {
|
|
41
|
+
throw new CustomError({
|
|
42
|
+
message: 'Zod validation error during SetPIRSensorSensitivity execution',
|
|
43
|
+
command: 'SetPIRSensorSensitivity',
|
|
44
|
+
originalError: e,
|
|
45
|
+
})
|
|
46
|
+
} else {
|
|
47
|
+
throw new CustomError({
|
|
48
|
+
message: 'Error during SetPIRSensorSensitivity execution',
|
|
49
|
+
command: 'SetPIRSensorSensitivity',
|
|
50
|
+
originalError: e as Error,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static getPIRSensorSensitivity() {
|
|
57
|
+
return new BaseCommand('GetPIRSensorSensitivity', 0x3f)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static setOccupancyTimeout(params: Co2PirLiteCommandTypes.SetOccupancyTimeoutParams) {
|
|
61
|
+
try {
|
|
62
|
+
DeviceCommandSchemas.Co2PirLiteCommandSchemas.setOccupancyTimeout.parse(params)
|
|
63
|
+
const { timeout } = params
|
|
64
|
+
// Convert timeout to two bytes (high byte and low byte)
|
|
65
|
+
const highByte = (timeout >> 8) & 0xFF
|
|
66
|
+
const lowByte = timeout & 0xFF
|
|
67
|
+
|
|
68
|
+
return new BaseCommand('SetOccupancyTimeout', 0x38, decToHex(highByte) + decToHex(lowByte))
|
|
69
|
+
} catch (e) {
|
|
70
|
+
if (e instanceof ZodError) {
|
|
71
|
+
throw new CustomError({
|
|
72
|
+
message: 'Zod validation error during SetOccupancyTimeout execution',
|
|
73
|
+
command: 'SetOccupancyTimeout',
|
|
74
|
+
originalError: e,
|
|
75
|
+
})
|
|
76
|
+
} else {
|
|
77
|
+
throw new CustomError({
|
|
78
|
+
message: 'Error during SetOccupancyTimeout execution',
|
|
79
|
+
command: 'SetOccupancyTimeout',
|
|
26
80
|
originalError: e as Error,
|
|
27
81
|
})
|
|
28
82
|
}
|
|
29
83
|
}
|
|
30
84
|
}
|
|
31
85
|
|
|
32
|
-
static
|
|
33
|
-
return new BaseCommand('
|
|
86
|
+
static getOccupancyTimeout() {
|
|
87
|
+
return new BaseCommand('GetOccupancyTimeout', 0x39)
|
|
34
88
|
}
|
|
35
89
|
|
|
36
90
|
static restartDevice() {
|
|
@@ -38,11 +92,9 @@ export class Co2PirLiteCommands extends GeneralCommands {
|
|
|
38
92
|
}
|
|
39
93
|
}
|
|
40
94
|
|
|
41
|
-
applyMixins(Co2PirLiteCommands, [GeneralCommands,
|
|
95
|
+
applyMixins(Co2PirLiteCommands, [GeneralCommands, CO2SensorCommands])
|
|
42
96
|
|
|
43
97
|
delMethods(Co2PirLiteCommands, [
|
|
44
|
-
'setPIRInitPeriod',
|
|
45
|
-
'getPIRInitPeriod',
|
|
46
98
|
'setNotifyPeriod',
|
|
47
99
|
'getNotifyPeriod',
|
|
48
100
|
'setBuzzerNotification',
|
|
@@ -1,36 +1,90 @@
|
|
|
1
1
|
import { GeneralCommands, PIRCommands } from '@/encoders'
|
|
2
2
|
import { applyMixins, delMethods } from '@/utils'
|
|
3
|
-
import { HTPirLiteCommandTypes, DeviceCommandSchemas } from '@/encoders/types'
|
|
3
|
+
import { HTPirLiteCommandTypes, DeviceCommandSchemas, PIRCommandTypes } from '@/encoders/types'
|
|
4
4
|
import { BaseCommand } from '@/encoders'
|
|
5
5
|
import { ZodError } from 'zod'
|
|
6
6
|
import { CustomError } from '@/utils'
|
|
7
7
|
import { decToHex } from '@/utils'
|
|
8
8
|
|
|
9
9
|
export class HTPirLiteCommands extends GeneralCommands {
|
|
10
|
-
|
|
10
|
+
static setPIRSensorState(params: HTPirLiteCommandTypes.SetPIRSensorStateParams) {
|
|
11
11
|
try {
|
|
12
|
-
DeviceCommandSchemas.HTPirLiteCommandSchemas.
|
|
13
|
-
const {
|
|
14
|
-
return new BaseCommand('
|
|
12
|
+
DeviceCommandSchemas.HTPirLiteCommandSchemas.setPIRSensorState.parse(params)
|
|
13
|
+
const { state } = params
|
|
14
|
+
return new BaseCommand('SetPIRSensorState', 0x36, decToHex(state))
|
|
15
15
|
} catch (e) {
|
|
16
16
|
if (e instanceof ZodError) {
|
|
17
17
|
throw new CustomError({
|
|
18
|
-
message: 'Zod validation error during
|
|
19
|
-
command: '
|
|
18
|
+
message: 'Zod validation error during SetPIRSensorState execution',
|
|
19
|
+
command: 'SetPIRSensorState',
|
|
20
20
|
originalError: e,
|
|
21
21
|
})
|
|
22
22
|
} else {
|
|
23
23
|
throw new CustomError({
|
|
24
|
-
message: 'Error during
|
|
25
|
-
command: '
|
|
24
|
+
message: 'Error during SetPIRSensorState execution',
|
|
25
|
+
command: 'SetPIRSensorState',
|
|
26
|
+
originalError: e as Error,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
static getPIRSensorState() {
|
|
32
|
+
return new BaseCommand('GetPIRSensorState', 0x37)
|
|
33
|
+
}
|
|
34
|
+
static setPIRSensorSensitivity(params: HTPirLiteCommandTypes.SetPIRSensorSensitivityParams) {
|
|
35
|
+
try {
|
|
36
|
+
DeviceCommandSchemas.HTPirLiteCommandSchemas.setPIRSensorSensitivity.parse(params)
|
|
37
|
+
const { sensitivity } = params
|
|
38
|
+
return new BaseCommand('SetPIRSensorSensitivity', 0x3e, decToHex(sensitivity))
|
|
39
|
+
} catch (e) {
|
|
40
|
+
if (e instanceof ZodError) {
|
|
41
|
+
throw new CustomError({
|
|
42
|
+
message: 'Zod validation error during SetPIRSensorSensitivity execution',
|
|
43
|
+
command: 'SetPIRSensorSensitivity',
|
|
44
|
+
originalError: e,
|
|
45
|
+
})
|
|
46
|
+
} else {
|
|
47
|
+
throw new CustomError({
|
|
48
|
+
message: 'Error during SetPIRSensorSensitivity execution',
|
|
49
|
+
command: 'SetPIRSensorSensitivity',
|
|
50
|
+
originalError: e as Error,
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static getPIRSensorSensitivity() {
|
|
57
|
+
return new BaseCommand('GetPIRSensorSensitivity', 0x3f)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static setOccupancyTimeout(params: HTPirLiteCommandTypes.SetOccupancyTimeoutParams) {
|
|
61
|
+
try {
|
|
62
|
+
DeviceCommandSchemas.HTPirLiteCommandSchemas.setOccupancyTimeout.parse(params)
|
|
63
|
+
const { timeout } = params
|
|
64
|
+
// Convert timeout to two bytes (high byte and low byte)
|
|
65
|
+
const highByte = (timeout >> 8) & 0xFF
|
|
66
|
+
const lowByte = timeout & 0xFF
|
|
67
|
+
|
|
68
|
+
return new BaseCommand('SetOccupancyTimeout', 0x38, decToHex(highByte) + decToHex(lowByte))
|
|
69
|
+
} catch (e) {
|
|
70
|
+
if (e instanceof ZodError) {
|
|
71
|
+
throw new CustomError({
|
|
72
|
+
message: 'Zod validation error during SetOccupancyTimeout execution',
|
|
73
|
+
command: 'SetOccupancyTimeout',
|
|
74
|
+
originalError: e,
|
|
75
|
+
})
|
|
76
|
+
} else {
|
|
77
|
+
throw new CustomError({
|
|
78
|
+
message: 'Error during SetOccupancyTimeout execution',
|
|
79
|
+
command: 'SetOccupancyTimeout',
|
|
26
80
|
originalError: e as Error,
|
|
27
81
|
})
|
|
28
82
|
}
|
|
29
83
|
}
|
|
30
84
|
}
|
|
31
85
|
|
|
32
|
-
static
|
|
33
|
-
return new BaseCommand('
|
|
86
|
+
static getOccupancyTimeout() {
|
|
87
|
+
return new BaseCommand('GetOccupancyTimeout', 0x39)
|
|
34
88
|
}
|
|
35
89
|
|
|
36
90
|
static restartDevice() {
|
|
@@ -38,6 +92,6 @@ export class HTPirLiteCommands extends GeneralCommands {
|
|
|
38
92
|
}
|
|
39
93
|
}
|
|
40
94
|
|
|
41
|
-
applyMixins(HTPirLiteCommands, [GeneralCommands
|
|
95
|
+
applyMixins(HTPirLiteCommands, [GeneralCommands])
|
|
42
96
|
|
|
43
|
-
delMethods(HTPirLiteCommands, [
|
|
97
|
+
delMethods(HTPirLiteCommands, [])
|
|
@@ -193,6 +193,20 @@ export const ButtonEnums = {
|
|
|
193
193
|
} satisfies NumberEnum<1 | 2 | 3>,
|
|
194
194
|
} as const
|
|
195
195
|
|
|
196
|
+
export const HTPirLiteEnums = {
|
|
197
|
+
setPIRSensorState: {
|
|
198
|
+
0: 'Disabled',
|
|
199
|
+
1: 'Enabled',
|
|
200
|
+
} satisfies NumberEnum<0 | 1>,
|
|
201
|
+
} as const
|
|
202
|
+
|
|
203
|
+
export const Co2PirLiteEnums = {
|
|
204
|
+
setPIRSensorState: {
|
|
205
|
+
0: 'Disabled',
|
|
206
|
+
1: 'Enabled',
|
|
207
|
+
} satisfies NumberEnum<0 | 1>,
|
|
208
|
+
} as const
|
|
209
|
+
|
|
196
210
|
/* ---------------------------------------GENERAL COMMANDS--------------------------------------- */
|
|
197
211
|
|
|
198
212
|
const GeneralCommandSchemas = {
|
|
@@ -457,7 +471,7 @@ const VickiCommandSchemas = {
|
|
|
457
471
|
eventIndex: z.number().int().min(0).max(19),
|
|
458
472
|
startHour: z.number().int().min(0).max(23),
|
|
459
473
|
startMinute: z.number().int().min(0).max(59),
|
|
460
|
-
targetTemperature: z.number().min(0
|
|
474
|
+
targetTemperature: z.number().min(5.0).max(30.0).multipleOf(0.1),
|
|
461
475
|
daysActive: z.object({
|
|
462
476
|
monday: z.boolean(),
|
|
463
477
|
tuesday: z.boolean(),
|
|
@@ -1325,28 +1339,52 @@ export namespace ButtonCommandTypes {
|
|
|
1325
1339
|
/* --------------------------------------- HT PIR LITE COMMANDS --------------------------------------- */
|
|
1326
1340
|
const HTPirLiteCommandSchemas = {
|
|
1327
1341
|
...GeneralCommandSchemas,
|
|
1328
|
-
...PIRCommandSchemas,
|
|
1329
1342
|
setUplinkSendingOnButtonPress: z.object({
|
|
1330
1343
|
value: z.number().min(0).max(1),
|
|
1331
1344
|
}),
|
|
1332
1345
|
getUplinkSendingOnButtonPress: z.object({}),
|
|
1333
1346
|
restartDevice: z.object({}),
|
|
1347
|
+
setPIRSensorState: z.object({
|
|
1348
|
+
state: z.number().min(0).max(1), // 0: disabled, 1: enabled
|
|
1349
|
+
}),
|
|
1350
|
+
getPIRSensorState: z.object({}),
|
|
1351
|
+
setPIRSensorSensitivity: z.object({
|
|
1352
|
+
sensitivity: z.number().min(12).max(255),
|
|
1353
|
+
}),
|
|
1354
|
+
getPIRSensorSensitivity: z.object({}),
|
|
1355
|
+
setOccupancyTimeout: z.object({
|
|
1356
|
+
timeout: z.number().min(15).max(65535), // in seconds, between 15 and 65535
|
|
1357
|
+
}),
|
|
1358
|
+
getOccupancyTimeout: z.object({}),
|
|
1334
1359
|
}
|
|
1335
1360
|
|
|
1336
1361
|
export namespace HTPirLiteCommandTypes {
|
|
1337
1362
|
export type SetUplinkSendingOnButtonPressParams = z.infer<typeof HTPirLiteCommandSchemas.setUplinkSendingOnButtonPress>
|
|
1338
1363
|
export type GetUplinkSendingOnButtonPressParams = z.infer<typeof HTPirLiteCommandSchemas.getUplinkSendingOnButtonPress>
|
|
1339
1364
|
export type RestartDeviceParams = z.infer<typeof HTPirLiteCommandSchemas.restartDevice>
|
|
1365
|
+
export type SetPIRSensorStateParams = z.infer<typeof HTPirLiteCommandSchemas.setPIRSensorState>
|
|
1366
|
+
export type GetPIRSensorStateParams = z.infer<typeof HTPirLiteCommandSchemas.getPIRSensorState>
|
|
1367
|
+
export type SetPIRSensorSensitivityParams = z.infer<typeof HTPirLiteCommandSchemas.setPIRSensorSensitivity>
|
|
1368
|
+
export type GetPIRSensorSensitivityParams = z.infer<typeof HTPirLiteCommandSchemas.getPIRSensorSensitivity>
|
|
1369
|
+
export type SetOccupancyTimeoutParams = z.infer<typeof HTPirLiteCommandSchemas.setOccupancyTimeout>
|
|
1370
|
+
export type GetOccupancyTimeoutParams = z.infer<typeof HTPirLiteCommandSchemas.getOccupancyTimeout>
|
|
1340
1371
|
}
|
|
1341
1372
|
|
|
1342
1373
|
/* --------------------------------------- CO2 PIR LITE COMMANDS --------------------------------------- */
|
|
1343
1374
|
const Co2PirLiteCommandSchemas = {
|
|
1344
1375
|
...GeneralCommandSchemas,
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
value: z.number().min(0).max(1),
|
|
1376
|
+
setPIRSensorState: z.object({
|
|
1377
|
+
state: z.number().min(0).max(1), // 0: disabled, 1: enabled
|
|
1348
1378
|
}),
|
|
1349
|
-
|
|
1379
|
+
getPIRSensorState: z.object({}),
|
|
1380
|
+
setPIRSensorSensitivity: z.object({
|
|
1381
|
+
sensitivity: z.number().min(12).max(255),
|
|
1382
|
+
}),
|
|
1383
|
+
getPIRSensorSensitivity: z.object({}),
|
|
1384
|
+
setOccupancyTimeout: z.object({
|
|
1385
|
+
timeout: z.number().min(15).max(65535), // in seconds, between 15 and 65535
|
|
1386
|
+
}),
|
|
1387
|
+
getOccupancyTimeout: z.object({}),
|
|
1350
1388
|
restartDevice: z.object({}),
|
|
1351
1389
|
setCo2BoundaryLevels: z.object({
|
|
1352
1390
|
good_medium: z.number().min(0).max(1500),
|
|
@@ -1370,12 +1408,12 @@ const Co2PirLiteCommandSchemas = {
|
|
|
1370
1408
|
}
|
|
1371
1409
|
|
|
1372
1410
|
export namespace Co2PirLiteCommandTypes {
|
|
1373
|
-
export type
|
|
1374
|
-
|
|
1375
|
-
>
|
|
1376
|
-
export type
|
|
1377
|
-
|
|
1378
|
-
>
|
|
1411
|
+
export type SetPIRSensorStateParams = z.infer<typeof Co2PirLiteCommandSchemas.setPIRSensorState>
|
|
1412
|
+
export type GetPIRSensorStateParams = z.infer<typeof Co2PirLiteCommandSchemas.getPIRSensorState>
|
|
1413
|
+
export type SetPIRSensorSensitivityParams = z.infer<typeof Co2PirLiteCommandSchemas.setPIRSensorSensitivity>
|
|
1414
|
+
export type GetPIRSensorSensitivityParams = z.infer<typeof Co2PirLiteCommandSchemas.getPIRSensorSensitivity>
|
|
1415
|
+
export type SetOccupancyTimeoutParams = z.infer<typeof Co2PirLiteCommandSchemas.setOccupancyTimeout>
|
|
1416
|
+
export type GetOccupancyTimeoutParams = z.infer<typeof Co2PirLiteCommandSchemas.getOccupancyTimeout>
|
|
1379
1417
|
export type RestartDeviceParams = z.infer<typeof Co2PirLiteCommandSchemas.restartDevice>
|
|
1380
1418
|
}
|
|
1381
1419
|
|
|
@@ -776,12 +776,6 @@ describe('ASPM payload decoder', () => {
|
|
|
776
776
|
})
|
|
777
777
|
})
|
|
778
778
|
test('all settings (relay)', () => {
|
|
779
|
-
console.log(
|
|
780
|
-
uplinkPayloadParser(
|
|
781
|
-
'041312120A19781B001D02181F5F46210113FA2310250E605F00011C034A241805D9E7195201',
|
|
782
|
-
DeviceType.Relay16,
|
|
783
|
-
),
|
|
784
|
-
)
|
|
785
779
|
expect(
|
|
786
780
|
uplinkPayloadParser(
|
|
787
781
|
'041312120A19781B001D02181F5F46210113FA2310250E605F00011C034A241805D9E7195201',
|
|
@@ -884,41 +878,47 @@ describe('Melissa payload decoder', () => {
|
|
|
884
878
|
})
|
|
885
879
|
describe('CO2PirLite payload decoder', () => {
|
|
886
880
|
test('simple keepalive', () => {
|
|
887
|
-
expect(uplinkPayloadParser('
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
881
|
+
expect(uplinkPayloadParser('8106797EDA4718F1', DeviceType.CO2PirLite)).toStrictEqual({
|
|
882
|
+
pir: true,
|
|
883
|
+
sensorTemperature: 23.3,
|
|
884
|
+
relativeHumidity: 49.22,
|
|
885
|
+
batteryVoltage: 3.48,
|
|
886
|
+
CO2: 839,
|
|
887
|
+
pirTriggerCount: 241
|
|
893
888
|
})
|
|
894
889
|
})
|
|
895
890
|
test('keepalive with response of preloaded code', () => {
|
|
896
|
-
expect(uplinkPayloadParser('
|
|
897
|
-
|
|
898
|
-
pir: false,
|
|
899
|
-
sensorTemperature: 27.8,
|
|
900
|
-
relativeHumidity: 49.61,
|
|
901
|
-
batteryVoltage: 3.44,
|
|
891
|
+
expect(uplinkPayloadParser('39003C120A8102797BD95A1800', DeviceType.CO2PirLite)).toStrictEqual({
|
|
892
|
+
occupancyTimeout: 60,
|
|
902
893
|
keepAliveTime: 10,
|
|
894
|
+
pir: false,
|
|
895
|
+
sensorTemperature: 23.3,
|
|
896
|
+
relativeHumidity: 48.05,
|
|
897
|
+
batteryVoltage: 3.47,
|
|
898
|
+
CO2: 858,
|
|
899
|
+
pirTriggerCount: 0
|
|
903
900
|
})
|
|
904
901
|
})
|
|
905
902
|
})
|
|
906
903
|
describe('HTPirLite payload decoder', () => {
|
|
907
904
|
test('simple keepalive', () => {
|
|
908
|
-
expect(uplinkPayloadParser('
|
|
905
|
+
expect(uplinkPayloadParser('8102797DE201', DeviceType.HTPirLite)).toStrictEqual({
|
|
909
906
|
pir: false,
|
|
910
|
-
sensorTemperature:
|
|
911
|
-
relativeHumidity:
|
|
912
|
-
batteryVoltage:
|
|
907
|
+
sensorTemperature: 23.3,
|
|
908
|
+
relativeHumidity: 48.83,
|
|
909
|
+
batteryVoltage: 3.55,
|
|
910
|
+
pirTriggerCount: 1,
|
|
913
911
|
})
|
|
914
912
|
})
|
|
915
913
|
test('keepalive with response of preloaded code', () => {
|
|
916
|
-
expect(uplinkPayloadParser('
|
|
914
|
+
expect(uplinkPayloadParser('39003C120A8102797DE201', DeviceType.HTPirLite)).toStrictEqual({
|
|
917
915
|
pir: false,
|
|
918
|
-
sensorTemperature:
|
|
919
|
-
relativeHumidity:
|
|
920
|
-
batteryVoltage:
|
|
916
|
+
sensorTemperature: 23.3,
|
|
917
|
+
relativeHumidity: 48.83,
|
|
918
|
+
batteryVoltage: 3.55,
|
|
919
|
+
pirTriggerCount: 1,
|
|
921
920
|
keepAliveTime: 10,
|
|
921
|
+
occupancyTimeout: 60,
|
|
922
922
|
})
|
|
923
923
|
})
|
|
924
924
|
})
|