Die eigentliche Funktion des Scripts sollte hier nicht so wichtig sein, aber man kann ein paar Dinge sehen.
- mittels configparser Library werden die Zugangsdaten zum mqtt Server geholt. Liegt der entsprechende Wert nicht vor, wird ein Default Wert gesetzt.
- Auch das logging ist über einen Import bequem erledigt.
- Die Library, um die es eigentlich geht (paho.mqtt.client) und wie sie angesprochen wird.
Code: Alles auswählen
#!/usr/bin/python
import configparser
import logging
import paho.mqtt.client as mqtt
import time
from sysdmanager import SystemdManager
config = configparser.ConfigParser()
config.read('/etc/default/mqttclient')
log_file = (config['logging']).get('filename','/var/log/pymqtt.log')
log_level = int((config['logging']).get('level','30'))
logging.basicConfig(filename=log_file,format='%(asctime)s %(levelname)s:%(message)s', datefmt='%Y/%m/%d/ %H:%M:%S', level=log_level)
MQTT_SERVER = (config['mqtt']).get('url','localhost')
MQTT_PORT = int((config['mqtt']).get('port','1883'))
MQTT_RECONNECT = int((config['mqtt']).get('reconnect','60'))
MQTT_PATH = (config['mqtt']).get('path','/')
MQTT_COMMAND = (config['mqtt']).get('command','cmnd')
MQTT_STATE = (config['mqtt']).get('state','state')
MY_COMMAND = MQTT_PATH+MQTT_COMMAND
MY_STATE = MQTT_PATH+MQTT_STATE
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
logging.info("Connected with result code "+str(rc))
if rc: logging.warning("Connecting resulted with" +str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe(MY_COMMAND)
logging.info("Subscribed to "+str(MY_COMMAND))
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
manager = SystemdManager()
logging.debug("got message!")
logging.info(msg.topic+" : "+str(msg.payload))
startunit=""
stopunit1=""
stopunit2=""
if str(msg.payload) == "1":
logging.debug("Payload is 1 -> CS")
stopunit1="cps.service"
startunit="calibre-server.service"
elif str(msg.payload) == "2":
logging.debug("Payload is 2 -> CPS")
startunit="cps.service"
stopunit1="calibre-server.service"
elif str(msg.payload) == "0":
logging.debug("Payload is 0 -> OFF")
stopunit2="cps.service"
stopunit1="calibre-server.service"
else:
logging.info("Payload is "+str(msg.payload)+" -> only send state")
if stopunit1 != "":
logging.debug("stop service "+stopunit1+"!")
manager.stop_unit(stopunit1)
if stopunit2 != "":
logging.debug("stop service "+stopunit2+"!")
manager.stop_unit(stopunit2)
client.publish(MY_STATE, payload="0", qos=0, retain=False)
logging.debug("published state 0 to "+MY_STATE)
if startunit != "":
logging.debug("wait until starting service!")
time.sleep(10)
logging.debug("starting service "+startunit+"!")
manager.start_unit(startunit)
logging.debug("publishing state")
if manager.is_active("cps.service"):
cpsstate="ON"
client.publish(MY_STATE, payload="2", qos=0, retain=False)
logging.debug("published state 2 to "+MY_STATE)
else:
cpsstate="OFF"
if manager.is_active("calibre-server.service"):
csstate="ON"
client.publish(MY_STATE, payload="1", qos=0, retain=False)
logging.debug("published state 1 to "+MY_STATE)
else:
csstate="OFF"
client.publish(MQTT_PATH+"cs/state", payload=csstate, qos=0, retain=False)
client.publish(MQTT_PATH+"cps/state", payload=cpsstate, qos=0, retain=False)
logging.debug("published state "+csstate+" to "+MQTT_PATH+"cs/state")
logging.debug("published state "+cpsstate+" to "+MQTT_PATH+"cps/state")
# more callbacks, etc
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, MQTT_PORT, MQTT_RECONNECT)
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()
Code: Alles auswählen
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_SERVER, MQTT_PORT, MQTT_RECONNECT)
client.loop_forever()
Danach geht der client in eine Endlosschleife (client.loop_forever).
in der connect-Routine wird nach dem connect ein Topic subscribed, auf welches der Client fortan reagiert. Die Reaktion passiert in on_message, hier findet die eigentliche Arbeit statt.
Das Script läuft bei mir als Daemon. Ich sollte vielleicht noch erwähnen, dass ich von python keine Ahnung habe vermutlich ließe sich das alles auch viel eleganter lösen, aber es tut, was es soll