edilkamin 1.11.0 → 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-utils.js +2 -6
- 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-utils.js +2 -6
- 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-utils.ts +3 -7
- 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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeMac = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Normalizes a MAC address by removing separators and converting to lowercase.
|
|
6
|
+
* Accepts formats: AA:BB:CC:DD:EE:FF, AA-BB-CC-DD-EE-FF, AABBCCDDEEFF
|
|
7
|
+
*
|
|
8
|
+
* @param mac - MAC address in any common format
|
|
9
|
+
* @returns Normalized MAC address (12 lowercase hex chars, no separators)
|
|
10
|
+
* @throws Error if MAC address format is invalid
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* normalizeMac("AA:BB:CC:DD:EE:FF") // returns "aabbccddeeff"
|
|
14
|
+
* normalizeMac("AA-BB-CC-DD-EE-FF") // returns "aabbccddeeff"
|
|
15
|
+
* normalizeMac("AABBCCDDEEFF") // returns "aabbccddeeff"
|
|
16
|
+
*/
|
|
17
|
+
const normalizeMac = (mac) => {
|
|
18
|
+
const normalized = mac.replace(/[:-]/g, "").toLowerCase();
|
|
19
|
+
if (!/^[0-9a-f]{12}$/.test(normalized)) {
|
|
20
|
+
throw new Error(`Invalid MAC address format: ${mac}`);
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
};
|
|
24
|
+
exports.normalizeMac = normalizeMac;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const assert_1 = require("assert");
|
|
4
|
+
const mac_utils_1 = require("./mac-utils");
|
|
5
|
+
describe("mac-utils", () => {
|
|
6
|
+
describe("normalizeMac", () => {
|
|
7
|
+
it("should normalize MAC address with colons", () => {
|
|
8
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("AA:BB:CC:DD:EE:FF"), "aabbccddeeff");
|
|
9
|
+
});
|
|
10
|
+
it("should normalize MAC address with dashes", () => {
|
|
11
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("AA-BB-CC-DD-EE-FF"), "aabbccddeeff");
|
|
12
|
+
});
|
|
13
|
+
it("should normalize MAC address without separators", () => {
|
|
14
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("AABBCCDDEEFF"), "aabbccddeeff");
|
|
15
|
+
});
|
|
16
|
+
it("should normalize lowercase MAC address", () => {
|
|
17
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("aa:bb:cc:dd:ee:ff"), "aabbccddeeff");
|
|
18
|
+
});
|
|
19
|
+
it("should normalize mixed case MAC address", () => {
|
|
20
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("Aa:Bb:Cc:Dd:Ee:Ff"), "aabbccddeeff");
|
|
21
|
+
});
|
|
22
|
+
it("should normalize MAC address with mixed separators", () => {
|
|
23
|
+
assert_1.strict.equal((0, mac_utils_1.normalizeMac)("AA:BB-CC:DD-EE:FF"), "aabbccddeeff");
|
|
24
|
+
});
|
|
25
|
+
it("should throw on MAC address with invalid length (too short)", () => {
|
|
26
|
+
assert_1.strict.throws(() => (0, mac_utils_1.normalizeMac)("AA:BB:CC:DD:EE"), /Invalid MAC address format: AA:BB:CC:DD:EE/);
|
|
27
|
+
});
|
|
28
|
+
it("should throw on MAC address with invalid length (too long)", () => {
|
|
29
|
+
assert_1.strict.throws(() => (0, mac_utils_1.normalizeMac)("AA:BB:CC:DD:EE:FF:00"), /Invalid MAC address format: AA:BB:CC:DD:EE:FF:00/);
|
|
30
|
+
});
|
|
31
|
+
it("should throw on MAC address with invalid characters", () => {
|
|
32
|
+
assert_1.strict.throws(() => (0, mac_utils_1.normalizeMac)("GG:HH:II:JJ:KK:LL"), /Invalid MAC address format: GG:HH:II:JJ:KK:LL/);
|
|
33
|
+
});
|
|
34
|
+
it("should throw on empty string", () => {
|
|
35
|
+
assert_1.strict.throws(() => (0, mac_utils_1.normalizeMac)(""), /Invalid MAC address format: /);
|
|
36
|
+
});
|
|
37
|
+
it("should throw on whitespace-only string", () => {
|
|
38
|
+
assert_1.strict.throws(() => (0, mac_utils_1.normalizeMac)(" "), /Invalid MAC address format:/);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
package/dist/cjs/src/types.d.ts
CHANGED
|
@@ -25,12 +25,42 @@ interface PelletAutonomyType {
|
|
|
25
25
|
interface StatusCountersType {
|
|
26
26
|
service_time: number;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Device operational state information.
|
|
30
|
+
* Retrieved from status.state in the API response.
|
|
31
|
+
*/
|
|
32
|
+
interface StateType {
|
|
33
|
+
/** Main operational phase (0=Off, 1=Standby, 2=Ignition, 6=On) */
|
|
34
|
+
operational_phase: number;
|
|
35
|
+
/** Sub-phase within current operation (0-6 during ignition) */
|
|
36
|
+
sub_operational_phase: number;
|
|
37
|
+
/** Combined stove state code */
|
|
38
|
+
stove_state: number;
|
|
39
|
+
/** Current alarm code (0 = no alarm) */
|
|
40
|
+
alarm_type: number;
|
|
41
|
+
/** Current actual power level (1-5) */
|
|
42
|
+
actual_power: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fan speed information for all three fans.
|
|
46
|
+
* Retrieved from status.fans in the API response.
|
|
47
|
+
*/
|
|
48
|
+
interface FansType {
|
|
49
|
+
/** Fan 1 speed (0-5) */
|
|
50
|
+
fan_1_speed: number;
|
|
51
|
+
/** Fan 2 speed (0-5) */
|
|
52
|
+
fan_2_speed: number;
|
|
53
|
+
/** Fan 3 speed (0-5) */
|
|
54
|
+
fan_3_speed: number;
|
|
55
|
+
}
|
|
28
56
|
interface StatusType {
|
|
29
57
|
commands: CommandsType;
|
|
30
58
|
temperatures: TemperaturesType;
|
|
31
59
|
flags: GeneralFlagsType;
|
|
32
60
|
pellet: PelletAutonomyType;
|
|
33
61
|
counters: StatusCountersType;
|
|
62
|
+
state: StateType;
|
|
63
|
+
fans: FansType;
|
|
34
64
|
}
|
|
35
65
|
interface UserParametersType {
|
|
36
66
|
enviroment_1_temperature: number;
|
|
@@ -161,6 +191,68 @@ declare enum AlarmCode {
|
|
|
161
191
|
* Human-readable descriptions for alarm codes.
|
|
162
192
|
*/
|
|
163
193
|
declare const AlarmDescriptions: Record<AlarmCode, string>;
|
|
194
|
+
/**
|
|
195
|
+
* Main operational phases of the stove.
|
|
196
|
+
* Values derived from device behavior observation.
|
|
197
|
+
*/
|
|
198
|
+
declare enum OperationalPhase {
|
|
199
|
+
OFF = 0,
|
|
200
|
+
STANDBY = 1,
|
|
201
|
+
IGNITION = 2,
|
|
202
|
+
ON = 6
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Human-readable descriptions for operational phases.
|
|
206
|
+
*/
|
|
207
|
+
declare const OperationalPhaseDescriptions: Record<number, string>;
|
|
208
|
+
/**
|
|
209
|
+
* Get description for an operational phase, with fallback for unknown values.
|
|
210
|
+
*/
|
|
211
|
+
declare const getOperationalPhaseDescription: (phase: number) => string;
|
|
212
|
+
/**
|
|
213
|
+
* Sub-phases during ignition sequence.
|
|
214
|
+
* These are only meaningful when operational_phase === IGNITION.
|
|
215
|
+
*/
|
|
216
|
+
declare enum IgnitionSubPhase {
|
|
217
|
+
STARTING_CLEANING = 0,
|
|
218
|
+
PELLET_LOAD = 1,
|
|
219
|
+
LOADING_BREAK = 2,
|
|
220
|
+
SMOKE_TEMPERATURE_CHECK = 3,
|
|
221
|
+
THRESHOLD_EXCEEDING_CHECK = 4,
|
|
222
|
+
WARMUP = 5,
|
|
223
|
+
TRANSITION_TO_ON = 6
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Human-readable descriptions for ignition sub-phases.
|
|
227
|
+
*/
|
|
228
|
+
declare const IgnitionSubPhaseDescriptions: Record<number, string>;
|
|
229
|
+
/**
|
|
230
|
+
* Get description for an ignition sub-phase, with fallback for unknown values.
|
|
231
|
+
*/
|
|
232
|
+
declare const getIgnitionSubPhaseDescription: (subPhase: number) => string;
|
|
233
|
+
/**
|
|
234
|
+
* Combined stove states.
|
|
235
|
+
* This is a composite value combining operational phase and sub-phase.
|
|
236
|
+
*/
|
|
237
|
+
declare enum StoveState {
|
|
238
|
+
OFF = 0,
|
|
239
|
+
STANDBY = 1,
|
|
240
|
+
IGNITION_CLEANING = 2,
|
|
241
|
+
IGNITION_LOADING = 3,
|
|
242
|
+
IGNITION_WAITING = 4,
|
|
243
|
+
IGNITION_WARMUP = 5,
|
|
244
|
+
ON = 6,
|
|
245
|
+
COOLING = 7,
|
|
246
|
+
ALARM = 8
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Human-readable descriptions for stove states.
|
|
250
|
+
*/
|
|
251
|
+
declare const StoveStateDescriptions: Record<number, string>;
|
|
252
|
+
/**
|
|
253
|
+
* Get description for a stove state, with fallback for unknown values.
|
|
254
|
+
*/
|
|
255
|
+
declare const getStoveStateDescription: (state: number) => string;
|
|
164
256
|
interface DeviceInfoType {
|
|
165
257
|
status: StatusType;
|
|
166
258
|
nvm: {
|
|
@@ -224,5 +316,5 @@ interface DiscoveredDevice {
|
|
|
224
316
|
/** Signal strength in dBm (optional, not all platforms provide this) */
|
|
225
317
|
rssi?: number;
|
|
226
318
|
}
|
|
227
|
-
export type { AlarmEntryType, AlarmsLogType, BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, GeneralFlagsType, PelletAutonomyType, PowerDistributionType, RegenerationDataType, ServiceCountersType, ServiceStatusType, StatusCountersType, StatusType, TemperaturesType, TotalCountersType, UsageAnalyticsType, UserParametersType, };
|
|
228
|
-
export { AlarmCode, AlarmDescriptions };
|
|
319
|
+
export type { AlarmEntryType, AlarmsLogType, BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, FansType, GeneralFlagsType, PelletAutonomyType, PowerDistributionType, RegenerationDataType, ServiceCountersType, ServiceStatusType, StateType, StatusCountersType, StatusType, TemperaturesType, TotalCountersType, UsageAnalyticsType, UserParametersType, };
|
|
320
|
+
export { AlarmCode, AlarmDescriptions, getIgnitionSubPhaseDescription, getOperationalPhaseDescription, getStoveStateDescription, IgnitionSubPhase, IgnitionSubPhaseDescriptions, OperationalPhase, OperationalPhaseDescriptions, StoveState, StoveStateDescriptions, };
|
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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeMac } from "./mac-utils";
|
|
1
2
|
/**
|
|
2
3
|
* Converts a BLE MAC address to WiFi MAC address.
|
|
3
4
|
* The WiFi MAC is the BLE MAC minus 2 in hexadecimal.
|
|
@@ -10,12 +11,7 @@
|
|
|
10
11
|
* bleToWifiMac("a8032afed50a") // returns "a8032afed508"
|
|
11
12
|
*/
|
|
12
13
|
const bleToWifiMac = (bleMac) => {
|
|
13
|
-
|
|
14
|
-
const normalized = bleMac.replace(/[:-]/g, "").toLowerCase();
|
|
15
|
-
// Validate MAC address format (12 hex characters)
|
|
16
|
-
if (!/^[0-9a-f]{12}$/.test(normalized)) {
|
|
17
|
-
throw new Error(`Invalid MAC address format: ${bleMac}`);
|
|
18
|
-
}
|
|
14
|
+
const normalized = normalizeMac(bleMac);
|
|
19
15
|
// Convert to number, subtract 2, convert back to hex
|
|
20
16
|
const bleValue = BigInt(`0x${normalized}`);
|
|
21
17
|
const wifiValue = bleValue - BigInt(2);
|
package/dist/esm/src/cli.js
CHANGED
|
@@ -13,6 +13,7 @@ import readline from "readline";
|
|
|
13
13
|
import { version } from "../package.json";
|
|
14
14
|
import { NEW_API_URL, OLD_API_URL } from "./constants";
|
|
15
15
|
import { configure, configureAmplify, getSession, signIn } from "./library";
|
|
16
|
+
import { normalizeMac } from "./mac-utils";
|
|
16
17
|
import { clearSession, createFileStorage } from "./token-storage";
|
|
17
18
|
import { AlarmCode, AlarmDescriptions } from "./types";
|
|
18
19
|
const promptPassword = () => {
|
|
@@ -66,7 +67,7 @@ const addLegacyOption = (command) => command.option("--legacy", "Use legacy API
|
|
|
66
67
|
*/
|
|
67
68
|
const initializeCommand = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
69
|
const { username, password, mac, legacy = false } = options;
|
|
69
|
-
const normalizedMac = mac
|
|
70
|
+
const normalizedMac = normalizeMac(mac);
|
|
70
71
|
// Initialize file storage for session persistence
|
|
71
72
|
const storage = createFileStorage();
|
|
72
73
|
configureAmplify(storage);
|
|
@@ -389,7 +390,7 @@ const createProgram = () => {
|
|
|
389
390
|
.command("getFanSpeed")
|
|
390
391
|
.description("Retrieve fan speed by index (1-3)")).requiredOption("-i, --index <number>", "Fan index (1, 2, or 3)", parseInt))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
391
392
|
const { username, password, mac, index, legacy = false } = options;
|
|
392
|
-
const normalizedMac = mac
|
|
393
|
+
const normalizedMac = normalizeMac(mac);
|
|
393
394
|
const storage = createFileStorage();
|
|
394
395
|
configureAmplify(storage);
|
|
395
396
|
let jwtToken;
|
|
@@ -412,7 +413,7 @@ const createProgram = () => {
|
|
|
412
413
|
.command("getTargetTemperature")
|
|
413
414
|
.description("Retrieve target temperature by environment index (1-3)")).requiredOption("-i, --index <number>", "Environment index (1, 2, or 3)", parseInt))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
414
415
|
const { username, password, mac, index, legacy = false } = options;
|
|
415
|
-
const normalizedMac = mac
|
|
416
|
+
const normalizedMac = normalizeMac(mac);
|
|
416
417
|
const storage = createFileStorage();
|
|
417
418
|
configureAmplify(storage);
|
|
418
419
|
let jwtToken;
|
|
@@ -438,7 +439,7 @@ const createProgram = () => {
|
|
|
438
439
|
.requiredOption("-i, --index <number>", "Fan index (1, 2, or 3)", parseInt)
|
|
439
440
|
.requiredOption("-v, --value <number>", "Fan speed (0-5)", parseFloat))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
440
441
|
const { username, password, mac, index, value, legacy = false } = options;
|
|
441
|
-
const normalizedMac = mac
|
|
442
|
+
const normalizedMac = normalizeMac(mac);
|
|
442
443
|
const storage = createFileStorage();
|
|
443
444
|
configureAmplify(storage);
|
|
444
445
|
let jwtToken;
|
|
@@ -463,7 +464,7 @@ const createProgram = () => {
|
|
|
463
464
|
.requiredOption("-i, --index <number>", "Environment index (1, 2, or 3)", parseInt)
|
|
464
465
|
.requiredOption("-v, --value <number>", "Temperature in degrees Celsius", parseFloat))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
465
466
|
const { username, password, mac, index, value, legacy = false } = options;
|
|
466
|
-
const normalizedMac = mac
|
|
467
|
+
const normalizedMac = normalizeMac(mac);
|
|
467
468
|
const storage = createFileStorage();
|
|
468
469
|
configureAmplify(storage);
|
|
469
470
|
let jwtToken;
|
|
@@ -487,7 +488,7 @@ const createProgram = () => {
|
|
|
487
488
|
.command("getAlarmHistory")
|
|
488
489
|
.description("Get alarm history log with human-readable descriptions")))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
489
490
|
const { username, password, mac, legacy = false } = options;
|
|
490
|
-
const normalizedMac = mac
|
|
491
|
+
const normalizedMac = normalizeMac(mac);
|
|
491
492
|
const storage = createFileStorage();
|
|
492
493
|
configureAmplify(storage);
|
|
493
494
|
let jwtToken;
|
|
@@ -518,7 +519,7 @@ const createProgram = () => {
|
|
|
518
519
|
.requiredOption("-r, --room <deviceRoom>", "Room name")
|
|
519
520
|
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
520
521
|
const { username, password, mac, serial, name, room, legacy = false, } = options;
|
|
521
|
-
const normalizedMac = mac
|
|
522
|
+
const normalizedMac = normalizeMac(mac);
|
|
522
523
|
// Initialize file storage for session persistence
|
|
523
524
|
const storage = createFileStorage();
|
|
524
525
|
configureAmplify(storage);
|
|
@@ -547,7 +548,7 @@ const createProgram = () => {
|
|
|
547
548
|
.requiredOption("-r, --room <deviceRoom>", "Room name")
|
|
548
549
|
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
549
550
|
const { username, password, mac, name, room, legacy = false } = options;
|
|
550
|
-
const normalizedMac = mac
|
|
551
|
+
const normalizedMac = normalizeMac(mac);
|
|
551
552
|
// Initialize file storage for session persistence
|
|
552
553
|
const storage = createFileStorage();
|
|
553
554
|
configureAmplify(storage);
|
package/dist/esm/src/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { bleToWifiMac } from "./bluetooth-utils";
|
|
2
2
|
export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
|
|
3
3
|
export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
|
|
4
|
-
export { configure, deriveUsageAnalytics, getSession, signIn } from "./library";
|
|
4
|
+
export { configure, derivePhaseDescription, deriveUsageAnalytics, getPhaseDescription, getSession, signIn, } from "./library";
|
|
5
|
+
export { normalizeMac } from "./mac-utils";
|
|
5
6
|
export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
|
|
6
|
-
export { AlarmEntryType, AlarmsLogType, BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, PowerDistributionType, RegenerationDataType, ServiceCountersType, ServiceStatusType, StatusCountersType, StatusType, TemperaturesType, TotalCountersType, UsageAnalyticsType, UserParametersType, } from "./types";
|
|
7
|
-
export { AlarmCode, AlarmDescriptions } from "./types";
|
|
7
|
+
export { AlarmEntryType, AlarmsLogType, BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, FansType, PowerDistributionType, RegenerationDataType, ServiceCountersType, ServiceStatusType, StateType, StatusCountersType, StatusType, TemperaturesType, TotalCountersType, UsageAnalyticsType, UserParametersType, } from "./types";
|
|
8
|
+
export { AlarmCode, AlarmDescriptions, getIgnitionSubPhaseDescription, getOperationalPhaseDescription, getStoveStateDescription, IgnitionSubPhase, IgnitionSubPhaseDescriptions, OperationalPhase, OperationalPhaseDescriptions, StoveState, StoveStateDescriptions, } from "./types";
|
|
8
9
|
export declare const deviceInfo: (jwtToken: string, macAddress: string) => Promise<import("./types").DeviceInfoType>, registerDevice: (jwtToken: string, macAddress: string, serialNumber: string, deviceName?: string, deviceRoom?: string) => Promise<import("./types").DeviceAssociationResponse>, editDevice: (jwtToken: string, macAddress: string, deviceName?: string, deviceRoom?: string) => Promise<import("./types").DeviceAssociationResponse>, setPower: (jwtToken: string, macAddress: string, value: number) => Promise<unknown>, setPowerOff: (jwtToken: string, macAddress: string) => Promise<unknown>, setPowerOn: (jwtToken: string, macAddress: string) => Promise<unknown>, getPower: (jwtToken: string, macAddress: string) => Promise<boolean>, getEnvironmentTemperature: (jwtToken: string, macAddress: string) => Promise<number>, getTargetTemperature: (jwtToken: string, macAddress: string, envIndex: 1 | 2 | 3) => Promise<number>, setTargetTemperature: (jwtToken: string, macAddress: string, envIndex: 1 | 2 | 3, temperature: number) => Promise<unknown>;
|
package/dist/esm/src/index.js
CHANGED
|
@@ -2,7 +2,8 @@ import { configure } from "./library";
|
|
|
2
2
|
export { bleToWifiMac } from "./bluetooth-utils";
|
|
3
3
|
export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
|
|
4
4
|
export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
|
|
5
|
-
export { configure, deriveUsageAnalytics, getSession, signIn } from "./library";
|
|
5
|
+
export { configure, derivePhaseDescription, deriveUsageAnalytics, getPhaseDescription, getSession, signIn, } from "./library";
|
|
6
|
+
export { normalizeMac } from "./mac-utils";
|
|
6
7
|
export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
|
|
7
|
-
export { AlarmCode, AlarmDescriptions } from "./types";
|
|
8
|
+
export { AlarmCode, AlarmDescriptions, getIgnitionSubPhaseDescription, getOperationalPhaseDescription, getStoveStateDescription, IgnitionSubPhase, IgnitionSubPhaseDescriptions, OperationalPhase, OperationalPhaseDescriptions, StoveState, StoveStateDescriptions, } from "./types";
|
|
8
9
|
export const { deviceInfo, registerDevice, editDevice, setPower, setPowerOff, setPowerOn, getPower, getEnvironmentTemperature, getTargetTemperature, setTargetTemperature, } = configure();
|
|
@@ -45,6 +45,32 @@ declare const signIn: (username: string, password: string, legacy?: boolean) =>
|
|
|
45
45
|
* const analytics = deriveUsageAnalytics(info);
|
|
46
46
|
*/
|
|
47
47
|
export declare const deriveUsageAnalytics: (deviceInfo: DeviceInfoType, serviceThreshold?: number) => UsageAnalyticsType;
|
|
48
|
+
/**
|
|
49
|
+
* Get human-readable description of the current device phase.
|
|
50
|
+
* Combines operational_phase and sub_operational_phase for context.
|
|
51
|
+
*
|
|
52
|
+
* @param {number} operationalPhase - The main operational phase.
|
|
53
|
+
* @param {number} subOperationalPhase - The sub-phase (used during ignition).
|
|
54
|
+
* @returns {string} - Human-readable phase description.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const desc = getPhaseDescription(2, 1);
|
|
58
|
+
* // Returns: "Ignition - Pellet load"
|
|
59
|
+
*/
|
|
60
|
+
export declare const getPhaseDescription: (operationalPhase: number, subOperationalPhase: number) => string;
|
|
61
|
+
/**
|
|
62
|
+
* Derive phase description from existing DeviceInfo.
|
|
63
|
+
* Pure function - no API calls required.
|
|
64
|
+
*
|
|
65
|
+
* @param {DeviceInfoType} deviceInfo - The device info object.
|
|
66
|
+
* @returns {string} - Human-readable phase description.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const info = await api.deviceInfo(token, mac);
|
|
70
|
+
* const desc = derivePhaseDescription(info);
|
|
71
|
+
* // Returns: "On" or "Ignition - Warmup" etc.
|
|
72
|
+
*/
|
|
73
|
+
export declare const derivePhaseDescription: (deviceInfo: DeviceInfoType) => string;
|
|
48
74
|
/**
|
|
49
75
|
* Configures the library for API interactions.
|
|
50
76
|
* Initializes API methods with a specified base URL.
|
|
@@ -97,6 +123,10 @@ declare const configure: (baseURL?: string) => {
|
|
|
97
123
|
getLanguage: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
98
124
|
getPelletInReserve: (jwtToken: string, macAddress: string) => Promise<boolean>;
|
|
99
125
|
getPelletAutonomyTime: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
126
|
+
getOperationalPhase: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
127
|
+
getSubOperationalPhase: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
128
|
+
getStoveState: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
129
|
+
getActualPower: (jwtToken: string, macAddress: string) => Promise<number>;
|
|
100
130
|
getTotalCounters: (jwtToken: string, macAddress: string) => Promise<TotalCountersType>;
|
|
101
131
|
getServiceCounters: (jwtToken: string, macAddress: string) => Promise<ServiceCountersType>;
|
|
102
132
|
getAlarmHistory: (jwtToken: string, macAddress: string) => Promise<AlarmsLogType>;
|
package/dist/esm/src/library.js
CHANGED
|
@@ -13,6 +13,8 @@ import * as amplifyAuth from "aws-amplify/auth";
|
|
|
13
13
|
import { cognitoUserPoolsTokenProvider } from "aws-amplify/auth/cognito";
|
|
14
14
|
import { processResponse } from "./buffer-utils";
|
|
15
15
|
import { API_URL } from "./constants";
|
|
16
|
+
import { normalizeMac } from "./mac-utils";
|
|
17
|
+
import { getIgnitionSubPhaseDescription, getOperationalPhaseDescription, OperationalPhase, } from "./types";
|
|
16
18
|
/**
|
|
17
19
|
* Makes a fetch request and returns parsed JSON response.
|
|
18
20
|
* Throws an error for non-2xx status codes.
|
|
@@ -473,6 +475,56 @@ const getPelletAutonomyTime = (baseURL) =>
|
|
|
473
475
|
const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
|
|
474
476
|
return info.status.pellet.autonomy_time;
|
|
475
477
|
});
|
|
478
|
+
const getOperationalPhase = (baseURL) =>
|
|
479
|
+
/**
|
|
480
|
+
* Retrieves the current operational phase of the stove.
|
|
481
|
+
*
|
|
482
|
+
* @param {string} jwtToken - The JWT token for authentication.
|
|
483
|
+
* @param {string} macAddress - The MAC address of the device.
|
|
484
|
+
* @returns {Promise<number>} - The operational phase (0=Off, 1=Standby, 2=Ignition, 6=On).
|
|
485
|
+
*/
|
|
486
|
+
(jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
487
|
+
const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
|
|
488
|
+
return info.status.state.operational_phase;
|
|
489
|
+
});
|
|
490
|
+
const getSubOperationalPhase = (baseURL) =>
|
|
491
|
+
/**
|
|
492
|
+
* Retrieves the current sub-operational phase of the stove.
|
|
493
|
+
* Only meaningful during ignition (operational_phase === 2).
|
|
494
|
+
*
|
|
495
|
+
* @param {string} jwtToken - The JWT token for authentication.
|
|
496
|
+
* @param {string} macAddress - The MAC address of the device.
|
|
497
|
+
* @returns {Promise<number>} - The sub-operational phase (0-6 during ignition).
|
|
498
|
+
*/
|
|
499
|
+
(jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
500
|
+
const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
|
|
501
|
+
return info.status.state.sub_operational_phase;
|
|
502
|
+
});
|
|
503
|
+
const getStoveState = (baseURL) =>
|
|
504
|
+
/**
|
|
505
|
+
* Retrieves the combined stove state code.
|
|
506
|
+
*
|
|
507
|
+
* @param {string} jwtToken - The JWT token for authentication.
|
|
508
|
+
* @param {string} macAddress - The MAC address of the device.
|
|
509
|
+
* @returns {Promise<number>} - The stove state code.
|
|
510
|
+
*/
|
|
511
|
+
(jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
512
|
+
const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
|
|
513
|
+
return info.status.state.stove_state;
|
|
514
|
+
});
|
|
515
|
+
const getActualPower = (baseURL) =>
|
|
516
|
+
/**
|
|
517
|
+
* Retrieves the actual power level the stove is currently running at.
|
|
518
|
+
* This may differ from the requested power level during transitions.
|
|
519
|
+
*
|
|
520
|
+
* @param {string} jwtToken - The JWT token for authentication.
|
|
521
|
+
* @param {string} macAddress - The MAC address of the device.
|
|
522
|
+
* @returns {Promise<number>} - The actual power level (1-5).
|
|
523
|
+
*/
|
|
524
|
+
(jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
525
|
+
const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
|
|
526
|
+
return info.status.state.actual_power;
|
|
527
|
+
});
|
|
476
528
|
const getTotalCounters = (baseURL) =>
|
|
477
529
|
/**
|
|
478
530
|
* Retrieves lifetime operating counters.
|
|
@@ -693,7 +745,7 @@ const registerDevice = (baseURL) =>
|
|
|
693
745
|
*/
|
|
694
746
|
(jwtToken_1, macAddress_1, serialNumber_1, ...args_1) => __awaiter(void 0, [jwtToken_1, macAddress_1, serialNumber_1, ...args_1], void 0, function* (jwtToken, macAddress, serialNumber, deviceName = "", deviceRoom = "") {
|
|
695
747
|
const body = {
|
|
696
|
-
macAddress: macAddress
|
|
748
|
+
macAddress: normalizeMac(macAddress),
|
|
697
749
|
deviceName,
|
|
698
750
|
deviceRoom,
|
|
699
751
|
serialNumber,
|
|
@@ -715,7 +767,7 @@ const editDevice = (baseURL) =>
|
|
|
715
767
|
* @returns {Promise<DeviceAssociationResponse>} - A promise that resolves to the update response.
|
|
716
768
|
*/
|
|
717
769
|
(jwtToken_1, macAddress_1, ...args_1) => __awaiter(void 0, [jwtToken_1, macAddress_1, ...args_1], void 0, function* (jwtToken, macAddress, deviceName = "", deviceRoom = "") {
|
|
718
|
-
const normalizedMac = macAddress
|
|
770
|
+
const normalizedMac = normalizeMac(macAddress);
|
|
719
771
|
const body = {
|
|
720
772
|
deviceName,
|
|
721
773
|
deviceRoom,
|
|
@@ -726,6 +778,41 @@ const editDevice = (baseURL) =>
|
|
|
726
778
|
body: JSON.stringify(body),
|
|
727
779
|
});
|
|
728
780
|
});
|
|
781
|
+
/**
|
|
782
|
+
* Get human-readable description of the current device phase.
|
|
783
|
+
* Combines operational_phase and sub_operational_phase for context.
|
|
784
|
+
*
|
|
785
|
+
* @param {number} operationalPhase - The main operational phase.
|
|
786
|
+
* @param {number} subOperationalPhase - The sub-phase (used during ignition).
|
|
787
|
+
* @returns {string} - Human-readable phase description.
|
|
788
|
+
*
|
|
789
|
+
* @example
|
|
790
|
+
* const desc = getPhaseDescription(2, 1);
|
|
791
|
+
* // Returns: "Ignition - Pellet load"
|
|
792
|
+
*/
|
|
793
|
+
export const getPhaseDescription = (operationalPhase, subOperationalPhase) => {
|
|
794
|
+
if (operationalPhase === OperationalPhase.IGNITION) {
|
|
795
|
+
const subDesc = getIgnitionSubPhaseDescription(subOperationalPhase);
|
|
796
|
+
return `Ignition - ${subDesc}`;
|
|
797
|
+
}
|
|
798
|
+
return getOperationalPhaseDescription(operationalPhase);
|
|
799
|
+
};
|
|
800
|
+
/**
|
|
801
|
+
* Derive phase description from existing DeviceInfo.
|
|
802
|
+
* Pure function - no API calls required.
|
|
803
|
+
*
|
|
804
|
+
* @param {DeviceInfoType} deviceInfo - The device info object.
|
|
805
|
+
* @returns {string} - Human-readable phase description.
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* const info = await api.deviceInfo(token, mac);
|
|
809
|
+
* const desc = derivePhaseDescription(info);
|
|
810
|
+
* // Returns: "On" or "Ignition - Warmup" etc.
|
|
811
|
+
*/
|
|
812
|
+
export const derivePhaseDescription = (deviceInfo) => {
|
|
813
|
+
const { operational_phase, sub_operational_phase } = deviceInfo.status.state;
|
|
814
|
+
return getPhaseDescription(operational_phase, sub_operational_phase);
|
|
815
|
+
};
|
|
729
816
|
/**
|
|
730
817
|
* Configures the library for API interactions.
|
|
731
818
|
* Initializes API methods with a specified base URL.
|
|
@@ -778,6 +865,11 @@ const configure = (baseURL = API_URL) => ({
|
|
|
778
865
|
getLanguage: getLanguage(baseURL),
|
|
779
866
|
getPelletInReserve: getPelletInReserve(baseURL),
|
|
780
867
|
getPelletAutonomyTime: getPelletAutonomyTime(baseURL),
|
|
868
|
+
// Phase/state getters
|
|
869
|
+
getOperationalPhase: getOperationalPhase(baseURL),
|
|
870
|
+
getSubOperationalPhase: getSubOperationalPhase(baseURL),
|
|
871
|
+
getStoveState: getStoveState(baseURL),
|
|
872
|
+
getActualPower: getActualPower(baseURL),
|
|
781
873
|
// Statistics getters
|
|
782
874
|
getTotalCounters: getTotalCounters(baseURL),
|
|
783
875
|
getServiceCounters: getServiceCounters(baseURL),
|