26 Commits

Author SHA1 Message Date
dependabot[bot]
aebbf175d3 chore(deps-dev): Bump the dev-dependencies group across 1 directory with 5 updates
Bumps the dev-dependencies group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@semantic-release/npm](https://github.com/semantic-release/npm) | `12.0.2` | `13.1.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.6.2` | `24.8.1` |
| [eslint](https://github.com/eslint/eslint) | `9.37.0` | `9.38.0` |
| [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) | `60.8.1` | `61.1.4` |
| [semantic-release](https://github.com/semantic-release/semantic-release) | `24.2.9` | `25.0.1` |



Updates `@semantic-release/npm` from 12.0.2 to 13.1.1
- [Release notes](https://github.com/semantic-release/npm/releases)
- [Commits](https://github.com/semantic-release/npm/compare/v12.0.2...v13.1.1)

Updates `@types/node` from 24.6.2 to 24.8.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 9.37.0 to 9.38.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.37.0...v9.38.0)

Updates `eslint-plugin-jsdoc` from 60.8.1 to 61.1.4
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v60.8.1...v61.1.4)

Updates `semantic-release` from 24.2.9 to 25.0.1
- [Release notes](https://github.com/semantic-release/semantic-release/releases)
- [Commits](https://github.com/semantic-release/semantic-release/compare/v24.2.9...v25.0.1)

---
updated-dependencies:
- dependency-name: "@semantic-release/npm"
  dependency-version: 13.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
- dependency-name: "@types/node"
  dependency-version: 24.8.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: eslint
  dependency-version: 9.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: eslint-plugin-jsdoc
  dependency-version: 61.1.4
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
- dependency-name: semantic-release
  dependency-version: 25.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 04:42:45 +00:00
Pascal Bourque
3b5dafeda9 fix: Fatal error when starting realtime updates. (#64)
Via https://github.com/bourquep/mysa-js-sdk/pull/144
2025-10-05 15:08:07 -04:00
Pascal Bourque
35f2effe9c chore(deps): Updated all dependencies to their latest versions (#62) 2025-10-05 11:43:49 -04:00
dependabot[bot]
c29eae97ed chore(deps-dev): Bump the dev-dependencies group with 9 updates (#57) 2025-10-05 15:22:33 +00:00
dependabot[bot]
6502b76b77 chore(deps): Bump pino-pretty from 13.0.0 to 13.1.1 (#55) 2025-10-05 15:09:30 +00:00
dependabot[bot]
39d0e64dc0 chore(deps): Bump axios from 1.9.0 to 1.12.1 in the npm_and_yarn group across 1 directory (#60) 2025-10-05 15:08:44 +00:00
dependabot[bot]
49c7a0fd8e chore(deps-dev): Bump tsx from 4.20.3 to 4.20.6 (#61) 2025-10-05 15:08:29 +00:00
dependabot[bot]
36539b17b1 chore(deps-dev): Bump brace-expansion from 1.1.11 to 1.1.12 in the npm_and_yarn group (#54) 2025-08-29 12:36:55 +00:00
dependabot[bot]
e1bd2e3a91 chore(deps-dev): Bump conventional-changelog-conventionalcommits from 9.0.0 to 9.1.0 (#38) 2025-08-29 12:21:56 +00:00
dependabot[bot]
be163eddca chore(deps): Bump form-data from 4.0.2 to 4.0.4 in the npm_and_yarn group (#43) 2025-08-29 12:21:44 +00:00
dependabot[bot]
8a8ab7ab07 chore(deps): Bump dotenv from 16.5.0 to 17.2.1 (#45) 2025-08-29 12:21:29 +00:00
dependabot[bot]
a2f47220bd chore(deps-dev): Bump @eslint/js from 9.29.0 to 9.34.0 (#52) 2025-08-29 12:21:07 +00:00
dependabot[bot]
ec166cce61 chore(deps-dev): Bump typescript-eslint from 8.35.0 to 8.41.0 (#53) 2025-08-29 12:20:55 +00:00
Pascal Bourque
d2f7c73d84 docs(readme): Updated compatibility matrix for BB-V2 2025-08-25 11:40:39 -04:00
dependabot[bot]
1bfb7e3add chore(deps-dev): Bump typescript-eslint from 8.34.1 to 8.35.0 (#22) 2025-06-25 14:39:05 +00:00
dependabot[bot]
e9f2335c38 chore(deps): Bump mysa-js-sdk from 1.2.0 to 1.3.0 (#20) 2025-06-25 14:36:27 +00:00
dependabot[bot]
96114d2e91 chore(deps-dev): Bump the dev-dependencies group across 1 directory with 3 updates (#16) 2025-06-21 13:39:21 +00:00
dependabot[bot]
21bc257b22 chore(deps-dev): Bump tsx from 4.19.4 to 4.20.3 (#18) 2025-06-21 13:36:54 +00:00
dependabot[bot]
16a82f93f4 chore(deps-dev): Bump @eslint/js from 9.28.0 to 9.29.0 (#17) 2025-06-21 13:35:55 +00:00
dependabot[bot]
a95aee6c27 chore(deps-dev): Bump typescript-eslint from 8.34.0 to 8.34.1 (#19) 2025-06-21 13:33:57 +00:00
dependabot[bot]
20b2866ee4 chore(deps-dev): Bump @types/node from 22.15.30 to 24.0.0 in the dev-dependencies group (#10) 2025-06-10 11:41:44 +00:00
dependabot[bot]
dd23fca857 chore(deps-dev): Bump typescript-eslint from 8.33.1 to 8.34.0 (#11) 2025-06-10 11:41:35 +00:00
Pascal Bourque
374dae1885 feat: Expose device serial number and origin (#7) 2025-06-07 10:58:41 -04:00
Pascal Bourque
2e2e64d2d0 feat: Temperature and humidity sensors (#6) 2025-06-07 09:35:48 -04:00
Pascal Bourque
57502c5fb7 docs(readme): Added a Docker Hub badge to the readme 2025-06-06 13:04:41 -04:00
Pascal Bourque
4895828426 fix(ci): Properly pass release version output to docker job 2025-06-06 12:54:08 -04:00
9 changed files with 2058 additions and 1908 deletions

View File

@@ -63,6 +63,8 @@ jobs:
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
needs: build needs: build
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
permissions: permissions:
contents: write # to be able to publish a GitHub release contents: write # to be able to publish a GitHub release
issues: write # to be able to comment on released issues issues: write # to be able to comment on released issues

View File

@@ -1,6 +1,7 @@
# mysa2mqtt # mysa2mqtt
[![NPM Version](https://img.shields.io/npm/v/mysa2mqtt)](https://www.npmjs.com/package/mysa2mqtt) [![NPM Version](https://img.shields.io/npm/v/mysa2mqtt)](https://www.npmjs.com/package/mysa2mqtt)
[![Docker Hub](https://img.shields.io/docker/pulls/bourquep/mysa2mqtt)](https://hub.docker.com/r/bourquep/mysa2mqtt)
[![CodeQL](https://github.com/bourquep/mysa2mqtt/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/bourquep/mysa2mqtt/actions/workflows/github-code-scanning/codeql) [![CodeQL](https://github.com/bourquep/mysa2mqtt/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/bourquep/mysa2mqtt/actions/workflows/github-code-scanning/codeql)
[![CI: lint, build and release](https://github.com/bourquep/mysa2mqtt/actions/workflows/ci.yml/badge.svg)](https://github.com/bourquep/mysa2mqtt/actions/workflows/ci.yml) [![CI: lint, build and release](https://github.com/bourquep/mysa2mqtt/actions/workflows/ci.yml/badge.svg)](https://github.com/bourquep/mysa2mqtt/actions/workflows/ci.yml)
@@ -17,13 +18,13 @@ home automation platforms.
## Supported hardware ## Supported hardware
| Model Number | Description | Supported | | Model Number | Description | Supported |
| ------------ | --------------------------------------------------------- | ---------------------------------------------------------------- | | ------------ | --------------------------------------------------------- | -------------------------------------------------------------------- |
| `BB-V1-X` | Mysa Smart Thermostat for Electric Baseboard Heaters V1 | ✅ Tested and working | | `BB-V1-X` | Mysa Smart Thermostat for Electric Baseboard Heaters V1 | ✅ Tested and working |
| `BB-V2-X` | Mysa Smart Thermostat for Electric Baseboard Heaters V2 | ⚠️ Should work but not tested | | `BB-V2-X` | Mysa Smart Thermostat for Electric Baseboard Heaters V2 | ⚠️ Partially working, in progress |
| `BB-V2-X-L` | Mysa Smart Thermostat LITE for Electric Baseboard Heaters | ⚠️ Should work but not tested; does not report power consumption | | `BB-V2-X-L` | Mysa Smart Thermostat LITE for Electric Baseboard Heaters | ⚠️ Partially working, in progress; does not report power consumption |
| `unknown` | Mysa Smart Thermostat for Electric In-Floor Heating | ⚠️ Should work but not tested | | `unknown` | Mysa Smart Thermostat for Electric In-Floor Heating | ⚠️ Should work but not tested |
| `AC-V1-X` | Mysa Smart Thermostat for Mini-Split Heat Pumps & AC | 🚫 Not supported (yet) | | `AC-V1-X` | Mysa Smart Thermostat for Mini-Split Heat Pumps & AC | 🚫 Not supported (yet) |
## Disclaimer ## Disclaimer
@@ -212,13 +213,11 @@ When using Home Assistant, devices will be automatically discovered and appear i
### Common Issues ### Common Issues
1. **Authentication Failures** 1. **Authentication Failures**
- Verify your Mysa username and password - Verify your Mysa username and password
- Check if session.json exists and is valid - Check if session.json exists and is valid
- Try deleting session.json to force re-authentication - Try deleting session.json to force re-authentication
2. **MQTT Connection Issues** 2. **MQTT Connection Issues**
- Verify MQTT broker hostname and port - Verify MQTT broker hostname and port
- Check MQTT credentials if authentication is required - Check MQTT credentials if authentication is required
- Ensure the MQTT broker is accessible from your network - Ensure the MQTT broker is accessible from your network
@@ -363,7 +362,6 @@ copyright notice and license text in any copy of the software or substantial por
## Acknowledgments ## Acknowledgments
- [mysa-js-sdk](https://github.com/bourquep/mysa-js-sdk) - Mysa API client library - [mysa-js-sdk](https://github.com/bourquep/mysa-js-sdk) - Mysa API client library
- This library would not be possible without the amazing work by [@dlenski](https://github.com/dlenski) in his - This library would not be possible without the amazing work by [@dlenski](https://github.com/dlenski) in his
[mysotherm](https://github.com/dlenski/mysotherm) repository. He's the one who reversed-engineered the Mysa MQTT [mysotherm](https://github.com/dlenski/mysotherm) repository. He's the one who reversed-engineered the Mysa MQTT
protocol which is being used by this library. protocol which is being used by this library.

3797
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -46,29 +46,29 @@
"build": "tsup" "build": "tsup"
}, },
"dependencies": { "dependencies": {
"commander": "14.0.0", "commander": "14.0.1",
"dotenv": "16.5.0", "dotenv": "17.2.3",
"mqtt2ha": "4.0.0", "mqtt2ha": "4.1.2",
"mysa-js-sdk": "1.1.2", "mysa-js-sdk": "1.3.3",
"pino": "9.7.0", "pino": "10.0.0",
"pino-pretty": "13.0.0" "pino-pretty": "13.1.1"
}, },
"devDependencies": { "devDependencies": {
"@commander-js/extra-typings": "14.0.0", "@commander-js/extra-typings": "14.0.0",
"@eslint/js": "9.28.0", "@eslint/js": "9.37.0",
"@semantic-release/npm": "12.0.1", "@semantic-release/npm": "13.1.1",
"@types/node": "22.15.30", "@types/node": "24.8.1",
"conventional-changelog-conventionalcommits": "9.0.0", "conventional-changelog-conventionalcommits": "9.1.0",
"eslint": "9.28.0", "eslint": "9.38.0",
"eslint-plugin-jsdoc": "50.7.1", "eslint-plugin-jsdoc": "61.1.4",
"eslint-plugin-tsdoc": "0.4.0", "eslint-plugin-tsdoc": "0.4.0",
"prettier": "3.5.3", "prettier": "3.6.2",
"prettier-plugin-jsdoc": "1.3.2", "prettier-plugin-jsdoc": "1.3.3",
"prettier-plugin-organize-imports": "4.1.0", "prettier-plugin-organize-imports": "4.3.0",
"semantic-release": "24.2.5", "semantic-release": "25.0.1",
"tsup": "8.5.0", "tsup": "8.5.0",
"tsx": "4.19.4", "tsx": "4.20.6",
"typescript": "5.8.3", "typescript": "5.9.3",
"typescript-eslint": "8.33.1" "typescript-eslint": "8.45.0"
} }
} }

View File

@@ -22,7 +22,7 @@ SOFTWARE.
*/ */
import { Logger } from 'mqtt2ha'; import { Logger } from 'mqtt2ha';
import { pino } from 'pino'; import pino from 'pino';
export class PinoLogger implements Logger { export class PinoLogger implements Logger {
constructor(private readonly logger: pino.Logger) {} constructor(private readonly logger: pino.Logger) {}
@@ -32,7 +32,7 @@ export class PinoLogger implements Logger {
if (obj) { if (obj) {
this.logger.debug(obj, message, ...meta); this.logger.debug(obj, message, ...meta);
} else { } else {
this.logger.debug(message, ...meta); this.logger.debug(null, message, ...meta);
} }
} }
@@ -41,7 +41,7 @@ export class PinoLogger implements Logger {
if (obj) { if (obj) {
this.logger.info(obj, message, ...meta); this.logger.info(obj, message, ...meta);
} else { } else {
this.logger.info(message, ...meta); this.logger.info(null, message, ...meta);
} }
} }
@@ -50,7 +50,7 @@ export class PinoLogger implements Logger {
if (obj) { if (obj) {
this.logger.warn(obj, message, ...meta); this.logger.warn(obj, message, ...meta);
} else { } else {
this.logger.warn(message, ...meta); this.logger.warn(null, message, ...meta);
} }
} }
@@ -59,7 +59,7 @@ export class PinoLogger implements Logger {
if (obj) { if (obj) {
this.logger.error(obj, message, ...meta); this.logger.error(obj, message, ...meta);
} else { } else {
this.logger.error(message, ...meta); this.logger.error(null, message, ...meta);
} }
} }
} }

View File

@@ -64,8 +64,24 @@ async function main() {
await client.login(options.mysaUsername, options.mysaPassword); await client.login(options.mysaUsername, options.mysaPassword);
} }
rootLogger.debug('Fetching devices and firmwares...');
const [devices, firmwares] = await Promise.all([client.getDevices(), client.getDeviceFirmwares()]); const [devices, firmwares] = await Promise.all([client.getDevices(), client.getDeviceFirmwares()]);
rootLogger.debug('Fetching serial numbers...');
const serialNumbers = new Map<string, string>();
for (const [deviceId] of Object.entries(devices.DevicesObj)) {
try {
const serial = await client.getDeviceSerialNumber(deviceId);
if (serial) {
serialNumbers.set(deviceId, serial);
}
} catch (error) {
rootLogger.error(error, `Failed to retrieve serial number for device ${deviceId}`);
}
}
rootLogger.debug('Initializing MQTT entities...');
const mqttSettings: MqttSettings = { const mqttSettings: MqttSettings = {
host: options.mqttHost, host: options.mqttHost,
port: options.mqttPort, port: options.mqttPort,
@@ -82,7 +98,8 @@ async function main() {
device, device,
mqttSettings, mqttSettings,
new PinoLogger(rootLogger.child({ module: 'thermostat', deviceId: device.Id })), new PinoLogger(rootLogger.child({ module: 'thermostat', deviceId: device.Id })),
firmwares.Firmware[device.Id] firmwares.Firmware[device.Id],
serialNumbers.get(device.Id)
) )
); );

View File

@@ -54,7 +54,6 @@ function getPackageVersion(): string {
* *
* @param value - The value to parse. * @param value - The value to parse.
* @returns The parsed integer value. * @returns The parsed integer value.
* @throws InvalidArgumentError if the value is not a valid integer.
*/ */
function parseRequiredInt(value: string) { function parseRequiredInt(value: string) {
const parsedValue = parseInt(value, 10); const parsedValue = parseInt(value, 10);
@@ -64,6 +63,8 @@ function parseRequiredInt(value: string) {
return parsedValue; return parsedValue;
} }
export const version = getPackageVersion();
const extraHelpText = ` const extraHelpText = `
Copyright (c) 2025 Pascal Bourque Copyright (c) 2025 Pascal Bourque
Licensed under the MIT License Licensed under the MIT License
@@ -72,7 +73,7 @@ Source code and documentation available at: https://github.com/bourquep/mysa2mqt
`; `;
export const options = new Command('mysa2mqtt') export const options = new Command('mysa2mqtt')
.version(getPackageVersion()) .version(version)
.description('Expose Mysa smart thermostats to home automation platforms via MQTT.') .description('Expose Mysa smart thermostats to home automation platforms via MQTT.')
.addHelpText('afterAll', extraHelpText) .addHelpText('afterAll', extraHelpText)
.addOption( .addOption(

View File

@@ -21,13 +21,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
import { Climate, ClimateAction, DeviceConfiguration, Logger, MqttSettings, Sensor } from 'mqtt2ha'; import {
Climate,
ClimateAction,
DeviceConfiguration,
Logger,
MqttSettings,
OriginConfiguration,
Sensor
} from 'mqtt2ha';
import { DeviceBase, FirmwareDevice, MysaApiClient, MysaDeviceMode, StateChange, Status } from 'mysa-js-sdk'; import { DeviceBase, FirmwareDevice, MysaApiClient, MysaDeviceMode, StateChange, Status } from 'mysa-js-sdk';
import { version } from './options';
export class Thermostat { export class Thermostat {
private isStarted = false; private isStarted = false;
private readonly mqttDevice: DeviceConfiguration; private readonly mqttDevice: DeviceConfiguration;
private readonly mqttOrigin: OriginConfiguration;
private readonly mqttClimate: Climate; private readonly mqttClimate: Climate;
private readonly mqttTemperature: Sensor;
private readonly mqttHumidity: Sensor;
private readonly mqttPower: Sensor; private readonly mqttPower: Sensor;
private readonly mysaStatusUpdateHandler = this.handleMysaStatusUpdate.bind(this); private readonly mysaStatusUpdateHandler = this.handleMysaStatusUpdate.bind(this);
@@ -38,14 +50,22 @@ export class Thermostat {
public readonly mysaDevice: DeviceBase, public readonly mysaDevice: DeviceBase,
private readonly mqttSettings: MqttSettings, private readonly mqttSettings: MqttSettings,
private readonly logger: Logger, private readonly logger: Logger,
public readonly mysaDeviceFirmware?: FirmwareDevice public readonly mysaDeviceFirmware?: FirmwareDevice,
public readonly mysaDeviceSerialNumber?: string
) { ) {
this.mqttDevice = { this.mqttDevice = {
identifiers: mysaDevice.Id, identifiers: mysaDevice.Id,
name: mysaDevice.Name, name: mysaDevice.Name,
manufacturer: 'Mysa', manufacturer: 'Mysa',
model: mysaDevice.Model, model: mysaDevice.Model,
sw_version: mysaDeviceFirmware?.InstalledVersion sw_version: mysaDeviceFirmware?.InstalledVersion,
serial_number: mysaDeviceSerialNumber
};
this.mqttOrigin = {
name: 'mysa2mqtt',
sw_version: version,
support_url: 'https://github.com/bourquep/mysa2mqtt'
}; };
this.mqttClimate = new Climate( this.mqttClimate = new Climate(
@@ -55,6 +75,7 @@ export class Thermostat {
component: { component: {
component: 'climate', component: 'climate',
device: this.mqttDevice, device: this.mqttDevice,
origin: this.mqttOrigin,
unique_id: `mysa_${mysaDevice.Id}_climate`, unique_id: `mysa_${mysaDevice.Id}_climate`,
name: 'Thermostat', name: 'Thermostat',
min_temp: mysaDevice.MinSetpoint, min_temp: mysaDevice.MinSetpoint,
@@ -104,13 +125,49 @@ export class Thermostat {
} }
); );
this.mqttTemperature = new Sensor({
mqtt: this.mqttSettings,
logger: this.logger,
component: {
component: 'sensor',
device: this.mqttDevice,
origin: this.mqttOrigin,
unique_id: `mysa_${mysaDevice.Id}_temperature`,
name: 'Current temperature',
device_class: 'temperature',
state_class: 'measurement',
unit_of_measurement: '°C',
suggested_display_precision: 1,
force_update: true
}
});
this.mqttHumidity = new Sensor({
mqtt: this.mqttSettings,
logger: this.logger,
component: {
component: 'sensor',
device: this.mqttDevice,
origin: this.mqttOrigin,
unique_id: `mysa_${mysaDevice.Id}_humidity`,
name: 'Current humidity',
device_class: 'humidity',
state_class: 'measurement',
unit_of_measurement: '%',
suggested_display_precision: 0,
force_update: true
}
});
this.mqttPower = new Sensor({ this.mqttPower = new Sensor({
mqtt: this.mqttSettings, mqtt: this.mqttSettings,
logger: this.logger, logger: this.logger,
component: { component: {
component: 'sensor', component: 'sensor',
device: this.mqttDevice, device: this.mqttDevice,
origin: this.mqttOrigin,
unique_id: `mysa_${mysaDevice.Id}_power`, unique_id: `mysa_${mysaDevice.Id}_power`,
name: 'Current power',
device_class: 'power', device_class: 'power',
state_class: 'measurement', state_class: 'measurement',
unit_of_measurement: 'W', unit_of_measurement: 'W',
@@ -136,9 +193,14 @@ export class Thermostat {
this.mqttClimate.currentMode = state.TstatMode.v === 1 ? 'off' : state.TstatMode.v === 3 ? 'heat' : undefined; this.mqttClimate.currentMode = state.TstatMode.v === 1 ? 'off' : state.TstatMode.v === 3 ? 'heat' : undefined;
this.mqttClimate.currentAction = this.computeCurrentAction(undefined, state.Duty.v); this.mqttClimate.currentAction = this.computeCurrentAction(undefined, state.Duty.v);
this.mqttClimate.targetTemperature = this.mqttClimate.currentMode !== 'off' ? state.SetPoint.v : undefined; this.mqttClimate.targetTemperature = this.mqttClimate.currentMode !== 'off' ? state.SetPoint.v : undefined;
await this.mqttClimate.writeConfig(); await this.mqttClimate.writeConfig();
await this.mqttTemperature.setState('state_topic', state.CorrectedTemp.v.toFixed(2));
await this.mqttTemperature.writeConfig();
await this.mqttHumidity.setState('state_topic', state.Humidity.v.toFixed(2));
await this.mqttHumidity.writeConfig();
// `state.Current.v` always has a non-zero value, even for thermostats that are off, so we can't use it to determine initial power state. // `state.Current.v` always has a non-zero value, even for thermostats that are off, so we can't use it to determine initial power state.
await this.mqttPower.setState('state_topic', 'None'); await this.mqttPower.setState('state_topic', 'None');
await this.mqttPower.writeConfig(); await this.mqttPower.writeConfig();
@@ -166,6 +228,8 @@ export class Thermostat {
this.mysaApiClient.emitter.off('stateChanged', this.mysaStateChangeHandler); this.mysaApiClient.emitter.off('stateChanged', this.mysaStateChangeHandler);
await this.mqttPower.setState('state_topic', 'None'); await this.mqttPower.setState('state_topic', 'None');
await this.mqttTemperature.setState('state_topic', 'None');
await this.mqttHumidity.setState('state_topic', 'None');
} }
private async handleMysaStatusUpdate(status: Status) { private async handleMysaStatusUpdate(status: Status) {
@@ -184,6 +248,9 @@ export class Thermostat {
} else { } else {
await this.mqttPower.setState('state_topic', 'None'); await this.mqttPower.setState('state_topic', 'None');
} }
await this.mqttTemperature.setState('state_topic', status.temperature.toFixed(2));
await this.mqttHumidity.setState('state_topic', status.humidity.toFixed(2));
} }
private async handleMysaStateChange(state: StateChange) { private async handleMysaStateChange(state: StateChange) {
@@ -200,6 +267,7 @@ export class Thermostat {
case 'heat': case 'heat':
this.mqttClimate.currentMode = 'heat'; this.mqttClimate.currentMode = 'heat';
this.mqttClimate.targetTemperature = state.setPoint;
break; break;
} }
} }

View File

@@ -8,6 +8,7 @@
"noEmit": true, "noEmit": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"module": "ESNext", "module": "ESNext",
"lib": ["ES2022"],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }