Skip to content

Commit

Permalink
Change default V5 to mbus
Browse files Browse the repository at this point in the history
At least the BE and the NL DSMR devices use MBUS.
Therefor we make the MBUS obis reference generic, and convert the V5
telegram to use MBUS values.

Also remove BELGIUM_MAX_POWER_PER_PHASE as this was a duplicate.

Finally set self.maxDiff = None to have a full test output on some
tests.
  • Loading branch information
dupondje committed Oct 26, 2023
1 parent 5810770 commit b4fa6be
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 297 deletions.
50 changes: 18 additions & 32 deletions dsmr_parser/obis_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,25 @@
ACTUAL_SWITCH_POSITION = r'^\d-\d:96\.3\.10.+?\r\n'
VALVE_POSITION_GAS = r'^\d-\d:24\.4\.0.+?\r\n'

# Multiple 'slaves' can be linked to the main device.
# The type is reported on 24.1.0
# Specifications are in EN 13757-3
# For example: Water mater = 7, Gas meter = 3
# Identifier is on 96.1.0 (in NL for ex) or
# on 96.1.1 (in BE for ex)
# The values are reported on 24.2.1
# With an exception in Belgium for the GAS meter
# Be aware that for the gas volume, another OBIS-code is published
# than the one listed in section 7 of DSMR P1.
# This is due to the fact that in Belgium the not-temperature
# corrected gas volume is used while in the Netherlands,
# the temperature corrected gas volume is used.
MBUS_DEVICE_TYPE = r'^\d-\d:24\.1\.0.+?\r\n'
MBUS_EQUIPMENT_IDENTIFIER = r'^\d-[1-9]:96\.1\.[01].+?\r\n'
MBUS_VALVE_POSITION = r'^\d-\d:24\.4\.0.+?\r\n'
MBUS_METER_READING = r'^\d-\d:24\.2\.[13].+?\r\n'

# TODO 17.0.0
# TODO 96.3.10

ELECTRICITY_USED_TARIFF_ALL = (
ELECTRICITY_USED_TARIFF_1,
Expand All @@ -91,37 +108,6 @@
BELGIUM_CURRENT_AVERAGE_DEMAND = r'^\d-\d:1\.4\.0.+?\r\n'
BELGIUM_MAXIMUM_DEMAND_MONTH = r'^\d-\d:1\.6\.0.+?\r\n'
BELGIUM_MAXIMUM_DEMAND_13_MONTHS = r'^\d-\d:98\.1\.0.+?\r\n'
BELGIUM_MAX_POWER_PER_PHASE = r'^\d-\d:17\.0\.0.+?\r\n' # Applicable when power limitation is active

# Multiple 'slaves' can be linked to the main device.
# Mostly MBUS1 = GAS METER with values on 24.2.3
# While WATER METER reports it's values on 24.2.1
# The GAS METER also reports its valve state on 24.4.0
# Dev type for gas = 7 and water = 8
BELGIUM_MBUS1_DEVICE_TYPE = r'^\d-1:24\.1\.0.+?\r\n'
BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER = r'^\d-1:96\.1\.1.+?\r\n'
BELGIUM_MBUS1_VALVE_POSITION = r'^\d-1:24\.4\.0.+?\r\n'
BELGIUM_MBUS1_METER_READING1 = r'^\d-1:24\.2\.1.+?\r\n'
BELGIUM_MBUS1_METER_READING2 = r'^\d-1:24\.2\.3.+?\r\n'

BELGIUM_MBUS2_DEVICE_TYPE = r'^\d-2:24\.1\.0.+?\r\n'
BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER = r'^\d-2:96\.1\.1.+?\r\n'
BELGIUM_MBUS2_VALVE_POSITION = r'^\d-2:24\.4\.0.+?\r\n'
BELGIUM_MBUS2_METER_READING1 = r'^\d-2:24\.2\.1.+?\r\n'
BELGIUM_MBUS2_METER_READING2 = r'^\d-2:24\.2\.3.+?\r\n'

BELGIUM_MBUS3_DEVICE_TYPE = r'^\d-3:24\.1\.0.+?\r\n'
BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER = r'^\d-3:96\.1\.1.+?\r\n'
BELGIUM_MBUS3_VALVE_POSITION = r'^\d-3:24\.4\.0.+?\r\n'
BELGIUM_MBUS3_METER_READING1 = r'^\d-3:24\.2\.1.+?\r\n'
BELGIUM_MBUS3_METER_READING2 = r'^\d-3:24\.2\.3.+?\r\n'

BELGIUM_MBUS4_DEVICE_TYPE = r'^\d-4:24\.1\.0.+?\r\n'
BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER = r'^\d-4:96\.1\.1.+?\r\n'
BELGIUM_MBUS4_VALVE_POSITION = r'^\d-4:24\.4\.0.+?\r\n'
BELGIUM_MBUS4_METER_READING1 = r'^\d-4:24\.2\.1.+?\r\n'
BELGIUM_MBUS4_METER_READING2 = r'^\d-4:24\.2\.3.+?\r\n'


LUXEMBOURG_EQUIPMENT_IDENTIFIER = r'^\d-\d:42\.0\.0.+?\r\n' # Logical device name

Expand Down
4 changes: 2 additions & 2 deletions dsmr_parser/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ def __init__(self, *args, **kwargs):
def add(self, obis_reference, dsmr_object, obis_name):
# Update name mapping used to get value by attribute. Example: telegram.P1_MESSAGE_HEADER
setattr(self, obis_name, dsmr_object)
if obis_name not in self._item_names: # TODO repeating obis references
self._item_names.append(obis_name)

# TODO isinstance check: MaxDemandParser (BELGIUM_MAXIMUM_DEMAND_13_MONTHS) returns a list
if isinstance(dsmr_object, DSMRObject) and dsmr_object.is_mbus_reading:
self._add_mbus(obis_reference, dsmr_object, obis_name)
elif obis_name not in self._item_names: # TODO repeating obis references
self._item_names.append(obis_name)

# Fill dict which is only used for backwards compatibility
if obis_reference not in self:
Expand Down
149 changes: 24 additions & 125 deletions dsmr_parser/telegram_specifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,6 @@
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'TEXT_MESSAGE'
},
{
'obis_reference': obis.DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'DEVICE_TYPE'
},
{
'obis_reference': obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE,
'value_parser': CosemParser(ValueParser(Decimal)),
Expand Down Expand Up @@ -466,17 +461,27 @@
'value_name': 'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE'
},
{
'obis_reference': obis.EQUIPMENT_IDENTIFIER_GAS,
'obis_reference': obis.MBUS_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'MBUS_DEVICE_TYPE'
},
{
'obis_reference': obis.MBUS_EQUIPMENT_IDENTIFIER,
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'EQUIPMENT_IDENTIFIER_GAS'
'value_name': 'MBUS_EQUIPMENT_IDENTIFIER'
},
{
'obis_reference': obis.HOURLY_GAS_METER_READING,
'value_parser': MBusParser(
'obis_reference': obis.MBUS_VALVE_POSITION,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'MBUS_VALVE_POSITION'
},
{
'obis_reference': obis.MBUS_METER_READING,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'HOURLY_GAS_METER_READING'
'value_name': 'MBUS_METER_READING'
},
]
}
Expand Down Expand Up @@ -624,11 +629,6 @@
'value_parser': CosemParser(ValueParser(Decimal)),
'value_name': 'ACTUAL_TRESHOLD_ELECTRICITY'
},
{
'obis_reference': obis.BELGIUM_MAX_POWER_PER_PHASE,
'value_parser': CosemParser(ValueParser(Decimal)),
'value_name': 'BELGIUM_MAX_POWER_PER_PHASE'
},
{
'obis_reference': obis.FUSE_THRESHOLD_L1,
'value_parser': CosemParser(ValueParser(Decimal)),
Expand All @@ -640,128 +640,27 @@
'value_name': 'TEXT_MESSAGE'
},
{
'obis_reference': obis.BELGIUM_MBUS1_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS1_DEVICE_TYPE'
},
{
'obis_reference': obis.BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER,
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER'
},
{
'obis_reference': obis.BELGIUM_MBUS1_VALVE_POSITION,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS1_VALVE_POSITION'
},
{
'obis_reference': obis.BELGIUM_MBUS1_METER_READING1,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS1_METER_READING1'
},
{
'obis_reference': obis.BELGIUM_MBUS1_METER_READING2,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS1_METER_READING2'
},
{
'obis_reference': obis.BELGIUM_MBUS2_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS2_DEVICE_TYPE'
},
{
'obis_reference': obis.BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER,
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER'
},
{
'obis_reference': obis.BELGIUM_MBUS2_VALVE_POSITION,
'obis_reference': obis.MBUS_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS2_VALVE_POSITION'
},
{
'obis_reference': obis.BELGIUM_MBUS2_METER_READING1,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS2_METER_READING1'
'value_name': 'MBUS_DEVICE_TYPE'
},
{
'obis_reference': obis.BELGIUM_MBUS2_METER_READING2,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS2_METER_READING2'
},
{
'obis_reference': obis.BELGIUM_MBUS3_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS3_DEVICE_TYPE'
},
{
'obis_reference': obis.BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER,
'obis_reference': obis.MBUS_EQUIPMENT_IDENTIFIER,
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER'
'value_name': 'MBUS_EQUIPMENT_IDENTIFIER'
},
{
'obis_reference': obis.BELGIUM_MBUS3_VALVE_POSITION,
'obis_reference': obis.MBUS_VALVE_POSITION,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS3_VALVE_POSITION'
},
{
'obis_reference': obis.BELGIUM_MBUS3_METER_READING1,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS3_METER_READING1'
'value_name': 'MBUS_VALVE_POSITION'
},
{
'obis_reference': obis.BELGIUM_MBUS3_METER_READING2,
'obis_reference': obis.MBUS_METER_READING,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS3_METER_READING2'
},
{
'obis_reference': obis.BELGIUM_MBUS4_DEVICE_TYPE,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS4_DEVICE_TYPE'
},
{
'obis_reference': obis.BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER,
'value_parser': CosemParser(ValueParser(str)),
'value_name': 'BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER'
},
{
'obis_reference': obis.BELGIUM_MBUS4_VALVE_POSITION,
'value_parser': CosemParser(ValueParser(int)),
'value_name': 'BELGIUM_MBUS4_VALVE_POSITION'
},
{
'obis_reference': obis.BELGIUM_MBUS4_METER_READING1,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS4_METER_READING1'
},
{
'obis_reference': obis.BELGIUM_MBUS4_METER_READING2,
'value_parser': MBusParser(
ValueParser(timestamp),
ValueParser(Decimal)
),
'value_name': 'BELGIUM_MBUS4_METER_READING2'
'value_name': 'MBUS_METER_READING'
},
]
}
Expand Down Expand Up @@ -1233,7 +1132,7 @@
# This seems to be wrong in documentation, it's not 0-0:96.50.68, but 0-0:96.3.10
},
{
'obis_reference': obis.BELGIUM_MAX_POWER_PER_PHASE,
'obis_reference': obis.ACTUAL_TRESHOLD_ELECTRICITY,
'value_parser': CosemParser(ValueParser(Decimal)),
'value_name': 'ACTUAL_TRESHOLD_ELECTRICITY'
},
Expand Down
42 changes: 21 additions & 21 deletions test/objects/test_mbusdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,59 +15,59 @@ def setUp(self):
device_type_parser = [
object["value_parser"]
for object in v5_objects
if object["obis_reference"] == obis_references.DEVICE_TYPE
if object["obis_reference"] == obis_references.MBUS_DEVICE_TYPE
][0]
device_type = device_type_parser.parse('0-2:24.1.0(003)\r\n')

equipment_parser = [
object["value_parser"]
for object in v5_objects
if object["obis_reference"] == obis_references.EQUIPMENT_IDENTIFIER_GAS
if object["obis_reference"] == obis_references.MBUS_EQUIPMENT_IDENTIFIER
][0]
equipment = equipment_parser.parse('0-2:96.1.0(4730303339303031393336393930363139)\r\n')

gas_reading_parser = [
object["value_parser"]
for object in v5_objects
if object["obis_reference"] == obis_references.HOURLY_GAS_METER_READING
if object["obis_reference"] == obis_references.MBUS_METER_READING
][0]
gas_reading = gas_reading_parser.parse('0-2:24.2.1(200426223001S)(00246.138*m3)\r\n')

mbus_device = MbusDevice(channel_id=1)
mbus_device.add(obis_references.DEVICE_TYPE, device_type, "DEVICE_TYPE")
mbus_device.add(obis_references.EQUIPMENT_IDENTIFIER_GAS, equipment, "EQUIPMENT_IDENTIFIER_GAS")
mbus_device.add(obis_references.HOURLY_GAS_METER_READING, gas_reading, "HOURLY_GAS_METER_READING")
mbus_device = MbusDevice(channel_id=2)
mbus_device.add(obis_references.MBUS_DEVICE_TYPE, device_type, "MBUS_DEVICE_TYPE")
mbus_device.add(obis_references.MBUS_EQUIPMENT_IDENTIFIER, equipment, "MBUS_EQUIPMENT_IDENTIFIER")
mbus_device.add(obis_references.MBUS_METER_READING, gas_reading, "MBUS_METER_READING")

self.mbus_device = mbus_device

def test_attributes(self):
self.assertEqual(self.mbus_device.DEVICE_TYPE.value, 3)
self.assertEqual(self.mbus_device.DEVICE_TYPE.unit, None)
self.assertEqual(self.mbus_device.MBUS_DEVICE_TYPE.value, 3)
self.assertEqual(self.mbus_device.MBUS_DEVICE_TYPE.unit, None)

self.assertEqual(self.mbus_device.EQUIPMENT_IDENTIFIER_GAS.value,
self.assertEqual(self.mbus_device.MBUS_EQUIPMENT_IDENTIFIER.value,
'4730303339303031393336393930363139')
self.assertEqual(self.mbus_device.EQUIPMENT_IDENTIFIER_GAS.unit, None)
self.assertEqual(self.mbus_device.MBUS_EQUIPMENT_IDENTIFIER.unit, None)

self.assertEqual(self.mbus_device.HOURLY_GAS_METER_READING.value, Decimal('246.138'))
self.assertEqual(self.mbus_device.HOURLY_GAS_METER_READING.unit, 'm3')
self.assertEqual(self.mbus_device.MBUS_METER_READING.value, Decimal('246.138'))
self.assertEqual(self.mbus_device.MBUS_METER_READING.unit, 'm3')

def test_to_json(self):
self.assertEqual(
json.loads(self.mbus_device.to_json()),
{
'CHANNEL_ID': 1,
'DEVICE_TYPE': {'value': 3, 'unit': None},
'EQUIPMENT_IDENTIFIER_GAS': {'value': '4730303339303031393336393930363139', 'unit': None},
'HOURLY_GAS_METER_READING': {'datetime': '2020-04-26T20:30:01+00:00', 'value': 246.138, 'unit': 'm3'}}
'CHANNEL_ID': 2,
'MBUS_DEVICE_TYPE': {'value': 3, 'unit': None},
'MBUS_EQUIPMENT_IDENTIFIER': {'value': '4730303339303031393336393930363139', 'unit': None},
'MBUS_METER_READING': {'datetime': '2020-04-26T20:30:01+00:00', 'value': 246.138, 'unit': 'm3'}}
)

def test_str(self):
self.assertEqual(
str(self.mbus_device),
(
'MBUS DEVICE (channel 1)\n'
'\tDEVICE_TYPE: 3 [None]\n'
'\tEQUIPMENT_IDENTIFIER_GAS: 4730303339303031393336393930363139 [None]\n'
'\tHOURLY_GAS_METER_READING: 246.138 [m3] at 2020-04-26T20:30:01+00:00\n'
'MBUS DEVICE (channel 2)\n'
'\tMBUS_DEVICE_TYPE: 3 [None]\n'
'\tMBUS_EQUIPMENT_IDENTIFIER: 4730303339303031393336393930363139 [None]\n'
'\tMBUS_METER_READING: 246.138 [m3] at 2020-04-26T20:30:01+00:00\n'
)
)
Loading

0 comments on commit b4fa6be

Please sign in to comment.