浏览代码

Add systemd service, sdnotify and local config

Thomas Dietrich 8 年之前
父节点
当前提交
0914cf8b44
共有 5 个文件被更改,包括 167 次插入17 次删除
  1. 109 0
      .gitignore
  2. 25 14
      README.md
  3. 16 3
      mqtt-flora.py
  4. 1 0
      requirements.txt
  5. 16 0
      template.service

+ 109 - 0
.gitignore

@@ -0,0 +1,109 @@
+# Project specific
+
+config.local.ini
+
+
+# Created by https://www.gitignore.io/api/python
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# dotenv
+.env
+
+# virtualenv
+.venv
+venv/
+ENV/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# End of https://www.gitignore.io/api/python
+

+ 25 - 14
README.md

@@ -16,8 +16,10 @@ The program can be executed for a single run or in **daemon mode** to run contin
 * JSON encoded
 * MQTT authentication support
 * Daemon mode (default)
+* Systemd service file included, sd\_notify messages generated
 * MQTT-less mode, printing data directly to stdout/file
 * Reliable and inituitive
+* Tested on Raspberry Pi
 
 ![Promotional image](https://xiaomi-mi.com/uploads/ck/xiaomi-flower-monitor-001.jpg)
 
@@ -35,25 +37,27 @@ The Mi Flora sensor offers the following plant and soil readings:
 
 ### Installation
 
-Shown for a modern Debian system:
+On a modern Linux system just a few steps are needed.
+The following example shows the installation under Debian/Raspbian:
 
 ```shell
+sudo apt install git python3 python3-pip bluetooth
+
 git clone https://github.com/ThomDietrich/miflora-mqtt-daemon.git /opt/miflora-mqtt-daemon
 cd /opt/miflora-mqtt-daemon
 
-apt install python3 python3-pip bluetooth libbluetooth-dev libboost-python-dev libglib2.0-dev
-pip3 install -r requirements.txt
+sudo pip3 install -r requirements.txt
 ```
 
 ### Configuration
 
-To match personal needs all operation details can be configured using the file [`config.ini`](config.ini).
+To match personal needs, all operation details can be configured using the file [`config.ini`](config.ini).
 
 You need to add at least one sensor to the configuration.
 Scan for available Miflora sensors in your proximity with the command:
 
 ```shell
-hcitool lescan
+sudo hcitool lescan
 ```
 
 ### Execution
@@ -71,26 +75,33 @@ The extensive output can be reduced to error messages:
 python3 mqtt-flora.py > /dev/null
 ```
 
-You probably want to execute the program **continuously in the background**.
-This can either be done by using the internal daemon or cron.
+#### Continous Daemon/Service
+
+You most probably want to execute the program **continuously in the background**.
+This can be done either by using the internal daemon or cron.
 
-**Attention:** Daemon mode can be enabled (default) and disabled in the config file.
+**Attention:** Daemon mode must be enabled in the configuration file (default).
 
-1. Send the program into the background with some simple command line foo:
+1. Systemd service - on systemd powered systems the recommended option
    
    ```shell
-   python3 /path/to/mqtt-flora.py &
+   sudo ln -s /opt/miflora-mqtt-daemon/template.service /etc/systemd/system/miflora.service
+
+   sudo systemctl daemon-reload
+
+   sudo systemctl start miflora.service
+   sudo systemctl status miflora.service
+
+   sudo systemctl enable miflora.service
    ```
-   
-   *Hint:* Bring back to foreground with `fg`.
 
-2. Screen Shell - Run the program inside a [screen shell](https://www.howtoforge.com/linux_screen):
+1. Screen Shell - Run the program inside a [screen shell](https://www.howtoforge.com/linux_screen):
    
    ```shell
    screen -S mqtt-flora -d -m python3 /path/to/mqtt-flora.py
    ```
 
-3. Cron job - Add a new con job, e.g., `/etc/cron.d/miflora`, execute every 5 minutes
+1. Cron job - Add a new con job, e.g., `/etc/cron.d/miflora`, execute every 5 minutes
    
    ```shell
    */5 * * * * root python3 /path/to/mqtt-flora.py > /dev/null

+ 16 - 3
mqtt-flora.py

@@ -7,6 +7,7 @@ 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
+import sdnotify
 
 parameters = [MI_BATTERY, MI_CONDUCTIVITY, MI_LIGHT, MI_MOISTURE, MI_TEMPERATURE]
 
@@ -15,10 +16,14 @@ print('Xiaomi Mi Flora Plant Sensor MQTT Client/Daemon')
 print('Source: https://github.com/ThomDietrich/miflora-mqtt-daemon')
 print()
 
-# Eclipse Paho callbacks http://www.eclipse.org/paho/clients/python/docs/#callbacks
+# Systemd Service Notifications - https://github.com/bb4242/sdnotify
+sd_notifier = sdnotify.SystemdNotifier()
+
+# Eclipse Paho callbacks - http://www.eclipse.org/paho/clients/python/docs/#callbacks
 def on_connect(client, userdata, flags, rc):
     if rc == 0:
         print('Connected.\n')
+        sd_notifier.notify('STATUS=MQTT connection established')
     else:
         print('Connection error with result code {} - {}'.format(str(rc), mqtt.connack_string(rc)), file=sys.stderr)
         #kill main thread
@@ -30,7 +35,7 @@ def on_publish(client, userdata, mid):
 # Load configuration file
 config = ConfigParser(delimiters=('=', ))
 config.optionxform = str
-config.read(os.path.join(sys.path[0], 'config.ini'))
+config.read([os.path.join(sys.path[0], 'config.ini'), os.path.join(sys.path[0], 'config.local.ini')])
 
 reporting_mode = config['General'].get('reporting_method', 'mqtt-json')
 daemon_enabled = config['Daemon'].getboolean('enabled', True)
@@ -47,6 +52,7 @@ 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 "sudo hcitool lescan".', file=sys.stderr)
     sys.exit(1)
+sd_notifier.notify('STATUS=Configuration accepted')
 
 # MQTT connection
 if reporting_mode == 'mqtt-json':
@@ -67,6 +73,8 @@ if reporting_mode == 'mqtt-json':
         mqtt_client.loop_start()
         sleep(1) # some slack to establish the connection
 
+sd_notifier.notify('READY=1')
+
 # Initialize Mi Flora sensors
 flores = dict()
 for [name, mac] in config['Sensors'].items():
@@ -80,6 +88,8 @@ for [name, mac] in config['Sensors'].items():
     print()
     flores[name] = flora_poller
 
+sd_notifier.notify('STATUS=Initialization complete, starting MQTT publish loop')
+
 # Sensor data retrieval and publication
 while True:
     for [flora_name, flora_poller] in flores.items():
@@ -101,11 +111,14 @@ while True:
         else:
             raise NameError('Unexpected reporting_mode.')
 
+    sd_notifier.notify('STATUS={} - Status messages published'.format(strftime('%Y-%m-%d %H:%M:%S', localtime())))
+
     if daemon_enabled:
         print('Sleeping ({} seconds) ...'.format(sleep_period))
         sleep(sleep_period)
         print()
     else:
-        mqtt_client.disconnect() if reporting_mode == 'mqtt-json'
+        if reporting_mode == 'mqtt-json':
+            mqtt_client.disconnect()
         break
 

+ 1 - 0
requirements.txt

@@ -1,3 +1,4 @@
 miflora==0.1.15
 paho-mqtt==1.2
 wheel==0.24.0
+sdnotify==0.3.1

+ 16 - 0
template.service

@@ -0,0 +1,16 @@
+[Unit]
+Description=Xiaomi Mi Flora Plant Sensor MQTT Client/Daemon
+Documentation=https://github.com/ThomDietrich/miflora-mqtt-daemon
+After=syslog.target mosquitto.service bluetooth.service
+
+[Service]
+Type=notify
+User=daemon
+Group=daemon
+WorkingDirectory=/opt/miflora-mqtt-daemon/
+ExecStart=/opt/miflora-mqtt-daemon/mqtt-flora.py
+StandardOutput=null
+Environment=PYTHONUNBUFFERED=true
+
+[Install]
+WantedBy=multi-user.target