2019-12-04 11:17:06 +01:00
const EventEmitter = require ( 'events' ) ;
const mqtt = require ( 'mqtt' ) ;
2021-02-01 21:19:22 +01:00
const Configuration = require ( './Configuration' ) ;
2021-01-21 21:31:37 +01:00
const Logger = require ( './Logger' ) ;
2019-12-04 11:17:06 +01:00
2021-01-28 14:24:04 +01:00
const startTopics = [ 'hass/status' , 'homeassistant/status' ] ;
2019-12-04 11:17:06 +01:00
2021-01-22 15:49:02 +01:00
const logger = Logger . getLogger ( 'plejd-mqtt' ) ;
2019-12-04 11:17:06 +01:00
const discoveryPrefix = 'homeassistant' ;
const nodeId = 'plejd' ;
2021-05-03 09:45:57 +02:00
/** @type {import('./types/Mqtt').MQTT_TYPES} */
2021-04-21 21:07:17 +02:00
const MQTT _TYPES = {
LIGHT : 'light' ,
2021-05-03 09:45:57 +02:00
SCENE : 'scene' ,
2021-04-21 21:07:17 +02:00
SWITCH : 'switch' ,
2021-05-03 09:45:57 +02:00
DEVICE _AUTOMATION : 'device_automation' ,
2021-04-21 21:07:17 +02:00
} ;
2021-05-03 09:45:57 +02:00
/** @type {import('./types/Mqtt').TOPIC_TYPES} */
const TOPIC _TYPES = {
2021-04-26 13:13:10 +02:00
CONFIG : 'config' ,
STATE : 'state' ,
AVAILABILITY : 'availability' ,
COMMAND : 'set' ,
} ;
2021-05-03 09:45:57 +02:00
const getBaseTopic = ( /** @type { string } */ uniqueId , /** @type { string } */ mqttDeviceType ) => ` ${ discoveryPrefix } / ${ mqttDeviceType } / ${ nodeId } / ${ uniqueId } ` ;
2021-03-31 20:07:46 +02:00
const getTopicName = (
2021-05-03 09:45:57 +02:00
/** @type { string } */ uniqueId ,
/** @type { import('./types/Mqtt').MqttType } */ mqttDeviceType ,
/** @type { import('./types/Mqtt').TopicType } */ topicType ,
) => ` ${ getBaseTopic ( uniqueId , mqttDeviceType ) } / ${ topicType } ` ;
2021-03-31 20:07:46 +02:00
2021-05-05 19:18:43 +02:00
const getButtonEventTopic = ( /** @type {string} */ deviceId ) => ` ${ getTopicName ( deviceId , MQTT _TYPES . DEVICE _AUTOMATION , TOPIC _TYPES . STATE ) } ` ;
2021-05-03 09:45:57 +02:00
const getTriggerUniqueId = ( /** @type { string } */ uniqueId ) => ` ${ uniqueId } _trigger ` ;
const getSceneEventTopic = ( /** @type {string} */ sceneId ) => ` ${ getTopicName ( getTriggerUniqueId ( sceneId ) , MQTT _TYPES . DEVICE _AUTOMATION , TOPIC _TYPES . STATE ) } ` ;
2021-04-26 13:13:10 +02:00
const getSubscribePath = ( ) => ` ${ discoveryPrefix } /+/ ${ nodeId } /# ` ;
2021-02-01 21:19:22 +01:00
const decodeTopicRegexp = new RegExp (
/(?<prefix>[^[]+)\/(?<type>.+)\/plejd\/(?<id>.+)\/(?<command>config|state|availability|set|scene)/ ,
) ;
const decodeTopic = ( topic ) => {
const matches = decodeTopicRegexp . exec ( topic ) ;
if ( ! matches ) {
return null ;
}
return matches . groups ;
} ;
2021-05-03 09:45:57 +02:00
const getOutputDeviceDiscoveryPayload = (
2021-03-31 20:07:46 +02:00
/** @type {import('./types/DeviceRegistry').OutputDevice} */ device ,
) => ( {
2019-12-10 22:01:12 +01:00
name : device . name ,
2021-03-31 23:28:25 +02:00
unique _id : device . uniqueId ,
2021-05-03 09:45:57 +02:00
'~' : getBaseTopic ( device . uniqueId , device . type ) ,
state _topic : ` ~/ ${ TOPIC _TYPES . STATE } ` ,
command _topic : ` ~/ ${ TOPIC _TYPES . COMMAND } ` ,
availability _topic : ` ~/ ${ TOPIC _TYPES . AVAILABILITY } ` ,
2019-12-21 15:01:15 +00:00
optimistic : false ,
2021-03-31 20:07:46 +02:00
qos : 1 ,
retain : true ,
2020-01-21 14:24:02 +00:00
device : {
2021-03-31 20:07:46 +02:00
identifiers : ` ${ device . deviceId } ` ,
2020-01-21 14:24:02 +00:00
manufacturer : 'Plejd' ,
model : device . typeName ,
name : device . name ,
2021-01-22 15:49:02 +01:00
sw _version : device . version ,
} ,
2021-05-03 09:45:57 +02:00
... ( device . type === MQTT _TYPES . LIGHT ? { brightness : device . dimmable , schema : 'json' } : { } ) ,
2019-12-10 22:01:12 +01:00
} ) ;
2021-04-26 13:13:10 +02:00
const getSceneDiscoveryPayload = (
2021-03-31 20:07:46 +02:00
/** @type {import('./types/DeviceRegistry').OutputDevice} */ sceneDevice ,
) => ( {
name : sceneDevice . name ,
2021-04-24 09:22:36 +02:00
unique _id : sceneDevice . uniqueId ,
2021-05-03 09:45:57 +02:00
'~' : getBaseTopic ( sceneDevice . uniqueId , MQTT _TYPES . SCENE ) ,
command _topic : ` ~/ ${ TOPIC _TYPES . COMMAND } ` ,
availability _topic : ` ~/ ${ TOPIC _TYPES . AVAILABILITY } ` ,
2021-04-24 09:22:36 +02:00
payload _on : 'ON' ,
2021-03-31 20:07:46 +02:00
qos : 1 ,
2021-04-21 21:07:17 +02:00
retain : false ,
2020-02-20 13:02:47 +01:00
} ) ;
2021-05-01 19:41:29 +02:00
const getInputDeviceTriggerDiscoveryPayload = (
/** @type {import('./types/DeviceRegistry').InputDevice} */ inputDevice ,
) => ( {
automation _type : 'trigger' ,
payload : ` ${ inputDevice . input } ` ,
2021-05-05 19:02:10 +02:00
'~' : getBaseTopic ( inputDevice . deviceId , MQTT _TYPES . DEVICE _AUTOMATION ) ,
2021-05-01 19:41:29 +02:00
qos : 1 ,
2021-05-05 19:02:10 +02:00
topic : ` ~/ ${ TOPIC _TYPES . STATE } ` ,
2021-05-01 19:41:29 +02:00
type : 'button_short_press' ,
subtype : ` button_ ${ inputDevice . input + 1 } ` ,
device : {
identifiers : ` ${ inputDevice . deviceId } ` ,
manufacturer : 'Plejd' ,
model : inputDevice . typeName ,
name : inputDevice . name ,
} ,
} ) ;
2021-04-26 13:13:10 +02:00
const getSceneDeviceTriggerhDiscoveryPayload = (
/** @type {import('./types/DeviceRegistry').OutputDevice} */ sceneDevice ,
) => ( {
automation _type : 'trigger' ,
2021-05-03 09:45:57 +02:00
'~' : getBaseTopic ( sceneDevice . uniqueId , MQTT _TYPES . DEVICE _AUTOMATION ) ,
2021-04-26 13:13:10 +02:00
qos : 1 ,
2021-05-03 09:45:57 +02:00
topic : ` ~/ ${ TOPIC _TYPES . STATE } ` ,
2021-04-26 13:13:10 +02:00
type : 'scene' ,
subtype : 'trigger' ,
device : {
identifiers : ` ${ sceneDevice . uniqueId } ` ,
manufacturer : 'Plejd' ,
model : sceneDevice . typeName ,
name : sceneDevice . name ,
} ,
} ) ;
2021-03-31 20:07:46 +02:00
const getMqttStateString = ( /** @type {boolean} */ state ) => ( state ? 'ON' : 'OFF' ) ;
const AVAILABLILITY = { ONLINE : 'online' , OFFLINE : 'offline' } ;
2019-12-04 11:17:06 +01:00
class MqttClient extends EventEmitter {
2021-03-31 20:07:46 +02:00
/** @type {import('DeviceRegistry')} */
2021-02-01 21:19:22 +01:00
deviceRegistry ;
2021-02-20 15:33:06 +01:00
static EVENTS = {
connected : 'connected' ,
stateChanged : 'stateChanged' ,
} ;
2021-04-21 21:07:17 +02:00
/ * *
* @ param { import ( "DeviceRegistry" ) } deviceRegistry
* /
2021-02-01 21:19:22 +01:00
constructor ( deviceRegistry ) {
2019-12-04 11:17:06 +01:00
super ( ) ;
2021-02-01 21:19:22 +01:00
this . config = Configuration . getOptions ( ) ;
this . deviceRegistry = deviceRegistry ;
2019-12-04 11:17:06 +01:00
}
init ( ) {
2021-01-22 15:49:02 +01:00
logger . info ( 'Initializing MQTT connection for Plejd addon' ) ;
2019-12-04 11:17:06 +01:00
2021-02-01 21:19:22 +01:00
this . client = mqtt . connect ( this . config . mqttBroker , {
2021-04-21 21:07:17 +02:00
clientId : ` hassio-plejd_ ${ Math . random ( ) . toString ( 16 ) . substr ( 2 , 8 ) } ` ,
2021-02-01 21:19:22 +01:00
password : this . config . mqttPassword ,
2021-04-23 10:42:18 +02:00
protocolVersion : 4 , // v5 not supported by HassIO Mosquitto
2021-04-21 21:07:17 +02:00
queueQoSZero : true ,
username : this . config . mqttUsername ,
2019-12-04 11:17:06 +01:00
} ) ;
2021-02-10 10:10:28 +01:00
this . client . on ( 'error' , ( err ) => {
logger . warn ( 'Error emitted from mqtt client' , err ) ;
} ) ;
2019-12-04 11:17:06 +01:00
this . client . on ( 'connect' , ( ) => {
2021-01-21 21:31:37 +01:00
logger . info ( 'Connected to MQTT.' ) ;
2019-12-04 11:17:06 +01:00
2021-04-23 10:42:18 +02:00
this . client . subscribe (
startTopics ,
// Add below when mqtt v5 is supported in Mosquitto 1.6 or 2.0 and forward
// {
// qos: 1,
// nl: true, // don't echo back messages sent
// rap: true, // retain as published - don't force retain = 0
// },
( err ) => {
if ( err ) {
logger . error ( 'Unable to subscribe to status topics' , err ) ;
}
2019-12-04 11:17:06 +01:00
2021-04-23 10:42:18 +02:00
this . emit ( MqttClient . EVENTS . connected ) ;
} ,
) ;
2019-12-04 11:17:06 +01:00
this . client . subscribe ( getSubscribePath ( ) , ( err ) => {
if ( err ) {
2021-01-21 21:31:37 +01:00
logger . error ( 'Unable to subscribe to control topics' ) ;
2019-12-04 11:17:06 +01:00
}
} ) ;
} ) ;
this . client . on ( 'close' , ( ) => {
2021-01-21 21:31:37 +01:00
logger . verbose ( 'Warning: mqtt channel closed event, reconnecting...' ) ;
2021-02-01 21:19:22 +01:00
this . reconnect ( ) ;
2019-12-04 11:17:06 +01:00
} ) ;
this . client . on ( 'message' , ( topic , message ) => {
2021-02-22 09:50:06 +01:00
try {
if ( startTopics . includes ( topic ) ) {
logger . info ( 'Home Assistant has started. lets do discovery.' ) ;
this . emit ( MqttClient . EVENTS . connected ) ;
} else {
2021-04-23 10:42:18 +02:00
logger . verbose ( ` Received mqtt message on ${ topic } ` ) ;
2021-02-22 09:50:06 +01:00
const decodedTopic = decodeTopic ( topic ) ;
if ( decodedTopic ) {
2021-04-21 21:07:17 +02:00
/** @type {import('types/DeviceRegistry').OutputDevice} */
let device ;
2021-05-03 09:45:57 +02:00
if ( decodedTopic . type === MQTT _TYPES . SCENE ) {
2021-04-21 21:07:17 +02:00
logger . verbose ( ` Getting scene ${ decodedTopic . id } from registry ` ) ;
device = this . deviceRegistry . getScene ( decodedTopic . id ) ;
} else {
logger . verbose ( ` Getting device ${ decodedTopic . id } from registry ` ) ;
device = this . deviceRegistry . getOutputDevice ( decodedTopic . id ) ;
}
2021-02-22 09:50:06 +01:00
const messageString = message . toString ( ) ;
const isJsonMessage = messageString . startsWith ( '{' ) ;
const command = isJsonMessage ? JSON . parse ( messageString ) : messageString ;
const deviceName = device ? device . name : '' ;
switch ( decodedTopic . command ) {
case 'set' :
logger . verbose (
` Got mqtt SET command for ${ decodedTopic . type } , ${ deviceName } ( ${ decodedTopic . id } ): ${ messageString } ` ,
) ;
2021-02-01 21:19:22 +01:00
2021-02-22 09:50:06 +01:00
if ( device ) {
this . emit ( MqttClient . EVENTS . stateChanged , device , command ) ;
} else {
logger . warn (
` Device for topic ${ topic } not found! Can happen if HA calls previously existing devices. ` ,
) ;
}
break ;
case 'state' :
case 'config' :
case 'availability' :
logger . verbose (
` Sent mqtt ${ decodedTopic . command } command for ${
decodedTopic . type
} , $ { deviceName } ( $ { decodedTopic . id } ) . $ {
decodedTopic . command === 'availability' ? messageString : ''
} ` ,
2021-02-01 21:19:22 +01:00
) ;
2021-02-22 09:50:06 +01:00
break ;
default :
logger . verbose ( ` Warning: Unknown command ${ decodedTopic . command } in decoded topic ` ) ;
}
} else {
logger . verbose (
` Warning: Got unrecognized mqtt command on ' ${ topic } ': ${ message . toString ( ) } ` ,
) ;
2021-02-01 21:19:22 +01:00
}
2021-01-25 08:06:28 +01:00
}
2021-02-22 09:50:06 +01:00
} catch ( err ) {
logger . error ( ` Error processing mqtt message on topic ${ topic } ` , err ) ;
2021-01-21 21:31:37 +01:00
}
2019-12-04 11:17:06 +01:00
} ) ;
}
reconnect ( ) {
this . client . reconnect ( ) ;
}
2021-02-20 15:33:06 +01:00
cleanup ( ) {
this . client . removeAllListeners ( ) ;
}
2021-01-29 21:25:34 +01:00
disconnect ( callback ) {
2021-05-03 09:45:57 +02:00
logger . info ( 'Mqtt disconnect requested. Setting all devices as unavailable in HA...' ) ;
2021-03-31 20:07:46 +02:00
this . deviceRegistry . getAllOutputDevices ( ) . forEach ( ( outputDevice ) => {
2021-05-03 09:45:57 +02:00
const mqttType = outputDevice . type === 'switch' ? MQTT _TYPES . SWITCH : MQTT _TYPES . LIGHT ;
this . client . publish (
getTopicName ( outputDevice . uniqueId , mqttType , 'availability' ) ,
AVAILABLILITY . OFFLINE ,
{
retain : true ,
qos : 1 ,
} ,
) ;
} ) ;
const allSceneDevices = this . deviceRegistry . getAllSceneDevices ( ) ;
allSceneDevices . forEach ( ( sceneDevice ) => {
this . client . publish (
getTopicName ( sceneDevice . uniqueId , MQTT _TYPES . SCENE , TOPIC _TYPES . AVAILABILITY ) ,
AVAILABLILITY . OFFLINE ,
{
retain : true ,
qos : 1 ,
} ,
) ;
2021-01-29 21:25:34 +01:00
} ) ;
this . client . end ( callback ) ;
}
2021-02-01 21:19:22 +01:00
sendDiscoveryToHomeAssistant ( ) {
2021-03-31 20:07:46 +02:00
const allOutputDevices = this . deviceRegistry . getAllOutputDevices ( ) ;
logger . info ( ` Sending discovery for ${ allOutputDevices . length } Plejd output devices ` ) ;
allOutputDevices . forEach ( ( outputDevice ) => {
logger . debug ( ` Sending discovery for ${ outputDevice . name } ` ) ;
2021-05-03 09:45:57 +02:00
const configPayload = getOutputDeviceDiscoveryPayload ( outputDevice ) ;
2021-03-31 20:07:46 +02:00
logger . info (
` Discovered ${ outputDevice . typeName } ( ${ outputDevice . type } ) named ${ outputDevice . name } ( ${ outputDevice . bleOutputAddress } : ${ outputDevice . uniqueId } ). ` ,
) ;
2021-05-03 09:45:57 +02:00
const mqttType = outputDevice . type === 'switch' ? MQTT _TYPES . SWITCH : MQTT _TYPES . LIGHT ;
this . client . publish (
getTopicName ( outputDevice . uniqueId , mqttType , TOPIC _TYPES . CONFIG ) ,
JSON . stringify ( configPayload ) ,
{
2021-04-21 21:07:17 +02:00
retain : true ,
qos : 1 ,
2021-05-03 09:45:57 +02:00
} ,
) ;
setTimeout ( ( ) => {
this . client . publish (
getTopicName ( outputDevice . uniqueId , mqttType , TOPIC _TYPES . AVAILABILITY ) ,
AVAILABLILITY . ONLINE ,
{
retain : true ,
qos : 1 ,
} ,
) ;
2021-03-31 20:07:46 +02:00
} , 2000 ) ;
} ) ;
2019-12-04 11:17:06 +01:00
2021-05-01 19:41:29 +02:00
const allInputDevices = this . deviceRegistry . getAllInputDevices ( ) ;
logger . info ( ` Sending discovery for ${ allInputDevices . length } Plejd input devices ` ) ;
allInputDevices . forEach ( ( inputDevice ) => {
logger . debug ( ` Sending discovery for ${ inputDevice . name } ` ) ;
const inputInputPayload = getInputDeviceTriggerDiscoveryPayload ( inputDevice ) ;
logger . info (
2021-05-05 19:02:10 +02:00
` Discovered ${ inputDevice . typeName } ( ${ inputDevice . type } ) named ${ inputDevice . name } ( ${ inputDevice . bleInputAddress } : ${ inputDevice . uniqueId } ). ` ,
2021-05-01 19:41:29 +02:00
) ;
2021-05-05 19:02:10 +02:00
logger . verbose ( ` Publishing ${ getTopicName ( inputDevice . uniqueId , MQTT _TYPES . DEVICE _AUTOMATION , TOPIC _TYPES . CONFIG ) } with payload ${ JSON . stringify ( inputInputPayload ) } ` ) ;
2021-05-01 19:41:29 +02:00
2021-05-05 19:02:10 +02:00
this . client . publish ( getTopicName ( inputDevice . uniqueId , MQTT _TYPES . DEVICE _AUTOMATION , TOPIC _TYPES . CONFIG ) , JSON . stringify ( inputInputPayload ) , {
2021-05-01 19:41:29 +02:00
retain : true ,
qos : 1 ,
} ) ;
} )
2021-03-31 20:07:46 +02:00
const allSceneDevices = this . deviceRegistry . getAllSceneDevices ( ) ;
logger . info ( ` Sending discovery for ${ allSceneDevices . length } Plejd scene devices ` ) ;
allSceneDevices . forEach ( ( sceneDevice ) => {
logger . debug ( ` Sending discovery for ${ sceneDevice . name } ` ) ;
2019-12-04 11:17:06 +01:00
2021-04-26 13:13:10 +02:00
const sceneConfigPayload = getSceneDiscoveryPayload ( sceneDevice ) ;
2021-01-22 15:49:02 +01:00
logger . info (
2021-03-31 20:07:46 +02:00
` Discovered ${ sceneDevice . typeName } ( ${ sceneDevice . type } ) named ${ sceneDevice . name } ( ${ sceneDevice . bleOutputAddress } : ${ sceneDevice . uniqueId } ). ` ,
2021-01-22 15:49:02 +01:00
) ;
2019-12-13 14:13:00 +01:00
2021-05-03 09:45:57 +02:00
this . client . publish (
getTopicName ( sceneDevice . uniqueId , MQTT _TYPES . SCENE , TOPIC _TYPES . CONFIG ) ,
JSON . stringify ( sceneConfigPayload ) ,
{
retain : true ,
qos : 1 ,
} ,
) ;
2021-04-26 13:13:10 +02:00
const sceneTriggerConfigPayload = getSceneDeviceTriggerhDiscoveryPayload ( sceneDevice ) ;
this . client . publish (
getTopicName (
2021-05-03 09:45:57 +02:00
getTriggerUniqueId ( sceneDevice . uniqueId ) ,
MQTT _TYPES . DEVICE _AUTOMATION ,
TOPIC _TYPES . CONFIG ,
2021-04-26 13:13:10 +02:00
) ,
JSON . stringify ( sceneTriggerConfigPayload ) ,
{
retain : true ,
qos : 1 ,
} ,
) ;
2021-01-29 21:25:34 +01:00
setTimeout ( ( ) => {
2021-05-03 09:45:57 +02:00
this . client . publish (
getTopicName ( sceneDevice . uniqueId , MQTT _TYPES . SCENE , TOPIC _TYPES . AVAILABILITY ) ,
AVAILABLILITY . ONLINE ,
{
retain : true ,
qos : 1 ,
} ,
) ;
2021-01-29 21:25:34 +01:00
} , 2000 ) ;
2019-12-04 11:17:06 +01:00
} ) ;
}
2021-03-31 20:07:46 +02:00
/ * *
* @ param { string } uniqueOutputId
* @ param { { state : boolean ; brightness ? : number ; } } data
* /
updateOutputState ( uniqueOutputId , data ) {
const device = this . deviceRegistry . getOutputDevice ( uniqueOutputId ) ;
2019-12-04 11:17:06 +01:00
if ( ! device ) {
2021-03-31 20:07:46 +02:00
logger . warn ( ` Unknown output id ${ uniqueOutputId } - not handled by us. ` ) ;
2019-12-04 11:17:06 +01:00
return ;
}
2021-01-25 08:06:28 +01:00
logger . verbose (
` Updating state for ${ device . name } : ${ data . state } ${
data . brightness ? ` , dim: ${ data . brightness } ` : ''
} ` ,
) ;
2019-12-21 15:01:15 +00:00
let payload = null ;
2019-12-04 11:17:06 +01:00
2020-02-29 15:54:08 +00:00
if ( device . type === 'switch' ) {
2021-03-31 20:07:46 +02:00
payload = getMqttStateString ( data . state ) ;
2021-01-22 15:49:02 +01:00
} else {
2020-02-29 15:54:08 +00:00
if ( device . dimmable ) {
payload = {
2021-03-31 20:07:46 +02:00
state : getMqttStateString ( data . state ) ,
2021-01-22 15:49:02 +01:00
brightness : data . brightness ,
} ;
} else {
2020-02-29 15:54:08 +00:00
payload = {
2021-03-31 20:07:46 +02:00
state : getMqttStateString ( data . state ) ,
2021-01-22 15:49:02 +01:00
} ;
2020-02-29 15:54:08 +00:00
}
payload = JSON . stringify ( payload ) ;
2019-12-04 11:17:06 +01:00
}
2021-05-03 09:45:57 +02:00
const mqttType = device . type === 'switch' ? MQTT _TYPES . SWITCH : MQTT _TYPES . LIGHT ;
this . client . publish ( getTopicName ( device . uniqueId , mqttType , TOPIC _TYPES . STATE ) , payload , {
2021-04-21 21:07:17 +02:00
retain : true ,
qos : 1 ,
} ) ;
2021-05-03 09:45:57 +02:00
// this.client.publish(
// getTopicName(device.uniqueId, mqttType, TOPIC_TYPES.AVAILABILITY),
// AVAILABLILITY.ONLINE,
// { retain: true, qos: 1 },
// );
2019-12-04 11:17:06 +01:00
}
2019-12-22 17:48:16 +00:00
2021-05-01 19:41:29 +02:00
buttonPressed ( data ) {
logger . verbose ( ` Button ${ data . deviceInput } pressed for deviceId ${ data . deviceId } ` ) ;
this . client . publish ( getButtonEventTopic ( data . deviceId ) , ` ${ data . deviceInput } ` , { qos : 1 } ) ;
}
2021-03-31 20:07:46 +02:00
/ * *
* @ param { string } sceneId
* /
2021-02-01 21:19:22 +01:00
sceneTriggered ( sceneId ) {
logger . verbose ( ` Scene triggered: ${ sceneId } ` ) ;
2021-04-26 13:13:10 +02:00
this . client . publish ( getSceneEventTopic ( sceneId ) , '' , { qos : 1 } ) ;
2019-12-22 17:48:16 +00:00
}
2019-12-04 11:17:06 +01:00
}
2021-01-22 15:49:02 +01:00
module . exports = MqttClient ;