minor fixes

This commit is contained in:
T 2025-01-27 14:17:52 +01:00
parent 6c2f762898
commit 9f8a12c1cd

View File

@ -1,200 +1,204 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from select import poll, POLLPRI, POLLIN, POLLERR
import sys
import os
import threading
import time
import queue
import requests
import configparser import configparser
import logging import logging
import os
import queue
import sys
import threading
import time
from select import poll, POLLERR
import paho.mqtt.publish as mqtt import paho.mqtt.publish as mqtt
import requests
def trans_http(): def trans_http():
global serverconf global serverconf
# build together url and headers # build together url and headers
uri = "" uri = ""
if serverconf.getboolean("ssl") == True: if serverconf.getboolean("ssl"):
uri = "https://" uri = "https://"
else: else:
uri = "http://" uri = "http://"
uri = uri + serverconf["url"] + "/get.php" uri = uri + serverconf["url"] + "/get.php"
log.info('Remote URI: {}'.format(uri)) log.info('Remote URI: {}'.format(uri))
queuelast = time.time() queuelast = time.time()
while True: while True:
# get value from queue (blocking) # get value from queue (blocking)
queuedata = powerqueue.get() queuedata = powerqueue.get()
powerqueue.task_done() powerqueue.task_done()
queuetime = int(queuedata[0]) queuetime = int(queuedata[0])
queueval = str(queuedata[1]) queueval = str(queuedata[1])
# if more than five seconds passed since last event # if more than five seconds passed since last event
if ((queuetime - queuelast) >= 5): if (queuetime - queuelast) >= 5:
# put payload together # put payload together
if serverconf.getboolean('timestamp'): if serverconf.getboolean('timestamp'):
payload = {"val": str(queuetime) + ";" + str(queueval)} payload = {"val": str(queuetime) + ";" + str(queueval)}
else: else:
payload = {"val": str(queueval)} payload = {"val": str(queueval)}
log.debug('request {}:{}{} => {}'.format(mqttconf['host'], mqttconf['port'], mqttconf['topic'], repr(payload))) log.debug('request {}:{}{} => {}'.format(mqttconf['host'], mqttconf['port'], mqttconf['topic'], repr(payload)))
# send to http server # send to http server
try: try:
if serverconf.getboolean("basicauth") == True: if serverconf.getboolean("basicauth"):
r = requests.post(uri, data=payload, verify=False, auth=(serverconf["user"], serverconf["password"]), timeout=10, headers={'connection':'close'}) r = requests.post(uri, data=payload, verify=False, auth=(serverconf["user"], serverconf["password"]), timeout=10, headers={'connection': 'close'})
else: else:
r = requests.post(uri, data=payload, verify=False, timeout=10, headers={'connection':'close'}) r = requests.post(uri, data=payload, verify=False, timeout=10, headers={'connection': 'close'})
except: except:
log.error('server response: {}'.format(str(r.status_code))) log.error('server response: {}'.format(str(r.status_code)))
queuelast = queuetime queuelast = queuetime
else: else:
# drop data if less than five seconds passed since last event # drop data if less than five seconds passed since last event
del queuedata del queuedata
log.info('dropped queued element') log.info('dropped queued element')
def trans_mqtt(): def trans_mqtt():
global mqttconf global mqttconf
queuelast = time.time() queuelast = time.time()
log.info('sending data via mqtt host: {}, port: {}, topic:{}'.format(mqttconf['host'], mqttconf['port'], mqttconf['topic'])) log.info('sending data via mqtt host: {}, port: {}, topic:{}'.format(mqttconf['host'], mqttconf['port'], mqttconf['topic']))
while True: while True:
# get value from queue (blocking) # get value from queue (blocking)
queuedata = powerqueue.get() queuedata = powerqueue.get()
powerqueue.task_done() powerqueue.task_done()
queuetime = int(queuedata[0]) queuetime = int(queuedata[0])
queueval = str(queuedata[1]) queueval = str(queuedata[1])
# if more than five seconds passed since last event # if more than five seconds passed since last event
if ((queuetime - queuelast) >= 5): if (queuetime - queuelast) >= 5:
# put payload together # put payload together
if mqttconf.getboolean('timestamp'): if mqttconf.getboolean('timestamp'):
payload = str(queuetime) + ";" + str(queueval) payload = str(queuetime) + ";" + str(queueval)
else: else:
payload = str(queueval) payload = str(queueval)
log.debug('mqtt {} => {}'.format(mqttconf['host'], repr(payload))) log.debug('mqtt {} => {}'.format(mqttconf['host'], repr(payload)))
# send to mqtt broker # send to mqtt broker
try: try:
mqtt.single(mqttconf['topic'], payload=payload, retain=True, hostname=mqttconf['host'], mqtt.single(mqttconf['topic'], payload=payload, retain=True, hostname=mqttconf['host'],
port=mqttconf.getint('port'), client_id=mqttconf['clientid'], transport="tcp") port=mqttconf.getint('port'), client_id=mqttconf['clientid'], transport="tcp")
except BaseException as e: except BaseException as e:
log.error('error while publishing: {}'.format(e)) log.error('error while publishing: {}'.format(e))
queuelast = queuetime queuelast = queuetime
else: else:
# drop data if less than five seconds passed since last event # drop data if less than five seconds passed since last event
del queuedata del queuedata
log.info('dropped queued element') log.info('dropped queued element')
def readgpio(): def readgpio():
global gpiopath global gpiopath
global gpioconf global gpioconf
global smconf global smconf
# open gpio filehandle # open gpio file handle
gpio = open(gpiopath + "value", "r") gpio = open(gpiopath + "value", "r")
# setup polling # setup polling
gpiopoll = poll() gpiopoll = poll()
gpiopoll.register(gpio, POLLERR) gpiopoll.register(gpio, POLLERR)
# wait for two interrupts to have a "clean" starting point # wait for two interrupts to have a "clean" starting point
log.info('waiting for 2 interrupts to get a clean start') log.info('waiting for 2 interrupts to get a clean start')
gpioevent = gpiopoll.poll() gpioevent = gpiopoll.poll()
gpio.read() gpio.read()
gpio.seek(0) gpio.seek(0)
log.info('waiting for 1 interrupt to get a clean start...') log.info('waiting for 1 interrupt to get a clean start...')
gpioevent = gpiopoll.poll() gpioevent = gpiopoll.poll()
last = time.time() last = time.time()
gpio.read() gpio.read()
gpio.seek(0) gpio.seek(0)
# start readgpio mainloop # start readgpio mainloop
log.info('start readgpio mainloop') log.info('start readgpio mainloop')
while True: while True:
gpioevent = gpiopoll.poll() gpioevent = gpiopoll.poll()
gpioval = gpio.read(1) gpioval = gpio.read(1)
gpio.seek(0) gpio.seek(0)
# check if interrupt was a falling edge (yes, really!) # check if interrupt was a falling edge (yes, really!)
if gpioval == '0': if gpioval == '0':
now = time.time() now = time.time()
# plausibility check # plausibility check
if ((now-last) >= gpioconf.getfloat("mintime")): if (now - last) >= gpioconf.getfloat("mintime"):
# calculate current power consumption # calculate current power consumption
power = round((3600000/smconf.getint("impkwh")) / (now-last),2) power = round((3600000 / smconf.getint("impkwh")) / (now - last), 2)
log.info('Current power consumption: {} Watt'.format(str(power))) log.info('Current power consumption: {} Watt'.format(str(power)))
log.debug('GPIO state: {}'.format(gpioval)) log.debug('GPIO state: {}'.format(gpioval))
# put measured value on queue # put measured value on queue
powerqueue.put([now, power]) powerqueue.put([now, power])
last = now last = now
# error if a tty is connected and a raising edge was triggered # error if a tty is connected and a raising edge was triggered
else: else:
log.debug('Not a falling edge, ignoring') log.debug('Not a falling edge, ignoring')
if __name__ == "__main__": if __name__ == "__main__":
# read config # configure logging
dirname, filename = os.path.split(os.path.abspath(__file__)) log = logging.getLogger(__name__)
conf = configparser.ConfigParser() log.setLevel(logging.DEBUG)
try: ch = logging.StreamHandler()
conf.read(os.path.join(dirname, "powerpi.local.conf")) ch.setLevel(logging.INFO)
except:
conf.read(os.path.join(dirname, "powerpi.conf"))
log.warning('using global config. Use powerpi.local.conf instead')
conf.sections()
transconf = conf['transport']
gpioconf = conf['gpio']
serverconf = conf['server']
smconf = conf['smartmeter']
mqttconf = conf['mqtt']
# configure logging
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
log.info('Running in path {}'.format(dirname))
if serverconf["url"] == "power.example.com" and mqttconf['host'] == "power.example.com":
log.critical('Server/Broker -> url still default value')
exit(1)
gpiopath = "/sys/class/gpio/gpio" + gpioconf["port"] + "/"
# initialise gpio interfaces
try:
if not os.path.exists(gpiopath):
# if not already exported, export gpio port
gpioinit = open("/sys/class/gpio/export", "w")
gpioinit.write(gpioconf["port"] + "\n")
gpioinit.close()
# set direction of gpio port to "IN"
gpiopin = open(gpiopath + "direction", "w")
gpiopin.write("in")
gpiopin.close()
# set trigger to falling edge
gpiotype = open(gpiopath + "edge", "w")
gpiotype.write("falling")
gpiotype.close()
except:
log.critical('can not initialize gpio interface. aborting.')
sys.exit(1)
# defining queue for measured values
powerqueue = queue.Queue()
# disable ssl "no verification" warnings # read config
if serverconf.getboolean("sslself") == True: dirname, filename = os.path.split(os.path.abspath(__file__))
requests.packages.urllib3.disable_warnings() conf = configparser.ConfigParser()
try:
conf.read(os.path.join(dirname, "powerpi.local.conf"))
except:
conf.read(os.path.join(dirname, "powerpi.conf"))
log.warning('using global config. Use powerpi.local.conf instead')
conf.sections()
transconf = conf['transport']
gpioconf = conf['gpio']
serverconf = conf['server']
smconf = conf['smartmeter']
mqttconf = conf['mqtt']
# initialising and starting threads log.info('Running in path {}'.format(dirname))
th1 = threading.Thread(target=readgpio) if serverconf["url"] == "power.example.com" and mqttconf['host'] == "power.example.com":
if transconf['transport'] == 'mqtt': log.critical('Server/Broker -> url still default value')
log.info('method of transfer: mqtt') exit(1)
th2 = threading.Thread(target=trans_mqtt) gpiopath = "/sys/class/gpio/gpio" + gpioconf["port"] + "/"
elif transconf['transport'] == 'http': # initialise gpio interfaces
log.info('method of transfer: http') try:
th2 = threading.Thread(target=trans_http) if not os.path.exists(gpiopath):
else: # if not already exported, export gpio port
log.error('transfer option {} is invalid. Exiting!'.format(transfer['transfer'])) gpioinit = open("/sys/class/gpio/export", "w")
sys.exit(1) gpioinit.write(gpioconf["port"] + "\n")
gpioinit.close()
# set direction of gpio port to "IN"
gpiopin = open(gpiopath + "direction", "w")
gpiopin.write("in")
gpiopin.close()
# set trigger to falling edge
gpiotype = open(gpiopath + "edge", "w")
gpiotype.write("falling")
gpiotype.close()
except:
log.critical('can not initialize gpio interface. aborting.')
sys.exit(1)
# defining queue for measured values
powerqueue = queue.Queue()
th1.setDaemon(True) # disable ssl "no verification" warnings
th2.setDaemon(True) if serverconf.getboolean("sslself"):
th1.start() requests.packages.urllib3.disable_warnings()
th2.start()
#busy loop # initialising and starting threads
while True: th1 = threading.Thread(target=readgpio)
time.sleep(1) if transconf['transport'] == 'mqtt':
log.info('method of transfer: mqtt')
th2 = threading.Thread(target=trans_mqtt)
elif transconf['transport'] == 'http':
log.info('method of transfer: http')
th2 = threading.Thread(target=trans_http)
else:
log.error('transfer option {} is invalid. Exiting!'.format(transconf['transport']))
sys.exit(1)
th1.setDaemon(True)
th2.setDaemon(True)
th1.start()
th2.start()
# busy loop
while True:
time.sleep(1)