esphome/esphomeyaml/mqtt.py
Otto Winter 7c7032c59e
[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234)
* Implement custom sensor platform

* Update

* Ethernet

* Lint

* Fix

* Login page

* Rename cookie secret

* Update manifest

* Update cookie check logic

* Favicon

* Fix

* Favicon manifest

* Fix

* Fix

* Fix

* Use hostname

* Message

* Temporary commit for screenshot

* Automatic board selection

* Undo temporary commit

* Update esphomeyaml-edge

* In-dashboard editing and hosting files locally

* Update esphomeyaml-edge

* Better ANSI color escaping

* Message

* Lint

* Download Efficiency

* Fix gitlab

* Fix

* Rename extra_libraries to libraries

* Add example

* Update README.md

* Update README.md

* Update README.md

* HassIO -> Hass.io

* Updates

* Add update available notice

* Update

* Fix substitutions

* Better error message

* Re-do dashboard ANSI colors

* Only include FastLED if user says so

* Autoscroll logs

* Remove old checks

* Use safer RedirectText

* Improvements

* Fix

* Use enviornment variable

* Use http://hassio/host/info

* Fix conditions

* Update platformio versions

* Revert "Use enviornment variable"

This reverts commit 7f038eb5d2.

* Fix

* README update

* Temp

* Better invalid config messages

* Platformio debug

* Improve error messages

* Debug

* Remove debug

* Multi Conf

* Update

* Better paths

* Remove unused

* Fixes

* Lint

* lib_ignore

* Try fix platformio colors

* Fix dashboard scrolling

* Revert

* Lint

* Revert
2018-12-05 21:22:06 +01:00

142 lines
5.0 KiB
Python

from __future__ import print_function
from datetime import datetime
import hashlib
import logging
import socket
import ssl
import sys
import time
import paho.mqtt.client as mqtt
from esphomeyaml.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOMEYAML, \
CONF_LOG_TOPIC, CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SSL_FINGERPRINTS, \
CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME
from esphomeyaml.core import CORE, EsphomeyamlError
from esphomeyaml.helpers import color
from esphomeyaml.util import safe_print
_LOGGER = logging.getLogger(__name__)
def initialize(config, subscriptions, on_message, username, password, client_id):
def on_connect(client, userdata, flags, return_code):
for topic in subscriptions:
client.subscribe(topic)
def on_disconnect(client, userdata, result_code):
if result_code == 0:
return
tries = 0
while True:
try:
if client.reconnect() == 0:
_LOGGER.info("Successfully reconnected to the MQTT server")
break
except socket.error:
pass
wait_time = min(2**tries, 300)
_LOGGER.warning(
"Disconnected from MQTT (%s). Trying to reconnect in %s s",
result_code, wait_time)
time.sleep(wait_time)
tries += 1
client = mqtt.Client(client_id or u'')
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
if username is None:
if config[CONF_MQTT].get(CONF_USERNAME):
client.username_pw_set(config[CONF_MQTT][CONF_USERNAME],
config[CONF_MQTT][CONF_PASSWORD])
elif username:
client.username_pw_set(username, password)
if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS):
if sys.version_info >= (2, 7, 13):
tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member
else:
tls_version = ssl.PROTOCOL_SSLv23
client.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED,
tls_version=tls_version, ciphers=None)
try:
client.connect(config[CONF_MQTT][CONF_BROKER], config[CONF_MQTT][CONF_PORT])
except socket.error as err:
raise EsphomeyamlError("Cannot connect to MQTT broker: {}".format(err))
try:
client.loop_forever()
except KeyboardInterrupt:
pass
return 0
def show_logs(config, topic=None, username=None, password=None, client_id=None):
if topic is not None:
pass # already have topic
elif CONF_MQTT in config:
conf = config[CONF_MQTT]
if CONF_LOG_TOPIC in conf:
topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC]
elif CONF_TOPIC_PREFIX in config[CONF_MQTT]:
topic = config[CONF_MQTT][CONF_TOPIC_PREFIX] + u'/debug'
else:
topic = config[CONF_ESPHOMEYAML][CONF_NAME] + u'/debug'
else:
_LOGGER.error(u"MQTT isn't setup, can't start MQTT logs")
return 1
_LOGGER.info(u"Starting log output from %s", topic)
def on_message(client, userdata, msg):
time_ = datetime.now().time().strftime(u'[%H:%M:%S]')
message = time_ + msg.payload
safe_print(message)
return initialize(config, [topic], on_message, username, password, client_id)
def clear_topic(config, topic, username=None, password=None, client_id=None):
if topic is None:
discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, u'homeassistant')
name = config[CONF_ESPHOMEYAML][CONF_NAME]
topic = u'{}/+/{}/#'.format(discovery_prefix, name)
_LOGGER.info(u"Clearing messages from '%s'", topic)
_LOGGER.info(u"Please close this window when no more messages appear and the "
u"MQTT topic has been cleared of retained messages.")
def on_message(client, userdata, msg):
if not msg.payload or not msg.retain:
return
try:
print(u"Clearing topic {}".format(msg.topic))
except UnicodeDecodeError:
print(u"Skipping non-UTF-8 topic (prohibited by MQTT standard)")
return
client.publish(msg.topic, None, retain=True)
return initialize(config, [topic], on_message, username, password, client_id)
# From marvinroger/async-mqtt-client -> scripts/get-fingerprint/get-fingerprint.py
def get_fingerprint(config):
addr = config[CONF_MQTT][CONF_BROKER], config[CONF_MQTT][CONF_PORT]
_LOGGER.info("Getting fingerprint from %s:%s", addr[0], addr[1])
try:
cert_pem = ssl.get_server_certificate(addr)
except IOError as err:
_LOGGER.error("Unable to connect to server: %s", err)
return 1
cert_der = ssl.PEM_cert_to_DER_cert(cert_pem)
sha1 = hashlib.sha1(cert_der).hexdigest()
safe_print(u"SHA1 Fingerprint: " + color('cyan', sha1))
safe_print(u"Copy the string above into mqtt.ssl_fingerprints section of {}"
u"".format(CORE.config_path))
return 0