commit 8e6bd6765ed1f30a9d2e21c4dcb51650790ffff2 Author: Julian Appel Date: Thu Dec 14 16:13:12 2023 +0100 First working version with smllib diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/heatingMeter.py b/heatingMeter.py new file mode 100644 index 0000000..2779065 --- /dev/null +++ b/heatingMeter.py @@ -0,0 +1,67 @@ +from smllib import SmlStreamReader +import time +import serial +from datetime import datetime + +from influxdb_client import Point, WritePrecision +from influx import writeToDB + +stream = SmlStreamReader() +port = serial.Serial(port='/dev/ttyUSB1', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) + +energyCounter = 0 # Counter for values that should only be pushed to db every minute + +while True: + energyCounter += 1 + pushTime = datetime.utcnow() # Get current datetime and safe it in pushTime variable + pointList = [] # Create list pointList where influxdb datapoint are stored before pushing to db + sml_frame = stream.get_frame() # Create the frame object from bytestream which is None until the frame is complete + + while sml_frame is None: + stream.add(port.read()) # Add bytes until full frame is received + try: + sml_frame = stream.get_frame() # Find frame from stream + except Exception: + print("CRCERROR") + pass + + # A quick Shortcut to extract all values without parsing the whole frame + # In rare cases this might raise an InvalidBufferPos exception, then you have to use sml_frame.parse_frame() + obis_values = sml_frame.get_obis() + + # return all values but slower + parsed_msgs = sml_frame.parse_frame() + for msg in parsed_msgs: + # prints a nice overview over the received values + print(msg.format_msg()) + + # In the parsed message the obis values are typically found like this + obis_values = parsed_msgs[1].message_body.val_list + + # The obis attribute of the SmlListEntry carries different obis representations as attributes + list_entry = obis_values[3] + + heatPowerIn = int(obis_values[5].value*0.01) + heatEnergyIn = int(obis_values[2].value*0.0001) + heatEnergyInHT = int(obis_values[3].value*0.0001) + heatEnergyInNT = int(obis_values[4].value*0.0001) + + print("Heizung Wirkleistung aktuell: " + str(heatPowerIn) + "W") + print("Heizung Energie bezug gesamt: " + str(heatEnergyIn) + "kWh") + print("Heizung Energie bezug HT: " + str(heatEnergyInHT) + "kWh") + print("Heizung Energie bezug NT: " + str(heatEnergyInNT) + "kWh") + pointList.append( Point('power').field('heatPowerIn', heatPowerIn).time(pushTime, WritePrecision.S) ) + + if energyCounter % 12 == 0: # Only add energy to db every 6th while loop (every minute) + pointList.append( Point('energy').field('heatEnergyIn', heatEnergyIn).time(pushTime, WritePrecision.S) ) + pointList.append( Point('energy').field('heatEnergyInHT', heatEnergyInHT).time(pushTime, WritePrecision.S) ) + pointList.append( Point('energy').field('heatEnergyInNT', heatEnergyInNT).time(pushTime, WritePrecision.S) ) + print("Energy in DB") + energyCounter = 0 + + for point in pointList: + print(point) + + writeToDB(pointList) + + time.sleep(5) \ No newline at end of file diff --git a/influx.py b/influx.py new file mode 100644 index 0000000..0c36a09 --- /dev/null +++ b/influx.py @@ -0,0 +1,16 @@ +from influxdb_client import InfluxDBClient, Point, WritePrecision +from influxdb_client.client.write_api import SYNCHRONOUS + +token = "chOaOOaMs1QpQaYwYgj3TWT-z1LxuoWP_YC7M0rrFqFwNDVnGzyGKrUMqSPHN0_xPOgyEzedKu3i8wbCLVHyFg==" +org = "main" +bucket = "power" + +client = InfluxDBClient(url="http://localhost:8086", token=token, org=org, timeout=30000) +write_api = client.write_api(write_options=SYNCHRONOUS) + + +def writeToDB(dataPoints): + """ Writes measurement to influx + """ + write_api.write(bucket, record=dataPoints) + print("Added to DB") diff --git a/officeMeter.py b/officeMeter.py new file mode 100644 index 0000000..3249161 --- /dev/null +++ b/officeMeter.py @@ -0,0 +1,61 @@ +from smllib import SmlStreamReader +import time +import serial +from datetime import datetime + +from influxdb_client import Point, WritePrecision +from influx import writeToDB + +stream = SmlStreamReader() +port = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) + +energyCounter = 0 # Counter for values that should only be pushed to db every minute + +while True: + energyCounter += 1 + pushTime = datetime.utcnow() # Get current datetime and safe it in pushTime variable + pointList = [] # Create list pointList where influxdb datapoint are stored before pushing to db + sml_frame = stream.get_frame() # Create the frame object from bytestream which is None until the frame is complete + + while sml_frame is None: + stream.add(port.read()) # Add bytes until full frame is received + try: + sml_frame = stream.get_frame() # Find frame from stream + except Exception: + print("CRCERROR") + pass + + # A quick Shortcut to extract all values without parsing the whole frame + # In rare cases this might raise an InvalidBufferPos exception, then you have to use sml_frame.parse_frame() + obis_values = sml_frame.get_obis() + + # return all values but slower + parsed_msgs = sml_frame.parse_frame() + for msg in parsed_msgs: + # prints a nice overview over the received values + print(msg.format_msg()) + + # In the parsed message the obis values are typically found like this + obis_values = parsed_msgs[1].message_body.val_list + + # The obis attribute of the SmlListEntry carries different obis representations as attributes + list_entry = obis_values[3] + + officePowerIn = int(obis_values[3].value*0.01) + officeEnergyIn = int(obis_values[2].value*0.0001) + + print("Büro Wirkleistung aktuell: " + str(officePowerIn) + "W") + print("Büro Energie bezug gesamt: " + str(officeEnergyIn) + "kWh") + pointList.append( Point('power').field('officePowerIn', officePowerIn).time(pushTime, WritePrecision.S) ) + + if energyCounter % 12 == 0: # Only add energy to db every 6th while loop (every minute) + pointList.append( Point('energy').field('officeEnergyIn', officeEnergyIn).time(pushTime, WritePrecision.S) ) + print("Energy in DB") + energyCounter = 0 + + for point in pointList: + print(point) + + writeToDB(pointList) + + time.sleep(5) \ No newline at end of file