浏览代码

Add functionality, improve error handling

Thomas Dietrich 8 年之前
父节点
当前提交
77c154e924
共有 3 个文件被更改,包括 81 次插入47 次删除
  1. 3 0
      AUTHORS
  2. 13 9
      config.ini
  3. 65 38
      mqtt-flora.py

+ 3 - 0
AUTHORS

@@ -0,0 +1,3 @@
+Jan Willhaus <mail@janwillhaus.de>
+Thomas Dietrich <thomas.dietrich@tu-ilmenau.de>
+

+ 13 - 9
config.ini

@@ -1,16 +1,20 @@
-[mqtt]
 
-hostname = homeassistant
+[Daemon]
+#enabled = false
+period = 120
+
+[MQTT]
+hostname = localhost
 port = 1883
-timeout = 60
+keepalive = 60
 topic_prefix = miflora
+#username = user
+#password = pwd123
 
-[miflora]
-
-timeout = 600
-sleep = 120
-
-[sensors]
+[MiFlora]
+cache_timeout = 600
 
+[Sensors]
 Feinblatt=C4:7C:8D:61:7E:0B
 Drachenbaum=C4:7C:8D:61:9D:8D
+

+ 65 - 38
mqtt-flora.py

@@ -1,57 +1,84 @@
 #!/usr/bin/env python3
 
-import paho.mqtt.client as mqtt
-import time
-from miflora.miflora_poller import MiFloraPoller, \
-    MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE
-from configparser import ConfigParser
+import sys
 import json
+from time import sleep, localtime, strftime
+from configparser import ConfigParser
+from miflora.miflora_poller import MiFloraPoller, MI_BATTERY, MI_CONDUCTIVITY, MI_LIGHT, MI_MOISTURE, MI_TEMPERATURE
+import paho.mqtt.client as mqtt
+
+parameters = [MI_BATTERY, MI_CONDUCTIVITY, MI_LIGHT, MI_MOISTURE, MI_TEMPERATURE]
 
-parameters = [MI_TEMPERATURE,
-              MI_LIGHT,
-              MI_MOISTURE,
-              MI_CONDUCTIVITY]
+print('Xiaomi Mi Flora Plant Sensor MQTT Client/Daemon')
+print('Source: https://github.com/janwh/miflora-mqtt-daemon')
+print()
 
+# Load configuration file
 config = ConfigParser(delimiters=('=', ))
+config.optionxform = str
 config.read('config.ini')
+daemon_enabled = config['Daemon'].getboolean('enabled', True)
+sleep_period = config['Daemon'].getint('period', 60)
+topic_prefix = config['MQTT'].get('topic_prefix', 'miflora')
+miflora_cache_timeout = config['MiFlora'].getint('cache_timeout', 600)
+if not config['Sensors']:
+    print('Error. Please add at least one sensor to the configuration file "config.ini".', file=sys.stderr)
+    print('Scan for available Miflora sensors with "hcitool lescan".', file=sys.stderr)
+    sys.exit(1)
 
-sleep_time = config['miflora'].getint('sleep', 60)
-topic_prefix = config['mqtt'].get('topic_prefix', 'miflora')
-miflora_timeout = config['miflora'].getint('timeout', 600)
-
-# The callback for when the client receives a CONNACK response from the server.
-def on_connect(client, userdata, flags, rc):
-    print("Connected with result code "+str(rc))
-
-# Initialize Flora sensors
-
+# Initialize Mi Flora sensors
 flores = {}
-for flora in config['sensors'].items():
-    print('Adding', flora[0])
-    flores[flora[0]] = MiFloraPoller(
-        mac=flora[1],
-        cache_timeout=miflora_timeout)
+for flora in config['Sensors'].items():
+    print('Adding device from config to Mi Flora device list ...')
+    print('Name:         "{}"'.format(flora[0]))
+    flores[flora[0]] = MiFloraPoller(mac=flora[1], cache_timeout=miflora_cache_timeout)
+    print('Device name:  "{}"'.format(flores[flora[0]].name()))
+    print('MAC address:  {}'.format(flora[1]))
+    print('Firmware:     {}'.format(flores[flora[0]].firmware_version()))
+    print()
 
+# Callbacks http://www.eclipse.org/paho/clients/python/docs/#callbacks
+def on_connect(client, userdata, flags, rc):
+    if rc != 0:
+        print('Connected with result code {}: {}'.format(str(rc), mqtt.connack_string(rc)), file=sys.stderr)
+        sys.exit(1)
+def on_publish(client, userdata, mid):
+    print('Data successfully published!')
 
-client = mqtt.Client()
-client.on_connect = on_connect
-client.connect(config['mqtt'].get('hostname', 'homeassistant'),
-               config['mqtt'].getint('port', 1883),
-               config['mqtt'].getint('timeout', 60))
-client.loop_start()
+# MQTT connection
+print('Connecting to MQTT broker ...')
+mqtt_client = mqtt.Client()
+mqtt_client.on_connect = on_connect
+mqtt_client.on_publish = on_publish
+if config['MQTT'].get('username'):
+    mqtt_client.username_pw_set(config['MQTT'].get('username'), config['MQTT'].get('password', None))
+try:
+    mqtt_client.connect(config['MQTT'].get('hostname', 'localhost'),
+                        port=config['MQTT'].getint('port', 1883),
+                        keepalive=config['MQTT'].getint('keepalive', 60))
+except:
+    print('Error. Please check your MQTT connection settings in the configuration file "config.ini".', file=sys.stderr)
+    sys.exit(1)
+else:
+    print('Connected.\n')
+    mqtt_client.loop_start()
 
+# Sensor data retrieval and publishing
 while True:
-
     for flora in flores:
-        print('Publishing for', flora)
-
         data = {}
         for param in parameters:
             data[param] = flores.get(flora).parameter_value(param)
+        print(strftime('[%Y-%m-%d %H:%M:%S]', localtime()), end=' ')
+        print('Attempting to publishing to MQTT topic "{}/{}" ...\nData: {}'.format(topic_prefix, flora, json.dumps(data)))
+        mqtt_client.publish('{}/{}'.format(topic_prefix, flora), json.dumps(data))
+        sleep(0.5) # some slack for the publish roundtrip and callback function
+        print()
+    if not daemon_enabled:
+        break
+    print('Sleeping ({} seconds) ...'.format(sleep_period))
+    sleep(sleep_period)
+    print()
 
-        client.publish("{}/{}".format(
-            topic_prefix,
-            flora), json.dumps(data))
+mqtt_client.disconnect()
 
-    print('Sleeping ...')
-    time.sleep(sleep_time)