edilkamin 1.10.0 → 1.10.1

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.
@@ -19,11 +19,18 @@ interface GeneralFlagsType {
19
19
  interface PelletAutonomyType {
20
20
  autonomy_time: number;
21
21
  }
22
+ /**
23
+ * Status counters including service time.
24
+ */
25
+ interface StatusCountersType {
26
+ service_time: number;
27
+ }
22
28
  interface StatusType {
23
29
  commands: CommandsType;
24
30
  temperatures: TemperaturesType;
25
31
  flags: GeneralFlagsType;
26
32
  pellet: PelletAutonomyType;
33
+ counters: StatusCountersType;
27
34
  }
28
35
  interface UserParametersType {
29
36
  enviroment_1_temperature: number;
@@ -40,10 +47,128 @@ interface UserParametersType {
40
47
  is_fahrenheit: boolean;
41
48
  language: number;
42
49
  }
50
+ /**
51
+ * Lifetime operating counters - never reset.
52
+ * Tracks total power-on cycles and runtime hours per power level.
53
+ */
54
+ interface TotalCountersType {
55
+ power_ons: number;
56
+ p1_working_time: number;
57
+ p2_working_time: number;
58
+ p3_working_time: number;
59
+ p4_working_time: number;
60
+ p5_working_time: number;
61
+ }
62
+ /**
63
+ * Service counters - reset after maintenance.
64
+ * Tracks runtime hours per power level since last service.
65
+ */
66
+ interface ServiceCountersType {
67
+ p1_working_time: number;
68
+ p2_working_time: number;
69
+ p3_working_time: number;
70
+ p4_working_time: number;
71
+ p5_working_time: number;
72
+ }
73
+ /**
74
+ * Individual alarm entry from the alarm history log.
75
+ */
76
+ interface AlarmEntryType {
77
+ type: number;
78
+ timestamp: number;
79
+ }
80
+ /**
81
+ * Alarm history log - circular buffer of recent alarms.
82
+ */
83
+ interface AlarmsLogType {
84
+ number: number;
85
+ index: number;
86
+ alarms: AlarmEntryType[];
87
+ }
88
+ /**
89
+ * Regeneration and maintenance tracking data.
90
+ */
91
+ interface RegenerationDataType {
92
+ time: number;
93
+ last_intervention: number;
94
+ daylight_time_flag: number;
95
+ blackout_counter: number;
96
+ airkare_working_hours_counter: number;
97
+ }
98
+ /**
99
+ * Power level distribution as percentages.
100
+ */
101
+ interface PowerDistributionType {
102
+ p1: number;
103
+ p2: number;
104
+ p3: number;
105
+ p4: number;
106
+ p5: number;
107
+ }
108
+ /**
109
+ * Service status with computed fields.
110
+ */
111
+ interface ServiceStatusType {
112
+ totalServiceHours: number;
113
+ hoursSinceService: number;
114
+ serviceThresholdHours: number;
115
+ isServiceDue: boolean;
116
+ }
117
+ /**
118
+ * Comprehensive usage analytics.
119
+ */
120
+ interface UsageAnalyticsType {
121
+ totalPowerOns: number;
122
+ totalOperatingHours: number;
123
+ powerDistribution: PowerDistributionType;
124
+ serviceStatus: ServiceStatusType;
125
+ blackoutCount: number;
126
+ lastMaintenanceDate: Date | null;
127
+ alarmCount: number;
128
+ }
129
+ /**
130
+ * Alarm type codes from Edilkamin devices.
131
+ * Based on AlarmsEnum.java from Android app (version 1.3.1-RC2 released 2025/12/10).
132
+ */
133
+ declare enum AlarmCode {
134
+ NONE = 0,
135
+ FLUE_BLOCK = 1,
136
+ SMOKE_EXTRACTOR_FAILURE = 2,
137
+ END_PELLET = 3,
138
+ MISSING_LIGHTING = 4,
139
+ NO_NAME_ALARM = 5,
140
+ SMOKE_PROBE_FAILURE = 6,
141
+ FUMES_OVERTEMPERATURE = 7,
142
+ PELLET_TANK_SAFETY_THERMOSTAT = 8,
143
+ GEAR_MOTOR_FAILURE = 9,
144
+ BOARD_OVER_TEMPERATURE = 10,
145
+ SAFETY_PRESSURE_SWITCH_INTERVENTION = 11,
146
+ ROOM_PROBE_FAILURE = 12,
147
+ ROOM_PROBE_2_OR_BOILER_PROBE_FAILURE = 13,
148
+ ROOM_PROBE_3_OR_BOILER_PROBE_FAILURE = 14,
149
+ WATER_EARTHQUAKE_SAFETY_THERMOSTAT_INTERVENTION = 15,
150
+ WATER_PRESSURE_TRANSDUCER_FAILURE = 16,
151
+ OUTSIDE_PROBE_OR_LOW_STORAGE_PROBE_FAILURE = 17,
152
+ PUFFER_PROBE_FAILURE = 18,
153
+ CRUCIBLE_CLEANING_FAILURE = 19,
154
+ TRIAC_FAILURE = 20,
155
+ BLACKOUT = 21,
156
+ OPEN_DOOR = 22,
157
+ OVERTEMPERATURE_PANEL = 23,
158
+ BOARD_FUSE = 24
159
+ }
160
+ /**
161
+ * Human-readable descriptions for alarm codes.
162
+ */
163
+ declare const AlarmDescriptions: Record<AlarmCode, string>;
43
164
  interface DeviceInfoType {
44
165
  status: StatusType;
45
166
  nvm: {
46
167
  user_parameters: UserParametersType;
168
+ total_counters: TotalCountersType;
169
+ service_counters: ServiceCountersType;
170
+ alarms_log: AlarmsLogType;
171
+ regeneration: RegenerationDataType;
47
172
  };
48
173
  }
49
174
  /**
@@ -99,4 +224,5 @@ interface DiscoveredDevice {
99
224
  /** Signal strength in dBm (optional, not all platforms provide this) */
100
225
  rssi?: number;
101
226
  }
102
- export type { BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, GeneralFlagsType, PelletAutonomyType, StatusType, TemperaturesType, UserParametersType, };
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 };
@@ -1,2 +1,66 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AlarmDescriptions = exports.AlarmCode = void 0;
4
+ /**
5
+ * Alarm type codes from Edilkamin devices.
6
+ * Based on AlarmsEnum.java from Android app (version 1.3.1-RC2 released 2025/12/10).
7
+ */
8
+ var AlarmCode;
9
+ (function (AlarmCode) {
10
+ AlarmCode[AlarmCode["NONE"] = 0] = "NONE";
11
+ AlarmCode[AlarmCode["FLUE_BLOCK"] = 1] = "FLUE_BLOCK";
12
+ AlarmCode[AlarmCode["SMOKE_EXTRACTOR_FAILURE"] = 2] = "SMOKE_EXTRACTOR_FAILURE";
13
+ AlarmCode[AlarmCode["END_PELLET"] = 3] = "END_PELLET";
14
+ AlarmCode[AlarmCode["MISSING_LIGHTING"] = 4] = "MISSING_LIGHTING";
15
+ AlarmCode[AlarmCode["NO_NAME_ALARM"] = 5] = "NO_NAME_ALARM";
16
+ AlarmCode[AlarmCode["SMOKE_PROBE_FAILURE"] = 6] = "SMOKE_PROBE_FAILURE";
17
+ AlarmCode[AlarmCode["FUMES_OVERTEMPERATURE"] = 7] = "FUMES_OVERTEMPERATURE";
18
+ AlarmCode[AlarmCode["PELLET_TANK_SAFETY_THERMOSTAT"] = 8] = "PELLET_TANK_SAFETY_THERMOSTAT";
19
+ AlarmCode[AlarmCode["GEAR_MOTOR_FAILURE"] = 9] = "GEAR_MOTOR_FAILURE";
20
+ AlarmCode[AlarmCode["BOARD_OVER_TEMPERATURE"] = 10] = "BOARD_OVER_TEMPERATURE";
21
+ AlarmCode[AlarmCode["SAFETY_PRESSURE_SWITCH_INTERVENTION"] = 11] = "SAFETY_PRESSURE_SWITCH_INTERVENTION";
22
+ AlarmCode[AlarmCode["ROOM_PROBE_FAILURE"] = 12] = "ROOM_PROBE_FAILURE";
23
+ AlarmCode[AlarmCode["ROOM_PROBE_2_OR_BOILER_PROBE_FAILURE"] = 13] = "ROOM_PROBE_2_OR_BOILER_PROBE_FAILURE";
24
+ AlarmCode[AlarmCode["ROOM_PROBE_3_OR_BOILER_PROBE_FAILURE"] = 14] = "ROOM_PROBE_3_OR_BOILER_PROBE_FAILURE";
25
+ AlarmCode[AlarmCode["WATER_EARTHQUAKE_SAFETY_THERMOSTAT_INTERVENTION"] = 15] = "WATER_EARTHQUAKE_SAFETY_THERMOSTAT_INTERVENTION";
26
+ AlarmCode[AlarmCode["WATER_PRESSURE_TRANSDUCER_FAILURE"] = 16] = "WATER_PRESSURE_TRANSDUCER_FAILURE";
27
+ AlarmCode[AlarmCode["OUTSIDE_PROBE_OR_LOW_STORAGE_PROBE_FAILURE"] = 17] = "OUTSIDE_PROBE_OR_LOW_STORAGE_PROBE_FAILURE";
28
+ AlarmCode[AlarmCode["PUFFER_PROBE_FAILURE"] = 18] = "PUFFER_PROBE_FAILURE";
29
+ AlarmCode[AlarmCode["CRUCIBLE_CLEANING_FAILURE"] = 19] = "CRUCIBLE_CLEANING_FAILURE";
30
+ AlarmCode[AlarmCode["TRIAC_FAILURE"] = 20] = "TRIAC_FAILURE";
31
+ AlarmCode[AlarmCode["BLACKOUT"] = 21] = "BLACKOUT";
32
+ AlarmCode[AlarmCode["OPEN_DOOR"] = 22] = "OPEN_DOOR";
33
+ AlarmCode[AlarmCode["OVERTEMPERATURE_PANEL"] = 23] = "OVERTEMPERATURE_PANEL";
34
+ AlarmCode[AlarmCode["BOARD_FUSE"] = 24] = "BOARD_FUSE";
35
+ })(AlarmCode || (exports.AlarmCode = AlarmCode = {}));
36
+ /**
37
+ * Human-readable descriptions for alarm codes.
38
+ */
39
+ const AlarmDescriptions = {
40
+ [AlarmCode.NONE]: "No alarm",
41
+ [AlarmCode.FLUE_BLOCK]: "Flue/chimney blockage",
42
+ [AlarmCode.SMOKE_EXTRACTOR_FAILURE]: "Smoke extractor motor failure",
43
+ [AlarmCode.END_PELLET]: "Pellet tank empty",
44
+ [AlarmCode.MISSING_LIGHTING]: "Ignition failure",
45
+ [AlarmCode.NO_NAME_ALARM]: "Unnamed alarm",
46
+ [AlarmCode.SMOKE_PROBE_FAILURE]: "Smoke temperature probe failure",
47
+ [AlarmCode.FUMES_OVERTEMPERATURE]: "Exhaust overtemperature",
48
+ [AlarmCode.PELLET_TANK_SAFETY_THERMOSTAT]: "Pellet tank safety thermostat triggered",
49
+ [AlarmCode.GEAR_MOTOR_FAILURE]: "Gear motor/auger failure",
50
+ [AlarmCode.BOARD_OVER_TEMPERATURE]: "Control board overtemperature",
51
+ [AlarmCode.SAFETY_PRESSURE_SWITCH_INTERVENTION]: "Safety pressure switch activated",
52
+ [AlarmCode.ROOM_PROBE_FAILURE]: "Room temperature probe failure",
53
+ [AlarmCode.ROOM_PROBE_2_OR_BOILER_PROBE_FAILURE]: "Room probe 2 or boiler probe failure",
54
+ [AlarmCode.ROOM_PROBE_3_OR_BOILER_PROBE_FAILURE]: "Room probe 3 or boiler probe failure",
55
+ [AlarmCode.WATER_EARTHQUAKE_SAFETY_THERMOSTAT_INTERVENTION]: "Water/earthquake safety thermostat",
56
+ [AlarmCode.WATER_PRESSURE_TRANSDUCER_FAILURE]: "Water pressure transducer failure",
57
+ [AlarmCode.OUTSIDE_PROBE_OR_LOW_STORAGE_PROBE_FAILURE]: "Outside probe or low storage probe failure",
58
+ [AlarmCode.PUFFER_PROBE_FAILURE]: "Buffer tank probe failure",
59
+ [AlarmCode.CRUCIBLE_CLEANING_FAILURE]: "Crucible cleaning failure",
60
+ [AlarmCode.TRIAC_FAILURE]: "Power control (TRIAC) failure",
61
+ [AlarmCode.BLACKOUT]: "Power outage detected",
62
+ [AlarmCode.OPEN_DOOR]: "Door open alarm",
63
+ [AlarmCode.OVERTEMPERATURE_PANEL]: "Panel overtemperature",
64
+ [AlarmCode.BOARD_FUSE]: "Control board fuse issue",
65
+ };
66
+ exports.AlarmDescriptions = AlarmDescriptions;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edilkamin",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "",
5
5
  "main": "dist/cjs/src/index.js",
6
6
  "module": "dist/esm/src/index.js",
@@ -14,6 +14,7 @@ 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
16
  import { clearSession, createFileStorage } from "./token-storage";
17
+ import { AlarmCode, AlarmDescriptions } from "./types";
17
18
  const promptPassword = () => {
18
19
  const rl = readline.createInterface({
19
20
  input: process.stdin,
@@ -222,6 +223,84 @@ const createProgram = () => {
222
223
  description: "Retrieve estimated pellet autonomy time",
223
224
  getter: (api, jwtToken, mac) => api.getPelletAutonomyTime(jwtToken, mac),
224
225
  },
226
+ // Statistics getters
227
+ {
228
+ commandName: "getTotalCounters",
229
+ description: "Get lifetime operating counters (power-ons, runtime by power level)",
230
+ getter: (api, jwtToken, mac) => api.getTotalCounters(jwtToken, mac),
231
+ },
232
+ {
233
+ commandName: "getServiceCounters",
234
+ description: "Get service counters (runtime since last maintenance)",
235
+ getter: (api, jwtToken, mac) => api.getServiceCounters(jwtToken, mac),
236
+ },
237
+ {
238
+ commandName: "getRegenerationData",
239
+ description: "Get regeneration and maintenance data",
240
+ getter: (api, jwtToken, mac) => api.getRegenerationData(jwtToken, mac),
241
+ },
242
+ {
243
+ commandName: "getServiceTime",
244
+ description: "Get total service time in hours",
245
+ getter: (api, jwtToken, mac) => api.getServiceTime(jwtToken, mac),
246
+ },
247
+ // Analytics getters
248
+ {
249
+ commandName: "getTotalOperatingHours",
250
+ description: "Get total operating hours across all power levels",
251
+ getter: (api, jwtToken, mac) => api.getTotalOperatingHours(jwtToken, mac),
252
+ },
253
+ {
254
+ commandName: "getPowerDistribution",
255
+ description: "Get power level usage distribution as percentages",
256
+ getter: (api, jwtToken, mac) => __awaiter(void 0, void 0, void 0, function* () {
257
+ const result = yield api.getPowerDistribution(jwtToken, mac);
258
+ return {
259
+ p1: `${result.p1.toFixed(1)}%`,
260
+ p2: `${result.p2.toFixed(1)}%`,
261
+ p3: `${result.p3.toFixed(1)}%`,
262
+ p4: `${result.p4.toFixed(1)}%`,
263
+ p5: `${result.p5.toFixed(1)}%`,
264
+ };
265
+ }),
266
+ },
267
+ {
268
+ commandName: "getServiceStatus",
269
+ description: "Get service status including whether maintenance is due",
270
+ getter: (api, jwtToken, mac) => api.getServiceStatus(jwtToken, mac),
271
+ },
272
+ {
273
+ commandName: "getUsageAnalytics",
274
+ description: "Get comprehensive usage analytics in single response",
275
+ getter: (api, jwtToken, mac) => __awaiter(void 0, void 0, void 0, function* () {
276
+ var _a;
277
+ const analytics = yield api.getUsageAnalytics(jwtToken, mac);
278
+ return {
279
+ lifetime: {
280
+ powerOnCount: analytics.totalPowerOns,
281
+ totalOperatingHours: analytics.totalOperatingHours,
282
+ blackoutCount: analytics.blackoutCount,
283
+ },
284
+ powerDistribution: {
285
+ p1: `${analytics.powerDistribution.p1.toFixed(1)}%`,
286
+ p2: `${analytics.powerDistribution.p2.toFixed(1)}%`,
287
+ p3: `${analytics.powerDistribution.p3.toFixed(1)}%`,
288
+ p4: `${analytics.powerDistribution.p4.toFixed(1)}%`,
289
+ p5: `${analytics.powerDistribution.p5.toFixed(1)}%`,
290
+ },
291
+ service: {
292
+ totalServiceHours: analytics.serviceStatus.totalServiceHours,
293
+ hoursSinceLastService: analytics.serviceStatus.hoursSinceService,
294
+ thresholdHours: analytics.serviceStatus.serviceThresholdHours,
295
+ isServiceDue: analytics.serviceStatus.isServiceDue,
296
+ lastMaintenanceDate: ((_a = analytics.lastMaintenanceDate) === null || _a === void 0 ? void 0 : _a.toISOString()) || "Never",
297
+ },
298
+ alarms: {
299
+ totalCount: analytics.alarmCount,
300
+ },
301
+ };
302
+ }),
303
+ },
225
304
  ].forEach(({ commandName, description, getter }) => {
226
305
  addLegacyOption(addMacOption(addAuthOptions(program.command(commandName).description(description)))).action((options) => executeGetter(options, getter));
227
306
  });
@@ -403,6 +482,32 @@ const createProgram = () => {
403
482
  const result = yield api.setTargetTemperature(jwtToken, normalizedMac, index, value);
404
483
  console.log(JSON.stringify(result, null, 2));
405
484
  }));
485
+ // Alarm history command with human-readable descriptions
486
+ addLegacyOption(addMacOption(addAuthOptions(program
487
+ .command("getAlarmHistory")
488
+ .description("Get alarm history log with human-readable descriptions")))).action((options) => __awaiter(void 0, void 0, void 0, function* () {
489
+ const { username, password, mac, legacy = false } = options;
490
+ const normalizedMac = mac.replace(/:/g, "");
491
+ const storage = createFileStorage();
492
+ configureAmplify(storage);
493
+ let jwtToken;
494
+ try {
495
+ jwtToken = yield getSession(false, legacy);
496
+ }
497
+ catch (_a) {
498
+ if (!username) {
499
+ throw new Error("No session found. Please provide --username to sign in.");
500
+ }
501
+ const pwd = password || (yield promptPassword());
502
+ jwtToken = yield signIn(username, pwd, legacy);
503
+ }
504
+ const apiUrl = legacy ? OLD_API_URL : NEW_API_URL;
505
+ const api = configure(apiUrl);
506
+ const result = yield api.getAlarmHistory(jwtToken, normalizedMac);
507
+ // Format alarms with human-readable descriptions
508
+ const formattedAlarms = result.alarms.map((alarm) => (Object.assign(Object.assign({}, alarm), { typeName: AlarmCode[alarm.type] || "UNKNOWN", description: AlarmDescriptions[alarm.type] || "Unknown alarm", date: new Date(alarm.timestamp * 1000).toISOString() })));
509
+ console.log(JSON.stringify(Object.assign(Object.assign({}, result), { alarms: formattedAlarms }), null, 2));
510
+ }));
406
511
  // Command: register
407
512
  addLegacyOption(addAuthOptions(program
408
513
  .command("register")
@@ -3,5 +3,6 @@ export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
3
3
  export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
4
4
  export { configure, getSession, signIn } from "./library";
5
5
  export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
6
- export { BufferEncodedType, CommandsType, DeviceAssociationBody, DeviceAssociationResponse, DeviceInfoRawType, DeviceInfoType, DiscoveredDevice, EditDeviceAssociationBody, StatusType, TemperaturesType, UserParametersType, } from "./types";
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
8
  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>;
@@ -4,4 +4,5 @@ export { decompressBuffer, isBuffer, processResponse } from "./buffer-utils";
4
4
  export { API_URL, NEW_API_URL, OLD_API_URL } from "./constants";
5
5
  export { configure, getSession, signIn } from "./library";
6
6
  export { serialNumberDisplay, serialNumberFromHex, serialNumberToHex, } from "./serial-utils";
7
+ export { AlarmCode, AlarmDescriptions } from "./types";
7
8
  export const { deviceInfo, registerDevice, editDevice, setPower, setPowerOff, setPowerOn, getPower, getEnvironmentTemperature, getTargetTemperature, setTargetTemperature, } = configure();
@@ -1,5 +1,5 @@
1
1
  import * as amplifyAuth from "aws-amplify/auth";
2
- import { DeviceAssociationResponse, DeviceInfoType } from "./types";
2
+ import { AlarmsLogType, DeviceAssociationResponse, DeviceInfoType, PowerDistributionType, RegenerationDataType, ServiceCountersType, ServiceStatusType, TotalCountersType, UsageAnalyticsType } from "./types";
3
3
  /**
4
4
  * Generates headers with a JWT token for authenticated requests.
5
5
  * @param {string} jwtToken - The JWT token for authorization.
@@ -81,5 +81,14 @@ declare const configure: (baseURL?: string) => {
81
81
  getLanguage: (jwtToken: string, macAddress: string) => Promise<number>;
82
82
  getPelletInReserve: (jwtToken: string, macAddress: string) => Promise<boolean>;
83
83
  getPelletAutonomyTime: (jwtToken: string, macAddress: string) => Promise<number>;
84
+ getTotalCounters: (jwtToken: string, macAddress: string) => Promise<TotalCountersType>;
85
+ getServiceCounters: (jwtToken: string, macAddress: string) => Promise<ServiceCountersType>;
86
+ getAlarmHistory: (jwtToken: string, macAddress: string) => Promise<AlarmsLogType>;
87
+ getRegenerationData: (jwtToken: string, macAddress: string) => Promise<RegenerationDataType>;
88
+ getServiceTime: (jwtToken: string, macAddress: string) => Promise<number>;
89
+ getTotalOperatingHours: (jwtToken: string, macAddress: string) => Promise<number>;
90
+ getPowerDistribution: (jwtToken: string, macAddress: string) => Promise<PowerDistributionType>;
91
+ getServiceStatus: (jwtToken: string, macAddress: string, thresholdHours?: number) => Promise<ServiceStatusType>;
92
+ getUsageAnalytics: (jwtToken: string, macAddress: string, serviceThreshold?: number) => Promise<UsageAnalyticsType>;
84
93
  };
85
94
  export { configure, configureAmplify, createAuthService, getSession, headers, signIn, };
@@ -473,6 +473,194 @@ const getPelletAutonomyTime = (baseURL) =>
473
473
  const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
474
474
  return info.status.pellet.autonomy_time;
475
475
  });
476
+ const getTotalCounters = (baseURL) =>
477
+ /**
478
+ * Retrieves lifetime operating counters.
479
+ * Includes power-on count and runtime hours per power level.
480
+ * These counters are never reset.
481
+ *
482
+ * @param {string} jwtToken - The JWT token for authentication.
483
+ * @param {string} macAddress - The MAC address of the device.
484
+ * @returns {Promise<TotalCountersType>} - Lifetime operating statistics.
485
+ */
486
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
487
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
488
+ return info.nvm.total_counters;
489
+ });
490
+ const getServiceCounters = (baseURL) =>
491
+ /**
492
+ * Retrieves service counters (runtime since last maintenance).
493
+ * These counters track hours per power level since last service reset.
494
+ *
495
+ * @param {string} jwtToken - The JWT token for authentication.
496
+ * @param {string} macAddress - The MAC address of the device.
497
+ * @returns {Promise<ServiceCountersType>} - Service tracking statistics.
498
+ */
499
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
500
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
501
+ return info.nvm.service_counters;
502
+ });
503
+ const getAlarmHistory = (baseURL) =>
504
+ /**
505
+ * Retrieves the alarm history log.
506
+ * Contains a circular buffer of recent alarms with timestamps.
507
+ *
508
+ * @param {string} jwtToken - The JWT token for authentication.
509
+ * @param {string} macAddress - The MAC address of the device.
510
+ * @returns {Promise<AlarmsLogType>} - Alarm history log.
511
+ */
512
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
513
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
514
+ return info.nvm.alarms_log;
515
+ });
516
+ const getRegenerationData = (baseURL) =>
517
+ /**
518
+ * Retrieves regeneration and maintenance data.
519
+ * Includes blackout counter and last intervention timestamp.
520
+ *
521
+ * @param {string} jwtToken - The JWT token for authentication.
522
+ * @param {string} macAddress - The MAC address of the device.
523
+ * @returns {Promise<RegenerationDataType>} - Maintenance tracking data.
524
+ */
525
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
526
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
527
+ return info.nvm.regeneration;
528
+ });
529
+ const getServiceTime = (baseURL) =>
530
+ /**
531
+ * Retrieves the total service time in hours.
532
+ *
533
+ * @param {string} jwtToken - The JWT token for authentication.
534
+ * @param {string} macAddress - The MAC address of the device.
535
+ * @returns {Promise<number>} - Total service hours.
536
+ */
537
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
538
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
539
+ return info.status.counters.service_time;
540
+ });
541
+ /**
542
+ * Default service threshold in hours (from OEM parameters).
543
+ * Most devices use 2000 hours.
544
+ */
545
+ const DEFAULT_SERVICE_THRESHOLD = 2000;
546
+ const getTotalOperatingHours = (baseURL) =>
547
+ /**
548
+ * Calculates total operating hours across all power levels.
549
+ *
550
+ * @param {string} jwtToken - The JWT token for authentication.
551
+ * @param {string} macAddress - The MAC address of the device.
552
+ * @returns {Promise<number>} - Total operating hours.
553
+ */
554
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
555
+ const counters = yield getTotalCounters(baseURL)(jwtToken, macAddress);
556
+ return (counters.p1_working_time +
557
+ counters.p2_working_time +
558
+ counters.p3_working_time +
559
+ counters.p4_working_time +
560
+ counters.p5_working_time);
561
+ });
562
+ const getPowerDistribution = (baseURL) =>
563
+ /**
564
+ * Calculates power level usage distribution as percentages.
565
+ *
566
+ * @param {string} jwtToken - The JWT token for authentication.
567
+ * @param {string} macAddress - The MAC address of the device.
568
+ * @returns {Promise<PowerDistributionType>} - Percentage time at each power level.
569
+ */
570
+ (jwtToken, macAddress) => __awaiter(void 0, void 0, void 0, function* () {
571
+ const counters = yield getTotalCounters(baseURL)(jwtToken, macAddress);
572
+ const total = counters.p1_working_time +
573
+ counters.p2_working_time +
574
+ counters.p3_working_time +
575
+ counters.p4_working_time +
576
+ counters.p5_working_time;
577
+ if (total === 0) {
578
+ return { p1: 0, p2: 0, p3: 0, p4: 0, p5: 0 };
579
+ }
580
+ return {
581
+ p1: (counters.p1_working_time / total) * 100,
582
+ p2: (counters.p2_working_time / total) * 100,
583
+ p3: (counters.p3_working_time / total) * 100,
584
+ p4: (counters.p4_working_time / total) * 100,
585
+ p5: (counters.p5_working_time / total) * 100,
586
+ };
587
+ });
588
+ const getServiceStatus = (baseURL) =>
589
+ /**
590
+ * Calculates service status including whether maintenance is due.
591
+ *
592
+ * @param {string} jwtToken - The JWT token for authentication.
593
+ * @param {string} macAddress - The MAC address of the device.
594
+ * @param {number} [thresholdHours=2000] - Service threshold in hours.
595
+ * @returns {Promise<ServiceStatusType>} - Service status with computed fields.
596
+ */
597
+ (jwtToken_1, macAddress_1, ...args_1) => __awaiter(void 0, [jwtToken_1, macAddress_1, ...args_1], void 0, function* (jwtToken, macAddress, thresholdHours = DEFAULT_SERVICE_THRESHOLD) {
598
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
599
+ const serviceCounters = info.nvm.service_counters;
600
+ const hoursSinceService = serviceCounters.p1_working_time +
601
+ serviceCounters.p2_working_time +
602
+ serviceCounters.p3_working_time +
603
+ serviceCounters.p4_working_time +
604
+ serviceCounters.p5_working_time;
605
+ return {
606
+ totalServiceHours: info.status.counters.service_time,
607
+ hoursSinceService,
608
+ serviceThresholdHours: thresholdHours,
609
+ isServiceDue: hoursSinceService >= thresholdHours,
610
+ };
611
+ });
612
+ const getUsageAnalytics = (baseURL) =>
613
+ /**
614
+ * Retrieves comprehensive usage analytics in a single call.
615
+ * Combines multiple statistics into a unified analytics object.
616
+ *
617
+ * @param {string} jwtToken - The JWT token for authentication.
618
+ * @param {string} macAddress - The MAC address of the device.
619
+ * @param {number} [serviceThreshold=2000] - Service threshold in hours.
620
+ * @returns {Promise<UsageAnalyticsType>} - Comprehensive usage analytics.
621
+ */
622
+ (jwtToken_1, macAddress_1, ...args_1) => __awaiter(void 0, [jwtToken_1, macAddress_1, ...args_1], void 0, function* (jwtToken, macAddress, serviceThreshold = DEFAULT_SERVICE_THRESHOLD) {
623
+ const info = yield deviceInfo(baseURL)(jwtToken, macAddress);
624
+ const totalCounters = info.nvm.total_counters;
625
+ const serviceCounters = info.nvm.service_counters;
626
+ const regeneration = info.nvm.regeneration;
627
+ const alarmsLog = info.nvm.alarms_log;
628
+ const totalOperatingHours = totalCounters.p1_working_time +
629
+ totalCounters.p2_working_time +
630
+ totalCounters.p3_working_time +
631
+ totalCounters.p4_working_time +
632
+ totalCounters.p5_working_time;
633
+ const hoursSinceService = serviceCounters.p1_working_time +
634
+ serviceCounters.p2_working_time +
635
+ serviceCounters.p3_working_time +
636
+ serviceCounters.p4_working_time +
637
+ serviceCounters.p5_working_time;
638
+ const powerDistribution = totalOperatingHours === 0
639
+ ? { p1: 0, p2: 0, p3: 0, p4: 0, p5: 0 }
640
+ : {
641
+ p1: (totalCounters.p1_working_time / totalOperatingHours) * 100,
642
+ p2: (totalCounters.p2_working_time / totalOperatingHours) * 100,
643
+ p3: (totalCounters.p3_working_time / totalOperatingHours) * 100,
644
+ p4: (totalCounters.p4_working_time / totalOperatingHours) * 100,
645
+ p5: (totalCounters.p5_working_time / totalOperatingHours) * 100,
646
+ };
647
+ return {
648
+ totalPowerOns: totalCounters.power_ons,
649
+ totalOperatingHours,
650
+ powerDistribution,
651
+ serviceStatus: {
652
+ totalServiceHours: info.status.counters.service_time,
653
+ hoursSinceService,
654
+ serviceThresholdHours: serviceThreshold,
655
+ isServiceDue: hoursSinceService >= serviceThreshold,
656
+ },
657
+ blackoutCount: regeneration.blackout_counter,
658
+ lastMaintenanceDate: regeneration.last_intervention > 0
659
+ ? new Date(regeneration.last_intervention * 1000)
660
+ : null,
661
+ alarmCount: alarmsLog.number,
662
+ };
663
+ });
476
664
  const registerDevice = (baseURL) =>
477
665
  /**
478
666
  * Registers a device with the user's account.
@@ -572,5 +760,16 @@ const configure = (baseURL = API_URL) => ({
572
760
  getLanguage: getLanguage(baseURL),
573
761
  getPelletInReserve: getPelletInReserve(baseURL),
574
762
  getPelletAutonomyTime: getPelletAutonomyTime(baseURL),
763
+ // Statistics getters
764
+ getTotalCounters: getTotalCounters(baseURL),
765
+ getServiceCounters: getServiceCounters(baseURL),
766
+ getAlarmHistory: getAlarmHistory(baseURL),
767
+ getRegenerationData: getRegenerationData(baseURL),
768
+ getServiceTime: getServiceTime(baseURL),
769
+ // Analytics functions
770
+ getTotalOperatingHours: getTotalOperatingHours(baseURL),
771
+ getPowerDistribution: getPowerDistribution(baseURL),
772
+ getServiceStatus: getServiceStatus(baseURL),
773
+ getUsageAnalytics: getUsageAnalytics(baseURL),
575
774
  });
576
775
  export { configure, configureAmplify, createAuthService, getSession, headers, signIn, };