mysa-js-sdk 3.1.0 → 3.1.2

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/index.d.cts CHANGED
@@ -187,8 +187,8 @@ declare class EventEmitter<TEvents extends Record<string, any>> implements NodeJ
187
187
  removeAllListeners<TEventName extends keyof TEvents & string>(eventName?: TEventName | undefined): this;
188
188
  setMaxListeners(n: number): this;
189
189
  getMaxListeners(): number;
190
- listeners<TEventName extends keyof TEvents & string>(eventName: TEventName): Function[];
191
- rawListeners<TEventName extends keyof TEvents & string>(eventName: TEventName): Function[];
190
+ listeners<TEventName extends keyof TEvents & string>(eventName: TEventName): ((...args: any[]) => void)[];
191
+ rawListeners<TEventName extends keyof TEvents & string>(eventName: TEventName): ((...args: any[]) => void)[];
192
192
  listenerCount<TEventName extends keyof TEvents & string>(eventName: TEventName, listener?: (...args: TEvents[TEventName]) => void): number;
193
193
  prependListener<TEventName extends keyof TEvents & string>(eventName: TEventName, listener: (...args: TEvents[TEventName]) => void): this;
194
194
  prependOnceListener<TEventName extends keyof TEvents & string>(eventName: TEventName, listener: (...args: TEvents[TEventName]) => void): this;
@@ -225,6 +225,8 @@ interface SupportedCaps {
225
225
  [modeId: string]: {
226
226
  /** Array of available temperature setpoints for this mode */
227
227
  temperatures: number[];
228
+ /** Array of supported raw fan speed (fn) values for this mode, if any */
229
+ fanSpeeds?: number[];
228
230
  };
229
231
  };
230
232
  /** Version string of the capability definition */
@@ -494,6 +496,8 @@ declare enum OutMessageType {
494
496
  DEVICE_LOG = 4,
495
497
  /** Notification sent when a device completes its boot sequence */
496
498
  DEVICE_POST_BOOT = 10,
499
+ /** Periodic status report from an in-floor heating thermostat (INF-V1-0) */
500
+ DEVICE_IN_FLOOR_STATUS = 17,
497
501
  /** Version 2 device status report with enhanced device information */
498
502
  DEVICE_V2_STATUS = 40,
499
503
  /** AC device status report with temperature, humidity, setpoint, and AC-specific fields */
@@ -531,6 +535,45 @@ interface DeviceAcStatus extends MsgPayload<OutMessageType.DEVICE_AC_STATUS> {
531
535
  };
532
536
  }
533
537
 
538
+ /**
539
+ * Interface representing a periodic status report from a Mysa in-floor heating thermostat.
540
+ *
541
+ * In-floor units (`INF-V1-0`) publish their telemetry every few seconds as message type 17 rather than the
542
+ * {@link DeviceV2Status} (type 40) sent by baseboard devices. The body carries the same ambient readings plus the
543
+ * floor-probe temperature and the binary heating-relay state.
544
+ */
545
+ interface DeviceInFloorStatus extends MsgPayload<OutMessageType.DEVICE_IN_FLOOR_STATUS> {
546
+ /** Source information identifying the device sending the status */
547
+ src: {
548
+ /** Reference identifier for the device */
549
+ ref: string;
550
+ /** Type identifier for the source device */
551
+ type: number;
552
+ };
553
+ /** Status data payload containing current device measurements and settings */
554
+ body: {
555
+ /** Ambient temperature reading from the device sensor (°C) */
556
+ ambTemp: number;
557
+ /** Floor-probe temperature reading (°C) */
558
+ flrSnsrTemp?: number;
559
+ /** Relative humidity percentage */
560
+ hum: number;
561
+ /** Current temperature setpoint (°C) */
562
+ stpt: number;
563
+ /** Binary heating-relay state (0 = off, 1 = energized) */
564
+ heatStat?: number;
565
+ /**
566
+ * Reported duty cycle. Observed to stay pinned at a constant value regardless of the relay state on this message
567
+ * type, so {@link heatStat} is the reliable indicator of whether the device is heating.
568
+ */
569
+ dutyCycle?: number;
570
+ /** Which sensor the thermostat regulates against (3 = floor probe, 5 = ambient air) */
571
+ trackedSnsr?: number;
572
+ /** Line voltage (V) */
573
+ lineVtg?: number;
574
+ };
575
+ }
576
+
534
577
  /**
535
578
  * Interface representing a device state change notification from a Mysa device.
536
579
  *
@@ -622,7 +665,7 @@ interface DeviceV2Status extends MsgPayload<OutMessageType.DEVICE_V2_STATUS> {
622
665
  * This type encompasses payloads where the message type is specified in the `msg` field rather than the `MsgType`
623
666
  * field. Includes device status reports and state change notifications.
624
667
  */
625
- type MsgOutPayload = DeviceAcStatus | DeviceV2Status | DeviceStateChange;
668
+ type MsgOutPayload = DeviceAcStatus | DeviceInFloorStatus | DeviceV2Status | DeviceStateChange;
626
669
 
627
670
  /**
628
671
  * Base interface for MQTT message payloads that use the MsgType field.
@@ -1280,4 +1323,4 @@ type MsgTypeInPayload = CheckDeviceSettings | StartPublishingDeviceStatus;
1280
1323
  */
1281
1324
  type InPayload = MsgTypeInPayload | MsgInPayload;
1282
1325
 
1283
- export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, UnsupportedFanSpeedError, VoidLogger };
1326
+ export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceInFloorStatus, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, UnsupportedFanSpeedError, VoidLogger };
package/dist/index.d.ts CHANGED
@@ -187,8 +187,8 @@ declare class EventEmitter<TEvents extends Record<string, any>> implements NodeJ
187
187
  removeAllListeners<TEventName extends keyof TEvents & string>(eventName?: TEventName | undefined): this;
188
188
  setMaxListeners(n: number): this;
189
189
  getMaxListeners(): number;
190
- listeners<TEventName extends keyof TEvents & string>(eventName: TEventName): Function[];
191
- rawListeners<TEventName extends keyof TEvents & string>(eventName: TEventName): Function[];
190
+ listeners<TEventName extends keyof TEvents & string>(eventName: TEventName): ((...args: any[]) => void)[];
191
+ rawListeners<TEventName extends keyof TEvents & string>(eventName: TEventName): ((...args: any[]) => void)[];
192
192
  listenerCount<TEventName extends keyof TEvents & string>(eventName: TEventName, listener?: (...args: TEvents[TEventName]) => void): number;
193
193
  prependListener<TEventName extends keyof TEvents & string>(eventName: TEventName, listener: (...args: TEvents[TEventName]) => void): this;
194
194
  prependOnceListener<TEventName extends keyof TEvents & string>(eventName: TEventName, listener: (...args: TEvents[TEventName]) => void): this;
@@ -225,6 +225,8 @@ interface SupportedCaps {
225
225
  [modeId: string]: {
226
226
  /** Array of available temperature setpoints for this mode */
227
227
  temperatures: number[];
228
+ /** Array of supported raw fan speed (fn) values for this mode, if any */
229
+ fanSpeeds?: number[];
228
230
  };
229
231
  };
230
232
  /** Version string of the capability definition */
@@ -494,6 +496,8 @@ declare enum OutMessageType {
494
496
  DEVICE_LOG = 4,
495
497
  /** Notification sent when a device completes its boot sequence */
496
498
  DEVICE_POST_BOOT = 10,
499
+ /** Periodic status report from an in-floor heating thermostat (INF-V1-0) */
500
+ DEVICE_IN_FLOOR_STATUS = 17,
497
501
  /** Version 2 device status report with enhanced device information */
498
502
  DEVICE_V2_STATUS = 40,
499
503
  /** AC device status report with temperature, humidity, setpoint, and AC-specific fields */
@@ -531,6 +535,45 @@ interface DeviceAcStatus extends MsgPayload<OutMessageType.DEVICE_AC_STATUS> {
531
535
  };
532
536
  }
533
537
 
538
+ /**
539
+ * Interface representing a periodic status report from a Mysa in-floor heating thermostat.
540
+ *
541
+ * In-floor units (`INF-V1-0`) publish their telemetry every few seconds as message type 17 rather than the
542
+ * {@link DeviceV2Status} (type 40) sent by baseboard devices. The body carries the same ambient readings plus the
543
+ * floor-probe temperature and the binary heating-relay state.
544
+ */
545
+ interface DeviceInFloorStatus extends MsgPayload<OutMessageType.DEVICE_IN_FLOOR_STATUS> {
546
+ /** Source information identifying the device sending the status */
547
+ src: {
548
+ /** Reference identifier for the device */
549
+ ref: string;
550
+ /** Type identifier for the source device */
551
+ type: number;
552
+ };
553
+ /** Status data payload containing current device measurements and settings */
554
+ body: {
555
+ /** Ambient temperature reading from the device sensor (°C) */
556
+ ambTemp: number;
557
+ /** Floor-probe temperature reading (°C) */
558
+ flrSnsrTemp?: number;
559
+ /** Relative humidity percentage */
560
+ hum: number;
561
+ /** Current temperature setpoint (°C) */
562
+ stpt: number;
563
+ /** Binary heating-relay state (0 = off, 1 = energized) */
564
+ heatStat?: number;
565
+ /**
566
+ * Reported duty cycle. Observed to stay pinned at a constant value regardless of the relay state on this message
567
+ * type, so {@link heatStat} is the reliable indicator of whether the device is heating.
568
+ */
569
+ dutyCycle?: number;
570
+ /** Which sensor the thermostat regulates against (3 = floor probe, 5 = ambient air) */
571
+ trackedSnsr?: number;
572
+ /** Line voltage (V) */
573
+ lineVtg?: number;
574
+ };
575
+ }
576
+
534
577
  /**
535
578
  * Interface representing a device state change notification from a Mysa device.
536
579
  *
@@ -622,7 +665,7 @@ interface DeviceV2Status extends MsgPayload<OutMessageType.DEVICE_V2_STATUS> {
622
665
  * This type encompasses payloads where the message type is specified in the `msg` field rather than the `MsgType`
623
666
  * field. Includes device status reports and state change notifications.
624
667
  */
625
- type MsgOutPayload = DeviceAcStatus | DeviceV2Status | DeviceStateChange;
668
+ type MsgOutPayload = DeviceAcStatus | DeviceInFloorStatus | DeviceV2Status | DeviceStateChange;
626
669
 
627
670
  /**
628
671
  * Base interface for MQTT message payloads that use the MsgType field.
@@ -1280,4 +1323,4 @@ type MsgTypeInPayload = CheckDeviceSettings | StartPublishingDeviceStatus;
1280
1323
  */
1281
1324
  type InPayload = MsgTypeInPayload | MsgInPayload;
1282
1325
 
1283
- export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, UnsupportedFanSpeedError, VoidLogger };
1326
+ export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceInFloorStatus, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, UnsupportedFanSpeedError, VoidLogger };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  mysa-js-sdk
3
- Copyright (C) 2025 Pascal Bourque
3
+ Copyright (C) 2025-2026 Pascal Bourque
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -227,6 +227,7 @@ var OutMessageType = /* @__PURE__ */ ((OutMessageType2) => {
227
227
  OutMessageType2[OutMessageType2["DEVICE_SETPOINT_CHANGE"] = 1] = "DEVICE_SETPOINT_CHANGE";
228
228
  OutMessageType2[OutMessageType2["DEVICE_LOG"] = 4] = "DEVICE_LOG";
229
229
  OutMessageType2[OutMessageType2["DEVICE_POST_BOOT"] = 10] = "DEVICE_POST_BOOT";
230
+ OutMessageType2[OutMessageType2["DEVICE_IN_FLOOR_STATUS"] = 17] = "DEVICE_IN_FLOOR_STATUS";
230
231
  OutMessageType2[OutMessageType2["DEVICE_V2_STATUS"] = 40] = "DEVICE_V2_STATUS";
231
232
  OutMessageType2[OutMessageType2["DEVICE_AC_STATUS"] = 30] = "DEVICE_AC_STATUS";
232
233
  OutMessageType2[OutMessageType2["DEVICE_STATE_CHANGE"] = 44] = "DEVICE_STATE_CHANGE";
@@ -260,6 +261,8 @@ var MqttResetMaxDelay = dayjs.duration(30, "seconds");
260
261
  var MqttStabilityWindow = dayjs.duration(60, "seconds");
261
262
  var CanonicalFanSpeedOrder = ["auto", "low", "medium", "high", "max"];
262
263
  var LegacyFanSpeedSendMap = { auto: 1, low: 3, medium: 5, high: 7, max: 8 };
264
+ var CanonicalFanSpeedSendMap = { auto: 1, low: 2, medium: 4, high: 6 };
265
+ var CANONICAL_FAN_SPEED_CODE_NUM = 1117;
263
266
  var FanSpeedReceiveMap = {
264
267
  1: "auto",
265
268
  2: "low",
@@ -280,7 +283,7 @@ function buildFanSpeedSendMap(device) {
280
283
  var _a;
281
284
  const fanSpeeds = (_a = device.SupportedCaps) == null ? void 0 : _a.fanSpeeds;
282
285
  if (!fanSpeeds || fanSpeeds.length === 0) {
283
- return LegacyFanSpeedSendMap;
286
+ return device.CodeNum === CANONICAL_FAN_SPEED_CODE_NUM ? CanonicalFanSpeedSendMap : LegacyFanSpeedSendMap;
284
287
  }
285
288
  const map = {};
286
289
  CanonicalFanSpeedOrder.forEach((name, index) => {
@@ -1210,6 +1213,16 @@ var MysaApiClient = class {
1210
1213
  dutyCycle: parsedPayload.body.dtyCycle
1211
1214
  });
1212
1215
  break;
1216
+ case 17 /* DEVICE_IN_FLOOR_STATUS */:
1217
+ this.emitter.emit("statusChanged", {
1218
+ deviceId: parsedPayload.src.ref,
1219
+ temperature: parsedPayload.body.ambTemp,
1220
+ humidity: parsedPayload.body.hum,
1221
+ setPoint: parsedPayload.body.stpt,
1222
+ dutyCycle: parsedPayload.body.heatStat,
1223
+ floorTemperature: parsedPayload.body.flrSnsrTemp
1224
+ });
1225
+ break;
1213
1226
  case 40 /* DEVICE_V2_STATUS */:
1214
1227
  this.emitter.emit("statusChanged", {
1215
1228
  deviceId: parsedPayload.src.ref,