Initial commit

This commit is contained in:
Ard Kuijpers
2020-06-03 13:15:53 +02:00
commit 2f6e219e50
14 changed files with 535 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
.mypy_cache/
# local files
.env
.vscode

1
__init__.py Normal file
View File

@@ -0,0 +1 @@
__version__ = "0.1.0"

60
device_dsmr.py Normal file
View File

@@ -0,0 +1,60 @@
from homie.device_base import Device_Base
from homie.node.node_base import Node_Base
from settings import Settings
import logging
logger = logging.getLogger(__name__)
SETTINGS = Settings()
TRANSLATED_MQTT_SETTINGS = {
'MQTT_BROKER': SETTINGS.mqtt_host,
'MQTT_PORT': SETTINGS.mqtt_port,
'MQTT_USERNAME' : SETTINGS.mqtt_username,
'MQTT_PASSWORD' : SETTINGS.mqtt_password,
'MQTT_CLIENT_ID' : SETTINGS.hostname,
'MQTT_SHARE_CLIENT': False,
}
TRANSLATED_HOMIE_SETTINGS = {
'topic' : SETTINGS.homie_topic,
'fw_name' : SETTINGS.homie_fw_name,
'fw_version' : SETTINGS.homie_fw_version,
'update_interval' : SETTINGS.homie_update_interval,
}
class Device_DSMR(Device_Base):
def __init__(self, device_id=None, name=None, homie_settings=TRANSLATED_HOMIE_SETTINSG, mqtt_settings=TRANSLATED_MQTT_SETTINGS):
super().__init__(device_id, name, homie_settings, mqtt_settings)
node = Node_Base(self, "gasmeter", "Gasmeter", "status")
self.add_node(node)
self.start()
def register_status_properties(self, node):
super(Device_Temperature_Humidity_Battery, self).register_status_properties(
node
)
self.battery = Property_Battery(node)
node.add_property(self.battery)
def update_battery(self, battery):
logger.info("Updated Battery {}".format(battery))
self.battery.value = battery
/Ene5\T210-D ESMR5.0

134
dsmr2mqtt.py Normal file
View File

@@ -0,0 +1,134 @@
#!/usr/bin/env python
# Python script om P1 telegram weer te geven
import datetime
import re
import serial
import homie
import paho.mqtt.client as paho
VERSION = 0.1
def on_publish(client,userdata,result): #create function for callback
print("data published \n")
pass
client1=paho.Client("control1") #create client object
client1.on_publish = on_publish #assign function to callback
client1.connect(broker,port) #establish connection
class DSMRConnection:
def __init__(self):
"""Seriele poort confguratie naar DSMR configuratie"""
cfg = Settings()
self.serial = serial.Serial(
port=cfg.dsmr_port,
baudrate=cfg.dsmr_baudrate,
parity=serial.PARITY_NAMES[cfg.dsmr_parity],
timeout=10,
xonxoff=0
)
self.mqttclient = paho.Client(cfg.)
kwhtot = 0
kwhoud = 0
kwhverschil = 0
gastot = 0
gasoud = 0
gasverschil = 0
# Telegram
#
# /KMP5 KA6U001660740912
#
# 0-0:96.1.1(204B413655303031363630373430393132)
# 1-0:1.8.1(13629.373*kWh)
# 1-0:1.8.2(14700.866*kWh)
# 1-0:2.8.1(00000.000*kWh)
# 1-0:2.8.2(00000.000*kWh)
# 0-0:96.14.0(0001)
# 1-0:1.7.0(0000.64*kW)
# 1-0:2.7.0(0000.00*kW)
# 0-0:96.13.1()
# 0-0:96.13.0()
# 0-1:24.1.0(3)
# 0-1:96.1.0(3238313031353431303037343732343132)
# 0-1:24.3.0(180428140000)(08)(60)(1)(0-1:24.2.1)(m3)
# (03862.650)
# !
while True:
ser.open()
checksum_found = False
gasflag = 0
while not checksum_found:
telegram_line = ser.readline() # Lees een seriele lijn in.
telegram_line = telegram_line.decode('ascii').strip() # Strip spaties en blanke regels
#print (telegram_line) #debug
if re.match(b'(?=1-0:1.7.0)', telegram_line): #1-0:1.7.0 = Actueel verbruik in kW
# 1-0:1.7.0(0000.54*kW)
kw = telegram_line[10:-4] # Knip het kW gedeelte eruit (0000.54)
watt = float(kw) * 1000 # vermengvuldig met 1000 voor conversie naar Watt (540.0)
watt = int(watt) # rond float af naar heel getal (540)
if re.match(b'(?=1-0:1.8.1)', telegram_line): #1-0:1.8.1 - Hoog tarief / 1-0:1.8.1(13579.595*kWh)
kwh1 = telegram_line[10:-5] # Knip het kWh gedeelte eruit (13579.595)
if re.match(b'(?=1-0:1.8.2)', telegram_line): #1-0:1.8.2 - Laag tarief / 1-0:1.8.2(14655.223*kWh)
kwh2 = telegram_line[10:-5] # Knip het kWh gedeelte eruit (14655.223)
if gasflag == 1:
gas = telegram_line[1:-1]
gasflag = 0
if re.match(b'(?=0-1:24.3.0)', telegram_line): #0-1:24.3.0 - Gasverbruik
gasflag = 1
# Check wanneer het uitroepteken ontavangen wordt (einde telegram)
if re.match(b'(?=!)', telegram_line):
checksum_found = True
ser.close()
#######################################
if kwhoud < 1: #Script eerste keer opgestart, sla waarde op
kwhoud = kwhtot
kwhtot = float(kwh1) + float(kwh2)
kwhverschil = round(float(kwhtot) - float(kwhoud), 3)
if gasoud < 1: #Script eerste keer opgestart, sla waarde op
gasoud = gas
gasouduur = gas
gasverschil = round(float(gas) - float(gasoud), 3)
gasverschiluur = round(float(gas) - float(gasouduur), 3)
# Reset tellers
tijd = str(datetime.datetime.now().time())[0:-10]
tijdmin = str(datetime.datetime.now().time())[3:-10]
if tijd == "00:00": # Reset de counter van de dag
kwhoud = kwhtot
gasoud = gas
if tijdmin == "00": # Reset de counter van het uur
gasouduur = gas
######################################
# MQTT PUBLISH
######################################
client1.publish("elektra\w", watt)
client1.publish("elektra\kwh", kwhverschil)
client1.publish("gas", gasverschil)
client1.publish("gas\\uur", gasverschiluur)

0
node/__init__.py Normal file
View File

View File

@@ -0,0 +1,85 @@
from homie.node.node_base import Node_Base
from homie.node.property.property_enum import Property_Enum
from homie.node.property.property_integer import Property_Integer
from dsmr2mqtt.node.property.property_energy import Property_Energy
from dsmr2mqtt.node.property.property_power import Property_Power
from dsmr2mqtt.node.property.property_current import Property_Current
from dsmr2mqtt.node.property.property_voltage import Property_Voltage
class Node_ElectricityMeter(Node_Base):
def __init__(
self,
device,
id="electricitymeter",
name="Electricity meter",
type_="state",
retain=True,
qos=1,
state_values=None,
set_state=None,
):
assert state_values
assert set_state
super().__init__(device, id, name, type_, retain, qos)
self.add_property(Property_Integer(self, "tariff_indicator", "Tariff indicator", data_format="1:2", settable=False))
self.add_property(Property_Energy(self, "delivery_tariff1", "Delivery tariff 1"))
self.add_property(Property_Energy(self, "delivery_tariff2", "Delivery tariff 2"))
self.add_property(Property_Power(self, "power", "Power"))
self.add_property(Property_Voltage(self, "voltage_L1", "Voltage L1"))
self.add_property(Property_Voltage(self, "voltage_L2", "Voltage L2"))
self.add_property(Property_Voltage(self, "voltage_L3", "Voltage L3"))
self.add_property(Property_Current(self, "current_L1", "Current L1"))
self.add_property(Property_Current(self, "current_L2", "Current L2"))
self.add_property(Property_Current(self, "current_L3", "Current L3"))
self.add_property(Property_Power(self, "power_L1", "Power L1"))
self.add_property(Property_Power(self, "power_L2", "Power L2"))
self.add_property(Property_Power(self, "power_L3", "Power L3"))
def update_status(self, telegram: str):
#Telegram
# 1-3:0.2.8(50)
# 0-0:1.0.0(200603122725S)
# 0-0:96.1.1(4530303438303030303339393038333139)
# 1-0:1.8.1(001807.864*kWh)
# 1-0:1.8.2(001173.872*kWh)
# 1-0:2.8.1(000000.091*kWh)
# 1-0:2.8.2(000000.000*kWh)
# 0-0:96.14.0(0002)
# 1-0:1.7.0(00.909*kW)
# 1-0:2.7.0(00.000*kW)
# 0-0:96.7.21(00016)
# 0-0:96.7.9(00003)
# 1-0:99.97.0(0)(0-0:96.7.19)
# 1-0:32.32.0(00002)
# 1-0:52.32.0(00002)
# 1-0:72.32.0(00002)
# 1-0:32.36.0(00000)
# 1-0:52.36.0(00000)
# 1-0:72.36.0(00000)
# 0-0:96.13.0()
# 1-0:32.7.0(235.0*V)
# 1-0:52.7.0(237.0*V)
# 1-0:72.7.0(236.0*V)
# 1-0:31.7.0(001*A)
# 1-0:51.7.0(001*A)
# 1-0:71.7.0(001*A)
# 1-0:21.7.0(00.290*kW)
# 1-0:41.7.0(00.268*kW)
# 1-0:61.7.0(00.350*kW)
# 1-0:22.7.0(00.000*kW)
# 1-0:42.7.0(00.000*kW)
# 1-0:62.7.0(00.000*kW)
# 0-1:24.1.0(003)
# 0-1:96.1.0(4730303732303033393435373234323139)
# 0-1:24.2.1(200603122500S)(01741.782*m3)
pass

31
node/node_gasmeter.py Normal file
View File

@@ -0,0 +1,31 @@
from homie.node.node_base import Node_Base
from homie.node.property.property_enum import Property_Enum
from dsmr2mqtt.node.property.property_volume import Property_Volume
class Node_Gasmeter(Node_Base):
def __init__(
self,
device,
id="gasmeter",
name="Gas meter",
type_="state",
retain=True,
qos=1,
state_values=None,
set_state=None,
):
assert state_values
assert set_state
super().__init__(device, id, name, type_, retain, qos)
self.add_property(
Property_Volume(
self, "volume", "Volume", data_format=state_values, set_value=set_state
)
)
def update_volume(self, volume):
self.get_property("volume").value = volume

View File

View File

@@ -0,0 +1,37 @@
from homie.node.property.property_float import Property_Float
class Property_Current(Property_Float):
def __init__(
self,
node,
id="current",
name="Current",
settable=False,
retained=True,
qos=1,
unit="A",
data_type=None,
data_format=None,
value=None,
set_value=None,
tags=[],
meta={},
):
super().__init__(
node,
id,
name,
settable,
retained,
qos,
unit,
data_type,
data_format,
value,
set_value,
tags,
meta,
)

View File

@@ -0,0 +1,37 @@
from homie.node.property.property_float import Property_Float
class Property_Energy(Property_Float):
def __init__(
self,
node,
id="energy",
name="Energy",
settable=False,
retained=True,
qos=1,
unit="kWh",
data_type=None,
data_format=None,
value=None,
set_value=None,
tags=[],
meta={},
):
super().__init__(
node,
id,
name,
settable,
retained,
qos,
unit,
data_type,
data_format,
value,
set_value,
tags,
meta,
)

View File

@@ -0,0 +1,37 @@
from homie.node.property.property_float import Property_Float
class Property_Power(Property_Float):
def __init__(
self,
node,
id="power",
name="Power",
settable=False,
retained=True,
qos=1,
unit="W",
data_type=None,
data_format=None,
value=None,
set_value=None,
tags=[],
meta={},
):
super().__init__(
node,
id,
name,
settable,
retained,
qos,
unit,
data_type,
data_format,
value,
set_value,
tags,
meta,
)

View File

@@ -0,0 +1,37 @@
from homie.node.property.property_float import Property_Float
class Property_Voltage(Property_Float):
def __init__(
self,
node,
id="voltage",
name="Voltage",
settable=False,
retained=True,
qos=1,
unit="V",
data_type=None,
data_format=None,
value=None,
set_value=None,
tags=[],
meta={},
):
super().__init__(
node,
id,
name,
settable,
retained,
qos,
unit,
data_type,
data_format,
value,
set_value,
tags,
meta,
)

View File

@@ -0,0 +1,37 @@
from homie.node.property.property_float import Property_Float
class Property_Volume(Property_Float):
def __init__(
self,
node,
id="volume",
name="Volume",
settable=False,
retained=True,
qos=1,
unit="",
data_type=None,
data_format=None,
value=None,
set_value=None,
tags=[],
meta={},
):
super().__init__(
node,
id,
name,
settable,
retained,
qos,
unit,
data_type,
data_format,
value,
set_value,
tags,
meta,
)

31
settings.py Normal file
View File

@@ -0,0 +1,31 @@
from pydantic import BaseSettings, Field
from openhab.__init__ import __version__
class Settings(BaseSettings):
"""Application settings for the DSMR MQTT bridge."""
loglevel: str = Field('INFO', env='LOGLEVEL')
mqtt_host: str = Field(None, env='MQTT_HOST')
mqtt_port: int = Field(1883, env='MQTT_PORT')
mqtt_username: str = Field(None, env='MQTT_USERNAME')
mqtt_password: str = Field(None, env='MQTT_PASSWORD')
dsmr_port: str = Field('/dev/ttyUSB0', env='DSMR_PORT')
dsmr_baudrate: str = Field(115200, env='DSMR_BAUDRATE')
dsmr_bytesize: str = Field('EIGHTBITS', env='DSMR_BITESIZE')
dsmr_parity: str = Field('NONE', env='DSMR_PARITY')
dsmr_stopbits: str = Field('ONE', env='DSMR_STOPBITS')
homie_update_interval: int = 60
homie_topic: str = Field('homie', env='HOMIE_TOPIC')
homie_implementation: str \
= f"DSMR Homie {VERSION} Homie 4 Version {homie.__version__}"
homie_fw_name: str = "DSMR"
homie_fw_version: str = "0.1.0"
class Config:
"""Where to find the environment file containing the settings."""
env_file = '.env'