Files
2020-07-09 21:11:52 +02:00

145 lines
3.7 KiB
Python

import json
import paho.mqtt.client as mqtt
import logger
LWT_ONLINE = 'online'
LWT_OFFLINE = 'offline'
_LOGGER = logger.get(__name__)
class MqttClient:
def __init__(self, config):
self._config = config
self._mqttc = mqtt.Client(client_id=self.client_id,
clean_session=False,
userdata={'global_topic_prefix': self.topic_prefix})
if self.username and self.password:
self.mqttc.username_pw_set(self.username, self.password)
if self.availability_topic:
topic = self._format_topic(self.availability_topic)
_LOGGER.debug("Setting LWT to: %s" % topic)
self.mqttc.will_set(topic, payload=LWT_OFFLINE, retain=True)
def publish(self, messages):
if not messages:
return
for m in messages:
topic = self._format_topic(m.topic)
self.mqttc.publish(topic, m.payload, retain=m.retain)
@property
def client_id(self):
return self._config['client_id'] if 'client_id' in self._config else 'bt-mqtt-gateway'
@property
def hostname(self):
return self._config['host']
@property
def port(self):
return self._config['port'] if 'port' in self._config else 1883
@property
def username(self):
return self._config['username'] if 'username' in self._config else None
@property
def password(self):
return self._config['password'] if 'password' in self._config else None
@property
def topic_prefix(self):
return self._config['topic_prefix'] if 'topic_prefix' in self._config else None
@property
def availability_topic(self):
return self._config['availability_topic'] if 'availability_topic' in self._config else None
@property
def mqttc(self):
return self._mqttc
def on_connect(self, client, userdata, flags, rc):
if self.availability_topic:
self.publish([MqttMessage(topic=self.availability_topic, payload=LWT_ONLINE, retain=True)])
def callbacks_subscription(self, callbacks):
self.mqttc.on_connect = self.on_connect
self.mqttc.connect(self.hostname, port=self.port)
for topic, callback in callbacks:
topic = self._format_topic(topic)
_LOGGER.debug("Subscribing to: %s" % topic)
self.mqttc.message_callback_add(topic, callback)
self.mqttc.subscribe(topic)
self.mqttc.loop_start()
def __del__(self):
if self.availability_topic:
self.publish([MqttMessage(topic=self.availability_topic, payload=LWT_OFFLINE, retain=True)])
def _format_topic(self, topic):
return "{}/{}".format(self.topic_prefix, topic) if self.topic_prefix else topic
class MqttMessage:
def __init__(self, topic=None, payload=None, retain=False):
self._topic = topic
self._payload = payload
self._retain = retain
@property
def topic(self):
return self._topic
@topic.setter
def topic(self, new_topic):
self._topic = new_topic
@property
def payload(self):
return self._payload
@property
def retain(self):
return self._retain
@property
def as_dict(self):
return {
'topic': self.topic,
'payload': self.payload
}
def __repr__(self):
return self.as_dict.__str__()
def __str__(self):
return self.__repr__()
class MqttConfigMessage(MqttMessage):
SENSOR = 'sensor'
CLIMATE = 'climate'
BINARY_SENSOR = 'binary_sensor'
def __init__(self, component, name, payload=None, retain=False):
# if 'name' not in payload: payload['name'] = name
# super().__init__("{}/{}/config".format(component, name), json.dumps(payload), retain)
super().__init__("{}/{}".format(component, name), payload, retain)
@property
def retain(self):
return self._retain
@retain.setter
def retain(self, new_retain):
self._retain = new_retain