diff --git a/README.md b/README.md index 6dd53c7..7cd077b 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ ### python - paho-mqtt +- gpiozero + diff --git a/piValues2MQTT.py b/piValues2MQTT.py new file mode 100755 index 0000000..3e03ff7 --- /dev/null +++ b/piValues2MQTT.py @@ -0,0 +1,217 @@ +#!/usr/bin/python3 + +# \file piValues2MQTT.py +# \brief piValues2MQTT +# \author Pascal Gollor +# \copyright cc 2020 by-sa + + +import optparse, logging, signal, time, re, argparse, platform +from btlewrap.bluepy import BluepyBackend +import paho.mqtt.client as mqtt +from gpiozero import CPUTemperature + + +DEFAULT_MQTT_SERVER = "127.0.0.1" +DEFAULT_MQTT_PORT = 1883 +DEFAULT_BASETOPIC = "pis" # without leading / + + +## detecting kill signal +# source: http://stackoverflow.com/questions/18499497/how-to-process-sigterm-signal-gracefully +class GracefulKiller: + def __init__(self): + self.kill_now = False + + signal.signal(signal.SIGINT, self.exit_gracefully) + signal.signal(signal.SIGTERM, self.exit_gracefully) + # end __init__ + + def exit_gracefully(self, signum, frame): + self.kill_now = True + # end exit_gracefully +# end class GracefulKiller + + +def on_connect(client, userdata, flags, rc): + userdata['logger'].info("Connected with result code: %i", rc) +# end on_connect + + +def on_disconnect(client, userdata, rc): + msg = "Disconnected with result code: %i" + if (rc): + userdata['logger'].error(msg, rc) + else: + userdata['logger'].info(msg, rc) + # end if +# end on_disconnect + + +def main(): + parser = optparse.OptionParser( + usage = "%prog [options]", + description = "piValues2MQTT Grab Measurement data from RaspberryPi an post as MQTT topic", + version="%prog 0.1a" + ) + + group = optparse.OptionGroup(parser, "MQTT settings") + group.add_option("-s", "--server", + dest = "server", + help = "mqtt server, default %default", + default = DEFAULT_MQTT_SERVER + ) + group.add_option("--port", + dest = "port", + action = "store", + type = 'int', + help = "mqtt server port, default %default", + default = DEFAULT_MQTT_PORT + ) + group.add_option("-k", "--keepalive", + dest = "keepalive", + action = "store", + type = 'int', + help = "keepalive option for mqtt server, default %default", + default = 60 + ) + group.add_option("-t", "--topic", + dest = "basetopic", + help = "basetopic to publish to without leading /, default %default", + default = DEFAULT_BASETOPIC + ) + group.add_option("-u", "--username", + dest = "username", + help = "connection username", + default = "" + ) + group.add_option("-p", "--password", + dest = "password", + help = "connection password", + default = "" + ) + parser.add_option_group(group) + + group = optparse.OptionGroup(parser, "Basic settings") + group.add_option('-i', '--interval', + dest = 'interval', + help = 'polling interval in seconds, default %default', + type = 'int', + default = 60 + ) + group.add_option("-l", "--loglevel", + dest = "loglevel", + action = "store", + type = 'int', + help = str(logging.CRITICAL) + ": critical " + str(logging.ERROR) + ": error " + str(logging.WARNING) + ": warning " + str(logging.INFO) + ":info " + str(logging.DEBUG) + ":debug", + default = logging.ERROR + ) + group.add_option("-v", "--verbose", + dest = "verbose", + action = "store_true", + help = "show debug messages (overrites loglevel to debug)", + default = False + ) + parser.add_option_group(group) + + # parse options + (options, _) = parser.parse_args() + + # init logging + loglevel = int(options.loglevel) + if (options.verbose): + loglevel = logging.DEBUG + # end if + logger = logging.getLogger("piValues2MQTT") + logger.setLevel(loglevel) + ch = logging.StreamHandler() + ch.setLevel(loglevel) + formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s') + formatter.datefmt = '%Y-%m-%d %H:%M:%S' + ch.setFormatter(formatter) + logger.addHandler(ch) + + # add logger to userdata + userdata = dict() + userdata['logger'] = logger + + # add killer + killer = GracefulKiller() + + # add mqtt client + client = mqtt.Client() + + # set user data for MQTT callbacks + client.user_data_set(userdata) + + # register MQTT callbacks + client.on_connect = on_connect + client.on_disconnect = on_disconnect + + # check username and password + if (len(options.username) > 0): + if (len(options.password) == 0): + raise ValueError("please do not use username without password") + # end if + + client.username_pw_set(options.username, options.password) + # end if + + # debug output + logger.debug("server: %s" ,options.server) + logger.debug("port: %i", options.port) + logger.debug("bsaetopic: %s", options.basetopic) + logger.debug('polling interval: %i seconds', options.interval) + + # connect to MQTT server + logger.debug("connect to mqtt client") + client.connect(options.server, options.port, options.keepalive) + + # start client loop + client.loop_start() + + # forever loop + hostName = platform.node() + mqttTopic = options.basetopic + '/' + hostName + mqttTopic = mqttTopic.replace(':', '-') + lastPoll = 0 + try: + logger.debug("start program loop") + + while (1): + currentTime = time.time() + if (lastPoll == 0 or currentTime - lastPoll >= options.interval): + lastPoll = currentTime + + # get data + jsonStr = '{"cpuTemperature":' + str(CPUTemperature().temperature) + '}' + logger.debug(jsonStr) + + client.publish(mqttTopic, jsonStr) + # end if + + time.sleep(0.1) + + if (killer.kill_now): + raise KeyboardInterrupt + # end if + # end while + except KeyboardInterrupt: + logger.debug("exit program loop") + # end try + + # disconnecting + logger.debug("disconnecting from MQTT server") + client.loop_stop() + client.disconnect() +# end main + + + +if __name__ == "__main__": + try: + main() + except Exception as e: + logging.error(str(e)) + # end try +# end if