Improve MQTT behavior and add experimental parsing for color temp support from Plejd API (#298)

* Update underlying docker containers and dependencies.
* Minor linting and code issues fixes
* Update supported devices section
* Improve Mqtt message properties - retain, etc.
- Retain discovery messages
- Don't retain others
- Set QoS to 1 consistently to ensure at least once delivery
- Set session timeout to ensure a reasonable TTL on messages
* Code and logic to remove any retained mqtt messages for SET/STATE/AVAILABILITY
* Temporary restructure of init flow for mqtt.
- No longer wait for HA birth message
- Don't listen to incoming messages until old retained messages have been purged.
- More details in https://github.com/icanos/hassio-plejd/issues/218
* Fix lingering incorrect access of connectedDevice.id
* Fix to avoid Home Assistant setting retain flag on MQTT SET STATE messages
* Parse new TRAIT=15, assuming this means dimmable and tunable white
* Clarify TRAITS bitmask values
* Add experimental parsing for color temp support from Plejd API
* Lint fixes
* Remove null coalescing operator since we don't compile code
* Handle case where outputSettings is null in PlejdApi
* Solve MQTT errors due to deprecated api color_temp and unsupported removal of retained state messages
This commit is contained in:
Victor 2025-08-05 19:55:50 +02:00 committed by GitHub
parent a789d913d7
commit b3c6334f0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 255 additions and 147 deletions

View file

@ -11,9 +11,10 @@ const API_SITE_LIST_URL = 'functions/getSiteList';
const API_SITE_DETAILS_URL = 'functions/getSiteById';
const TRAITS = {
NO_LOAD: 0,
NON_DIMMABLE: 9,
DIMMABLE: 11,
NO_LOAD: 0, // 0b0000
NON_DIMMABLE: 9, // 0b1001
DIMMABLE: 11, // 0b1011
DIMMABLE_COLORTEMP: 15, // 0b1111
};
const logger = Logger.getLogger('plejd-api');
@ -338,8 +339,10 @@ class PlejdApi {
description: 'Dali broadcast with dimmer and tuneable white support',
type: 'light',
dimmable: true,
colorTemp: true,
broadcastClicks: false,
};
// 13: Non-dimmable generic light
case 14:
return {
name: 'DIM-01',
@ -395,6 +398,7 @@ class PlejdApi {
description: '1-channel LED dimmer/driver with tuneable white, 10 W',
type: 'light',
dimmable: true,
colorTemp: true,
broadcastClicks: false,
};
case 167:
@ -403,6 +407,7 @@ class PlejdApi {
description: 'Smart tunable downlight with a built-in dimmer function, 8W',
type: 'light',
dimmable: true,
colorTemp: true,
broadcastClicks: false,
};
case 199:
@ -411,6 +416,7 @@ class PlejdApi {
description: 'Smart tunable downlight with a built-in dimmer function, 8W',
type: 'light',
dimmable: true,
colorTemp: true,
broadcastClicks: false,
};
// PLEASE CREATE AN ISSUE WITH THE HARDWARE ID if you own one of these devices!
@ -480,8 +486,18 @@ class PlejdApi {
(x) => x.deviceId === device.deviceId,
);
const dimmable = device.traits === TRAITS.DIMMABLE;
// dimmable = settings.dimCurve !== 'NonDimmable';
const dimmable =
device.traits === TRAITS.DIMMABLE || device.traits === TRAITS.DIMMABLE_COLORTEMP;
// Alternate approach looks at outputSettings.dimCurve and outputSettings.predefinedLoad
// 1. outputSettings.dimCurve === null: Not dimmable
// 2. outputSettings.dimCurve NOT IN ["NonDimmable", "RelayNormal"]: Dimmable
// 3. outputSettings.predefinedLoad !== null && outputSettings.predefinedLoad.loadType === "DWN": Dimmable
const colorTemp =
outputSettings &&
outputSettings.colorTemperature &&
outputSettings.colorTemperature.behavior === 'adjustable';
try {
const decodedDeviceType = this._getDeviceType(plejdDevice);
@ -499,6 +515,8 @@ class PlejdApi {
/** @type {import('types/DeviceRegistry').OutputDevice} */
const outputDevice = {
bleOutputAddress,
colorTemp,
colorTempSettings: outputSettings ? outputSettings.colorTemperature : null,
deviceId: device.deviceId,
dimmable,
name: device.title,
@ -604,6 +622,7 @@ class PlejdApi {
const newDevice = {
bleOutputAddress: roomAddress,
deviceId: null,
colorTemp: false,
dimmable,
name: room.title,
output: undefined,
@ -633,6 +652,7 @@ class PlejdApi {
/** @type {import('types/DeviceRegistry').OutputDevice} */
const newScene = {
bleOutputAddress: sceneNum,
colorTemp: false,
deviceId: undefined,
dimmable: false,
name: scene.title,