#!/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("basetopic: %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
logger.debug("mqtt topic: %s", mqttTopic)
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