Device triggers for scenes implemented
This commit is contained in:
parent
b10583336e
commit
74e381f009
2 changed files with 60 additions and 18 deletions
|
|
@ -72,6 +72,8 @@ class DeviceRegistry {
|
||||||
...this.sceneDevices,
|
...this.sceneDevices,
|
||||||
[scene.uniqueId]: scene,
|
[scene.uniqueId]: scene,
|
||||||
};
|
};
|
||||||
|
this.sceneUniqueIdByBleOutputAddress[scene.bleOutputAddress] = scene.uniqueId;
|
||||||
|
|
||||||
logger.verbose(
|
logger.verbose(
|
||||||
`Added/updated scene: ${JSON.stringify(scene)}. ${
|
`Added/updated scene: ${JSON.stringify(scene)}. ${
|
||||||
Object.keys(this.sceneDevices).length
|
Object.keys(this.sceneDevices).length
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,6 @@ const MQTT_TYPES = {
|
||||||
SWITCH: 'switch',
|
SWITCH: 'switch',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMqttType = (/** @type {{ uniqueId: string; type: string; }} */ plug) => (plug.type === 'scene' ? MQTT_TYPES.SCENE : plug.type);
|
|
||||||
|
|
||||||
const getBaseTopic = (/** @type {{ uniqueId: string; type: string; }} */ plug) => `${discoveryPrefix}/${getMqttType(plug)}/${nodeId}/${plug.uniqueId}`;
|
|
||||||
const getSceneEventTopic = () => 'plejd/event/scene';
|
|
||||||
const getSubscribePath = () => `${discoveryPrefix}/+/${nodeId}/#`;
|
|
||||||
|
|
||||||
const getTopicName = (
|
|
||||||
/** @type {{ uniqueId: string; type: string; }} */ plug,
|
|
||||||
/** @type {'config' | 'state' | 'availability' | 'set'} */ topicType,
|
|
||||||
) => `${getBaseTopic(plug)}/${topicType}`;
|
|
||||||
|
|
||||||
// Very loosely check if string is a GUID/UUID
|
|
||||||
const isGuid = (s) => /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/.test(s);
|
|
||||||
|
|
||||||
const TOPICS = {
|
const TOPICS = {
|
||||||
CONFIG: 'config',
|
CONFIG: 'config',
|
||||||
STATE: 'state',
|
STATE: 'state',
|
||||||
|
|
@ -40,6 +26,21 @@ const TOPICS = {
|
||||||
COMMAND: 'set',
|
COMMAND: 'set',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getMqttType = (/** @type {{ uniqueId: string; type: string; }} */ plug) => (plug.type === 'scene' ? MQTT_TYPES.SCENE : plug.type);
|
||||||
|
|
||||||
|
const getBaseTopic = (/** @type {{ uniqueId: string; type: string; }} */ plug) => `${discoveryPrefix}/${getMqttType(plug)}/${nodeId}/${plug.uniqueId}`;
|
||||||
|
|
||||||
|
const getTopicName = (
|
||||||
|
/** @type {{ uniqueId: string; type: string; }} */ plug,
|
||||||
|
/** @type {'config' | 'state' | 'availability' | 'set'} */ topicType,
|
||||||
|
) => `${getBaseTopic(plug)}/${topicType}`;
|
||||||
|
|
||||||
|
const getSceneEventTopic = (sceneId) => `${getTopicName({ uniqueId: `${sceneId}_trigger`, type: 'device_automation' }, 'state')}`;
|
||||||
|
const getSubscribePath = () => `${discoveryPrefix}/+/${nodeId}/#`;
|
||||||
|
|
||||||
|
// Very loosely check if string is a GUID/UUID
|
||||||
|
const isGuid = (s) => /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/.test(s);
|
||||||
|
|
||||||
const decodeTopicRegexp = new RegExp(
|
const decodeTopicRegexp = new RegExp(
|
||||||
/(?<prefix>[^[]+)\/(?<type>.+)\/plejd\/(?<id>.+)\/(?<command>config|state|availability|set|scene)/,
|
/(?<prefix>[^[]+)\/(?<type>.+)\/plejd\/(?<id>.+)\/(?<command>config|state|availability|set|scene)/,
|
||||||
);
|
);
|
||||||
|
|
@ -75,7 +76,7 @@ const getLightDiscoveryPayload = (
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const getScenehDiscoveryPayload = (
|
const getSceneDiscoveryPayload = (
|
||||||
/** @type {import('./types/DeviceRegistry').OutputDevice} */ sceneDevice,
|
/** @type {import('./types/DeviceRegistry').OutputDevice} */ sceneDevice,
|
||||||
) => ({
|
) => ({
|
||||||
name: sceneDevice.name,
|
name: sceneDevice.name,
|
||||||
|
|
@ -88,6 +89,26 @@ const getScenehDiscoveryPayload = (
|
||||||
retain: false,
|
retain: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getSceneDeviceTriggerhDiscoveryPayload = (
|
||||||
|
/** @type {import('./types/DeviceRegistry').OutputDevice} */ sceneDevice,
|
||||||
|
) => ({
|
||||||
|
automation_type: 'trigger',
|
||||||
|
'~': getBaseTopic({
|
||||||
|
uniqueId: sceneDevice.uniqueId,
|
||||||
|
type: 'device_automation',
|
||||||
|
}),
|
||||||
|
qos: 1,
|
||||||
|
topic: `~/${TOPICS.STATE}`,
|
||||||
|
type: 'scene',
|
||||||
|
subtype: 'trigger',
|
||||||
|
device: {
|
||||||
|
identifiers: `${sceneDevice.uniqueId}`,
|
||||||
|
manufacturer: 'Plejd',
|
||||||
|
model: sceneDevice.typeName,
|
||||||
|
name: sceneDevice.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
const getMqttStateString = (/** @type {boolean} */ state) => (state ? 'ON' : 'OFF');
|
const getMqttStateString = (/** @type {boolean} */ state) => (state ? 'ON' : 'OFF');
|
||||||
|
|
@ -272,15 +293,34 @@ class MqttClient extends EventEmitter {
|
||||||
allSceneDevices.forEach((sceneDevice) => {
|
allSceneDevices.forEach((sceneDevice) => {
|
||||||
logger.debug(`Sending discovery for ${sceneDevice.name}`);
|
logger.debug(`Sending discovery for ${sceneDevice.name}`);
|
||||||
|
|
||||||
const configPayload = getScenehDiscoveryPayload(sceneDevice);
|
const sceneConfigPayload = getSceneDiscoveryPayload(sceneDevice);
|
||||||
logger.info(
|
logger.info(
|
||||||
`Discovered ${sceneDevice.typeName} (${sceneDevice.type}) named ${sceneDevice.name} (${sceneDevice.bleOutputAddress} : ${sceneDevice.uniqueId}).`,
|
`Discovered ${sceneDevice.typeName} (${sceneDevice.type}) named ${sceneDevice.name} (${sceneDevice.bleOutputAddress} : ${sceneDevice.uniqueId}).`,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.client.publish(getTopicName(sceneDevice, 'config'), JSON.stringify(configPayload), {
|
this.client.publish(getTopicName(sceneDevice, 'config'), JSON.stringify(sceneConfigPayload), {
|
||||||
retain: true,
|
retain: true,
|
||||||
qos: 1,
|
qos: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const sceneTriggerConfigPayload = getSceneDeviceTriggerhDiscoveryPayload(sceneDevice);
|
||||||
|
|
||||||
|
this.client.publish(
|
||||||
|
getTopicName(
|
||||||
|
{
|
||||||
|
...sceneDevice,
|
||||||
|
uniqueId: `${sceneDevice.uniqueId}_trigger`,
|
||||||
|
type: 'device_automation',
|
||||||
|
},
|
||||||
|
'config',
|
||||||
|
),
|
||||||
|
JSON.stringify(sceneTriggerConfigPayload),
|
||||||
|
{
|
||||||
|
retain: true,
|
||||||
|
qos: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.client.publish(getTopicName(sceneDevice, 'availability'), AVAILABLILITY.ONLINE, {
|
this.client.publish(getTopicName(sceneDevice, 'availability'), AVAILABLILITY.ONLINE, {
|
||||||
retain: true,
|
retain: true,
|
||||||
|
|
@ -338,7 +378,7 @@ class MqttClient extends EventEmitter {
|
||||||
*/
|
*/
|
||||||
sceneTriggered(sceneId) {
|
sceneTriggered(sceneId) {
|
||||||
logger.verbose(`Scene triggered: ${sceneId}`);
|
logger.verbose(`Scene triggered: ${sceneId}`);
|
||||||
this.client.publish(getSceneEventTopic(), JSON.stringify({ scene: sceneId }), { qos: 1 });
|
this.client.publish(getSceneEventTopic(sceneId), '', { qos: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue