edilkamin 1.10.2 → 1.12.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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/bluetooth-protocol.d.ts +178 -0
- package/dist/cjs/src/bluetooth-protocol.js +423 -0
- package/dist/cjs/src/bluetooth-protocol.test.d.ts +1 -0
- package/dist/cjs/src/bluetooth-protocol.test.js +389 -0
- package/dist/cjs/src/bluetooth-utils.js +2 -6
- package/dist/cjs/src/bluetooth.d.ts +2 -0
- package/dist/cjs/src/bluetooth.js +17 -1
- package/dist/cjs/src/cli.js +9 -8
- package/dist/cjs/src/index.d.ts +4 -3
- package/dist/cjs/src/index.js +14 -1
- package/dist/cjs/src/library.d.ts +30 -0
- package/dist/cjs/src/library.js +97 -3
- package/dist/cjs/src/library.test.js +225 -4
- package/dist/cjs/src/mac-utils.d.ts +15 -0
- package/dist/cjs/src/mac-utils.js +24 -0
- package/dist/cjs/src/mac-utils.test.d.ts +1 -0
- package/dist/cjs/src/mac-utils.test.js +41 -0
- package/dist/cjs/src/types.d.ts +94 -2
- package/dist/cjs/src/types.js +95 -1
- package/dist/esm/package.json +1 -1
- package/dist/esm/src/bluetooth-protocol.d.ts +178 -0
- package/dist/esm/src/bluetooth-protocol.js +415 -0
- package/dist/esm/src/bluetooth-protocol.test.d.ts +1 -0
- package/dist/esm/src/bluetooth-protocol.test.js +387 -0
- package/dist/esm/src/bluetooth-utils.js +2 -6
- package/dist/esm/src/bluetooth.d.ts +2 -0
- package/dist/esm/src/bluetooth.js +8 -0
- package/dist/esm/src/cli.js +9 -8
- package/dist/esm/src/index.d.ts +4 -3
- package/dist/esm/src/index.js +3 -2
- package/dist/esm/src/library.d.ts +30 -0
- package/dist/esm/src/library.js +94 -2
- package/dist/esm/src/library.test.js +226 -5
- package/dist/esm/src/mac-utils.d.ts +15 -0
- package/dist/esm/src/mac-utils.js +21 -0
- package/dist/esm/src/mac-utils.test.d.ts +1 -0
- package/dist/esm/src/mac-utils.test.js +39 -0
- package/dist/esm/src/types.d.ts +94 -2
- package/dist/esm/src/types.js +89 -1
- package/package.json +1 -1
- package/src/bluetooth-protocol.test.ts +497 -0
- package/src/bluetooth-protocol.ts +524 -0
- package/src/bluetooth-utils.ts +3 -7
- package/src/bluetooth.ts +21 -0
- package/src/cli.ts +9 -8
- package/src/index.ts +24 -2
- package/src/library.test.ts +325 -4
- package/src/library.ts +109 -2
- package/src/mac-utils.test.ts +60 -0
- package/src/mac-utils.ts +22 -0
- package/src/types.ts +144 -1
package/dist/cjs/src/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AlarmDescriptions = exports.AlarmCode = void 0;
|
|
3
|
+
exports.StoveStateDescriptions = exports.StoveState = exports.OperationalPhaseDescriptions = exports.OperationalPhase = exports.IgnitionSubPhaseDescriptions = exports.IgnitionSubPhase = exports.getStoveStateDescription = exports.getOperationalPhaseDescription = exports.getIgnitionSubPhaseDescription = exports.AlarmDescriptions = exports.AlarmCode = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Alarm type codes from Edilkamin devices.
|
|
6
6
|
* Based on AlarmsEnum.java from Android app (version 1.3.1-RC2 released 2025/12/10).
|
|
@@ -64,3 +64,97 @@ const AlarmDescriptions = {
|
|
|
64
64
|
[AlarmCode.BOARD_FUSE]: "Control board fuse issue",
|
|
65
65
|
};
|
|
66
66
|
exports.AlarmDescriptions = AlarmDescriptions;
|
|
67
|
+
/**
|
|
68
|
+
* Main operational phases of the stove.
|
|
69
|
+
* Values derived from device behavior observation.
|
|
70
|
+
*/
|
|
71
|
+
var OperationalPhase;
|
|
72
|
+
(function (OperationalPhase) {
|
|
73
|
+
OperationalPhase[OperationalPhase["OFF"] = 0] = "OFF";
|
|
74
|
+
OperationalPhase[OperationalPhase["STANDBY"] = 1] = "STANDBY";
|
|
75
|
+
OperationalPhase[OperationalPhase["IGNITION"] = 2] = "IGNITION";
|
|
76
|
+
OperationalPhase[OperationalPhase["ON"] = 6] = "ON";
|
|
77
|
+
})(OperationalPhase || (exports.OperationalPhase = OperationalPhase = {}));
|
|
78
|
+
/**
|
|
79
|
+
* Human-readable descriptions for operational phases.
|
|
80
|
+
*/
|
|
81
|
+
const OperationalPhaseDescriptions = {
|
|
82
|
+
[OperationalPhase.OFF]: "Off",
|
|
83
|
+
[OperationalPhase.STANDBY]: "Standby",
|
|
84
|
+
[OperationalPhase.IGNITION]: "Ignition",
|
|
85
|
+
[OperationalPhase.ON]: "On",
|
|
86
|
+
};
|
|
87
|
+
exports.OperationalPhaseDescriptions = OperationalPhaseDescriptions;
|
|
88
|
+
/**
|
|
89
|
+
* Get description for an operational phase, with fallback for unknown values.
|
|
90
|
+
*/
|
|
91
|
+
const getOperationalPhaseDescription = (phase) => { var _a; return (_a = OperationalPhaseDescriptions[phase]) !== null && _a !== void 0 ? _a : `Unknown phase (${phase})`; };
|
|
92
|
+
exports.getOperationalPhaseDescription = getOperationalPhaseDescription;
|
|
93
|
+
/**
|
|
94
|
+
* Sub-phases during ignition sequence.
|
|
95
|
+
* These are only meaningful when operational_phase === IGNITION.
|
|
96
|
+
*/
|
|
97
|
+
var IgnitionSubPhase;
|
|
98
|
+
(function (IgnitionSubPhase) {
|
|
99
|
+
IgnitionSubPhase[IgnitionSubPhase["STARTING_CLEANING"] = 0] = "STARTING_CLEANING";
|
|
100
|
+
IgnitionSubPhase[IgnitionSubPhase["PELLET_LOAD"] = 1] = "PELLET_LOAD";
|
|
101
|
+
IgnitionSubPhase[IgnitionSubPhase["LOADING_BREAK"] = 2] = "LOADING_BREAK";
|
|
102
|
+
IgnitionSubPhase[IgnitionSubPhase["SMOKE_TEMPERATURE_CHECK"] = 3] = "SMOKE_TEMPERATURE_CHECK";
|
|
103
|
+
IgnitionSubPhase[IgnitionSubPhase["THRESHOLD_EXCEEDING_CHECK"] = 4] = "THRESHOLD_EXCEEDING_CHECK";
|
|
104
|
+
IgnitionSubPhase[IgnitionSubPhase["WARMUP"] = 5] = "WARMUP";
|
|
105
|
+
IgnitionSubPhase[IgnitionSubPhase["TRANSITION_TO_ON"] = 6] = "TRANSITION_TO_ON";
|
|
106
|
+
})(IgnitionSubPhase || (exports.IgnitionSubPhase = IgnitionSubPhase = {}));
|
|
107
|
+
/**
|
|
108
|
+
* Human-readable descriptions for ignition sub-phases.
|
|
109
|
+
*/
|
|
110
|
+
const IgnitionSubPhaseDescriptions = {
|
|
111
|
+
[IgnitionSubPhase.STARTING_CLEANING]: "Starting cleaning",
|
|
112
|
+
[IgnitionSubPhase.PELLET_LOAD]: "Pellet load",
|
|
113
|
+
[IgnitionSubPhase.LOADING_BREAK]: "Loading break",
|
|
114
|
+
[IgnitionSubPhase.SMOKE_TEMPERATURE_CHECK]: "Smoke temperature check",
|
|
115
|
+
[IgnitionSubPhase.THRESHOLD_EXCEEDING_CHECK]: "Threshold exceeding check",
|
|
116
|
+
[IgnitionSubPhase.WARMUP]: "Warmup",
|
|
117
|
+
[IgnitionSubPhase.TRANSITION_TO_ON]: "Starting up",
|
|
118
|
+
};
|
|
119
|
+
exports.IgnitionSubPhaseDescriptions = IgnitionSubPhaseDescriptions;
|
|
120
|
+
/**
|
|
121
|
+
* Get description for an ignition sub-phase, with fallback for unknown values.
|
|
122
|
+
*/
|
|
123
|
+
const getIgnitionSubPhaseDescription = (subPhase) => { var _a; return (_a = IgnitionSubPhaseDescriptions[subPhase]) !== null && _a !== void 0 ? _a : `Unknown sub-phase (${subPhase})`; };
|
|
124
|
+
exports.getIgnitionSubPhaseDescription = getIgnitionSubPhaseDescription;
|
|
125
|
+
/**
|
|
126
|
+
* Combined stove states.
|
|
127
|
+
* This is a composite value combining operational phase and sub-phase.
|
|
128
|
+
*/
|
|
129
|
+
var StoveState;
|
|
130
|
+
(function (StoveState) {
|
|
131
|
+
StoveState[StoveState["OFF"] = 0] = "OFF";
|
|
132
|
+
StoveState[StoveState["STANDBY"] = 1] = "STANDBY";
|
|
133
|
+
StoveState[StoveState["IGNITION_CLEANING"] = 2] = "IGNITION_CLEANING";
|
|
134
|
+
StoveState[StoveState["IGNITION_LOADING"] = 3] = "IGNITION_LOADING";
|
|
135
|
+
StoveState[StoveState["IGNITION_WAITING"] = 4] = "IGNITION_WAITING";
|
|
136
|
+
StoveState[StoveState["IGNITION_WARMUP"] = 5] = "IGNITION_WARMUP";
|
|
137
|
+
StoveState[StoveState["ON"] = 6] = "ON";
|
|
138
|
+
StoveState[StoveState["COOLING"] = 7] = "COOLING";
|
|
139
|
+
StoveState[StoveState["ALARM"] = 8] = "ALARM";
|
|
140
|
+
})(StoveState || (exports.StoveState = StoveState = {}));
|
|
141
|
+
/**
|
|
142
|
+
* Human-readable descriptions for stove states.
|
|
143
|
+
*/
|
|
144
|
+
const StoveStateDescriptions = {
|
|
145
|
+
[StoveState.OFF]: "Off",
|
|
146
|
+
[StoveState.STANDBY]: "Standby",
|
|
147
|
+
[StoveState.IGNITION_CLEANING]: "Ignition - Cleaning",
|
|
148
|
+
[StoveState.IGNITION_LOADING]: "Ignition - Loading pellets",
|
|
149
|
+
[StoveState.IGNITION_WAITING]: "Ignition - Waiting",
|
|
150
|
+
[StoveState.IGNITION_WARMUP]: "Ignition - Warming up",
|
|
151
|
+
[StoveState.ON]: "On",
|
|
152
|
+
[StoveState.COOLING]: "Cooling down",
|
|
153
|
+
[StoveState.ALARM]: "Alarm",
|
|
154
|
+
};
|
|
155
|
+
exports.StoveStateDescriptions = StoveStateDescriptions;
|
|
156
|
+
/**
|
|
157
|
+
* Get description for a stove state, with fallback for unknown values.
|
|
158
|
+
*/
|
|
159
|
+
const getStoveStateDescription = (state) => { var _a; return (_a = StoveStateDescriptions[state]) !== null && _a !== void 0 ? _a : `Unknown state (${state})`; };
|
|
160
|
+
exports.getStoveStateDescription = getStoveStateDescription;
|
package/dist/esm/package.json
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edilkamin BLE Protocol Implementation
|
|
3
|
+
*
|
|
4
|
+
* Transport-agnostic protocol layer for communicating with Edilkamin stoves via BLE.
|
|
5
|
+
* Handles AES-128-CBC encryption, CRC16-Modbus checksums, and Modbus packet building/parsing.
|
|
6
|
+
*
|
|
7
|
+
* The consuming application is responsible for:
|
|
8
|
+
* - BLE device scanning and connection
|
|
9
|
+
* - Writing to BLE characteristics
|
|
10
|
+
* - Subscribing to BLE notifications
|
|
11
|
+
*
|
|
12
|
+
* Protocol details derived from: https://github.com/netmb/Edilkamin_BT
|
|
13
|
+
*/
|
|
14
|
+
/** Edilkamin GATT service UUID */
|
|
15
|
+
export declare const SERVICE_UUID = "0000abf0-0000-1000-8000-00805f9b34fb";
|
|
16
|
+
/** Write characteristic UUID (WRITE NO RESPONSE) */
|
|
17
|
+
export declare const WRITE_CHARACTERISTIC_UUID = "0000abf1-0000-1000-8000-00805f9b34fb";
|
|
18
|
+
/** Notify characteristic UUID (NOTIFY) */
|
|
19
|
+
export declare const NOTIFY_CHARACTERISTIC_UUID = "0000abf2-0000-1000-8000-00805f9b34fb";
|
|
20
|
+
/**
|
|
21
|
+
* Parsed Modbus response from the device.
|
|
22
|
+
*/
|
|
23
|
+
export interface ModbusResponse {
|
|
24
|
+
/** Slave address (always 0x01 for Edilkamin) */
|
|
25
|
+
slaveAddress: number;
|
|
26
|
+
/** Function code (0x03 for read, 0x06 for write) */
|
|
27
|
+
functionCode: number;
|
|
28
|
+
/** Byte count (for read responses) */
|
|
29
|
+
byteCount?: number;
|
|
30
|
+
/** Response data */
|
|
31
|
+
data: Uint8Array;
|
|
32
|
+
/** Whether the response indicates an error */
|
|
33
|
+
isError: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Calculate CRC16-Modbus checksum.
|
|
37
|
+
*
|
|
38
|
+
* @param data - Data to calculate CRC for
|
|
39
|
+
* @returns 2-byte CRC in little-endian order [crcLo, crcHi]
|
|
40
|
+
*/
|
|
41
|
+
export declare const crc16Modbus: (data: Uint8Array) => Uint8Array;
|
|
42
|
+
/**
|
|
43
|
+
* Encrypt data using AES-128-CBC (raw, without PKCS7 padding).
|
|
44
|
+
*
|
|
45
|
+
* This manually applies PKCS7 padding to make input a multiple of 16 bytes,
|
|
46
|
+
* encrypts with Web Crypto, then strips the extra padding block from output.
|
|
47
|
+
*
|
|
48
|
+
* @param plaintext - Data to encrypt (must be 32 bytes)
|
|
49
|
+
* @returns Encrypted data (32 bytes)
|
|
50
|
+
*/
|
|
51
|
+
export declare const aesEncrypt: (plaintext: Uint8Array) => Promise<Uint8Array>;
|
|
52
|
+
/**
|
|
53
|
+
* Decrypt data using AES-128-CBC (raw, handling PKCS7 padding).
|
|
54
|
+
*
|
|
55
|
+
* @param ciphertext - Data to decrypt (must be 32 bytes)
|
|
56
|
+
* @returns Decrypted data (32 bytes)
|
|
57
|
+
*/
|
|
58
|
+
export declare const aesDecrypt: (ciphertext: Uint8Array) => Promise<Uint8Array>;
|
|
59
|
+
/**
|
|
60
|
+
* Build and encrypt a command packet to send to the device.
|
|
61
|
+
*
|
|
62
|
+
* Packet structure (32 bytes before encryption):
|
|
63
|
+
* - Bytes 0-3: Unix timestamp (big-endian)
|
|
64
|
+
* - Bytes 4-19: Fixed key
|
|
65
|
+
* - Bytes 20-25: Modbus command (6 bytes)
|
|
66
|
+
* - Bytes 26-27: CRC16-Modbus of command
|
|
67
|
+
* - Bytes 28-31: Padding [0x04, 0x04, 0x04, 0x04]
|
|
68
|
+
*
|
|
69
|
+
* @param modbusCommand - 6-byte Modbus RTU command
|
|
70
|
+
* @returns 32-byte encrypted packet ready to send via BLE
|
|
71
|
+
*/
|
|
72
|
+
export declare const createPacket: (modbusCommand: Uint8Array) => Promise<Uint8Array>;
|
|
73
|
+
/**
|
|
74
|
+
* Decrypt and parse a response packet from the device.
|
|
75
|
+
*
|
|
76
|
+
* Response structure (32 bytes before decryption):
|
|
77
|
+
* - Bytes 0-3: Unix timestamp
|
|
78
|
+
* - Bytes 4-19: Fixed key
|
|
79
|
+
* - Bytes 20-26: Modbus response (7 bytes)
|
|
80
|
+
* - Bytes 27-28: CRC16-Modbus
|
|
81
|
+
* - Bytes 29-31: Padding [0x03, 0x03, 0x03]
|
|
82
|
+
*
|
|
83
|
+
* @param encrypted - 32-byte encrypted response from BLE notification
|
|
84
|
+
* @returns Parsed Modbus response
|
|
85
|
+
*/
|
|
86
|
+
export declare const parseResponse: (encrypted: Uint8Array) => Promise<ModbusResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Pre-built Modbus read commands for querying device state.
|
|
89
|
+
* Each command is 6 bytes: [SlaveAddr, FuncCode, RegHi, RegLo, CountHi, CountLo]
|
|
90
|
+
*/
|
|
91
|
+
export declare const readCommands: {
|
|
92
|
+
/** Power state (0=off, 1=on) */
|
|
93
|
+
power: Uint8Array<ArrayBuffer>;
|
|
94
|
+
/** Current ambient temperature (value / 10 = °C) */
|
|
95
|
+
temperature: Uint8Array<ArrayBuffer>;
|
|
96
|
+
/** Target temperature (value / 10 = °C) */
|
|
97
|
+
targetTemperature: Uint8Array<ArrayBuffer>;
|
|
98
|
+
/** Power level (1-5) */
|
|
99
|
+
powerLevel: Uint8Array<ArrayBuffer>;
|
|
100
|
+
/** Fan 1 speed (0=auto, 1-5=speed) */
|
|
101
|
+
fan1Speed: Uint8Array<ArrayBuffer>;
|
|
102
|
+
/** Fan 2 speed (0=auto, 1-5=speed) */
|
|
103
|
+
fan2Speed: Uint8Array<ArrayBuffer>;
|
|
104
|
+
/** Device state code */
|
|
105
|
+
state: Uint8Array<ArrayBuffer>;
|
|
106
|
+
/** Alarm status code */
|
|
107
|
+
alarm: Uint8Array<ArrayBuffer>;
|
|
108
|
+
/** Pellet warning status */
|
|
109
|
+
pelletAlarm: Uint8Array<ArrayBuffer>;
|
|
110
|
+
/** Auto mode (0=manual, 1=auto) */
|
|
111
|
+
autoMode: Uint8Array<ArrayBuffer>;
|
|
112
|
+
/** Standby mode status */
|
|
113
|
+
standby: Uint8Array<ArrayBuffer>;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Builder functions for Modbus write commands.
|
|
117
|
+
* Each function returns a 6-byte command: [SlaveAddr, FuncCode, RegHi, RegLo, ValHi, ValLo]
|
|
118
|
+
*/
|
|
119
|
+
export declare const writeCommands: {
|
|
120
|
+
/**
|
|
121
|
+
* Turn power on or off.
|
|
122
|
+
* @param on - true to turn on, false to turn off
|
|
123
|
+
*/
|
|
124
|
+
setPower: (on: boolean) => Uint8Array;
|
|
125
|
+
/**
|
|
126
|
+
* Set target temperature.
|
|
127
|
+
* @param tempCelsius - Temperature in Celsius (e.g., 21.5)
|
|
128
|
+
*/
|
|
129
|
+
setTemperature: (tempCelsius: number) => Uint8Array;
|
|
130
|
+
/**
|
|
131
|
+
* Set power level.
|
|
132
|
+
* @param level - Power level (1-5)
|
|
133
|
+
*/
|
|
134
|
+
setPowerLevel: (level: number) => Uint8Array;
|
|
135
|
+
/**
|
|
136
|
+
* Set fan 1 speed.
|
|
137
|
+
* @param speed - Fan speed (0=auto, 1-5=manual speed)
|
|
138
|
+
*/
|
|
139
|
+
setFan1Speed: (speed: number) => Uint8Array;
|
|
140
|
+
/**
|
|
141
|
+
* Set fan 2 speed.
|
|
142
|
+
* @param speed - Fan speed (0=auto, 1-5=manual speed)
|
|
143
|
+
*/
|
|
144
|
+
setFan2Speed: (speed: number) => Uint8Array;
|
|
145
|
+
/**
|
|
146
|
+
* Enable or disable auto mode.
|
|
147
|
+
* @param enabled - true to enable auto mode
|
|
148
|
+
*/
|
|
149
|
+
setAutoMode: (enabled: boolean) => Uint8Array;
|
|
150
|
+
/**
|
|
151
|
+
* Enable or disable standby mode.
|
|
152
|
+
* @param enabled - true to enable standby mode
|
|
153
|
+
*/
|
|
154
|
+
setStandby: (enabled: boolean) => Uint8Array;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Parser functions to extract meaningful values from Modbus responses.
|
|
158
|
+
*/
|
|
159
|
+
export declare const parsers: {
|
|
160
|
+
/**
|
|
161
|
+
* Parse boolean response (power state, auto mode, etc.).
|
|
162
|
+
* @param response - Parsed Modbus response
|
|
163
|
+
* @returns true if value is 0x01, false if 0x00
|
|
164
|
+
*/
|
|
165
|
+
boolean: (response: ModbusResponse) => boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Parse temperature response.
|
|
168
|
+
* @param response - Parsed Modbus response
|
|
169
|
+
* @returns Temperature in Celsius
|
|
170
|
+
*/
|
|
171
|
+
temperature: (response: ModbusResponse) => number;
|
|
172
|
+
/**
|
|
173
|
+
* Parse numeric value (power level, fan speed, state code, etc.).
|
|
174
|
+
* @param response - Parsed Modbus response
|
|
175
|
+
* @returns Numeric value
|
|
176
|
+
*/
|
|
177
|
+
number: (response: ModbusResponse) => number;
|
|
178
|
+
};
|