Merged master into autodetecttelegram
This commit is contained in:
+281
-4
@@ -1,5 +1,5 @@
|
||||
TELEGRAM_V2_2 = (
|
||||
'/ISk5\2MT382-1004\r\n'
|
||||
'/ISk5\\2MT382-1004\r\n'
|
||||
'\r\n'
|
||||
'0-0:96.1.1(00000000000000)\r\n'
|
||||
'1-0:1.8.1(00001.001*kWh)\r\n'
|
||||
@@ -22,7 +22,7 @@ TELEGRAM_V2_2 = (
|
||||
)
|
||||
|
||||
TELEGRAM_V3 = (
|
||||
'/ISk5\2MT382-1000\r\n'
|
||||
'/ISk5\\2MT382-1000\r\n'
|
||||
'\r\n'
|
||||
'0-0:96.1.1(4B384547303034303436333935353037)\r\n'
|
||||
'1-0:1.8.1(12345.678*kWh)\r\n'
|
||||
@@ -87,7 +87,7 @@ TELEGRAM_V4_2 = (
|
||||
)
|
||||
|
||||
TELEGRAM_V5 = (
|
||||
'/ISk5\2MT382-1000\r\n'
|
||||
'/ISk5\\2MT382-1000\r\n'
|
||||
'\r\n'
|
||||
'1-3:0.2.8(50)\r\n'
|
||||
'0-0:1.0.0(170102192002W)\r\n'
|
||||
@@ -126,5 +126,282 @@ TELEGRAM_V5 = (
|
||||
'0-1:24.2.1(170102161005W)(00000.107*m3)\r\n'
|
||||
'0-2:24.1.0(003)\r\n'
|
||||
'0-2:96.1.0()\r\n'
|
||||
'!87B3\r\n'
|
||||
'!6EEE\r\n'
|
||||
)
|
||||
|
||||
# V5 telegram with 2 MBUS devices
|
||||
TELEGRAM_V5_TWO_MBUS = (
|
||||
'/ISK5\\2M550T-1012\r\n'
|
||||
'\r\n'
|
||||
'1-3:0.2.8(50)\r\n'
|
||||
'0-0:1.0.0(200426223325S)\r\n'
|
||||
'0-0:96.1.1(4530303434303037333832323436303139)\r\n'
|
||||
'1-0:1.8.1(002130.115*kWh)\r\n'
|
||||
'1-0:1.8.2(000245.467*kWh)\r\n'
|
||||
'1-0:2.8.1(000000.000*kWh)\r\n'
|
||||
'1-0:2.8.2(000000.000*kWh)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'1-0:1.7.0(00.111*kW)\r\n'
|
||||
'1-0:2.7.0(00.000*kW)\r\n'
|
||||
'0-0:96.7.21(00005)\r\n'
|
||||
'0-0:96.7.9(00003)\r\n'
|
||||
'1-0:99.97.0(1)(0-0:96.7.19)(190326095015W)(0000002014*s)\r\n'
|
||||
'1-0:32.32.0(00001)\r\n'
|
||||
'1-0:52.32.0(00001)\r\n'
|
||||
'1-0:72.32.0(00192)\r\n'
|
||||
'1-0:32.36.0(00001)\r\n'
|
||||
'1-0:52.36.0(00001)\r\n'
|
||||
'1-0:72.36.0(00001)\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'1-0:32.7.0(229.9*V)\r\n'
|
||||
'1-0:52.7.0(229.2*V)\r\n'
|
||||
'1-0:72.7.0(222.9*V)\r\n'
|
||||
'1-0:31.7.0(000*A)\r\n'
|
||||
'1-0:51.7.0(000*A)\r\n'
|
||||
'1-0:71.7.0(001*A)\r\n'
|
||||
'1-0:21.7.0(00.056*kW)\r\n'
|
||||
'1-0:41.7.0(00.000*kW)\r\n'
|
||||
'1-0:61.7.0(00.055*kW)\r\n'
|
||||
'1-0:22.7.0(00.000*kW)\r\n'
|
||||
'1-0:42.7.0(00.000*kW)\r\n'
|
||||
'1-0:62.7.0(00.000*kW)\r\n'
|
||||
'0-1:24.1.0(003)\r\n'
|
||||
'0-1:96.1.0()\r\n'
|
||||
'0-1:24.2.1(700101010000W)(00000000)\r\n'
|
||||
'0-2:24.1.0(003)\r\n'
|
||||
'0-2:96.1.0(4730303339303031393336393930363139)\r\n'
|
||||
'0-2:24.2.1(200426223001S)(00246.138*m3)\r\n'
|
||||
'!56DD\r\n'
|
||||
)
|
||||
|
||||
TELEGRAM_FLUVIUS_V171 = (
|
||||
'/FLU5\\253769484_A\r\n'
|
||||
'\r\n'
|
||||
'0-0:96.1.4(50217)\r\n'
|
||||
'0-0:96.1.1(3153414733313031303231363035)\r\n'
|
||||
'0-0:1.0.0(200512135409S)\r\n'
|
||||
'1-0:1.8.1(000000.034*kWh)\r\n'
|
||||
'1-0:1.8.2(000015.758*kWh)\r\n'
|
||||
'1-0:2.8.1(000000.000*kWh)\r\n'
|
||||
'1-0:2.8.2(000000.011*kWh)\r\n'
|
||||
'1-0:1.4.0(02.351*kW)\r\n'
|
||||
'1-0:1.6.0(200509134558S)(02.589*kW)\r\n'
|
||||
'0-0:98.1.0(3)(1-0:1.6.0)(1-0:1.6.0)(200501000000S)(200423192538S)(03.695*kW)(200401000000S)(200305122139S)(05.980*kW)(200301000000S)(200210035421W)(04.318*kW)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'1-0:1.7.0(00.000*kW)\r\n'
|
||||
'1-0:2.7.0(00.000*kW)\r\n'
|
||||
'1-0:21.7.0(00.000*kW)\r\n'
|
||||
'1-0:41.7.0(00.000*kW)\r\n'
|
||||
'1-0:61.7.0(00.000*kW)\r\n'
|
||||
'1-0:22.7.0(00.000*kW)\r\n'
|
||||
'1-0:42.7.0(00.000*kW)\r\n'
|
||||
'1-0:62.7.0(00.000*kW)\r\n'
|
||||
'1-0:32.7.0(234.7*V)\r\n'
|
||||
'1-0:52.7.0(234.7*V)\r\n'
|
||||
'1-0:72.7.0(234.7*V)\r\n'
|
||||
'1-0:31.7.0(000.00*A)\r\n'
|
||||
'1-0:51.7.0(000.00*A)\r\n'
|
||||
'1-0:71.7.0(000.00*A)\r\n'
|
||||
'0-0:96.3.10(1)\r\n'
|
||||
'0-0:17.0.0(999.9*kW)\r\n'
|
||||
'1-0:31.4.0(999*A)\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'0-1:24.1.0(003)\r\n'
|
||||
'0-1:96.1.1(37464C4F32313139303333373333)\r\n'
|
||||
'0-1:24.4.0(1)\r\n'
|
||||
'0-1:24.2.3(200512134558S)(00112.384*m3)\r\n'
|
||||
'0-2:24.1.0(007)\r\n'
|
||||
'0-2:96.1.1(3853414731323334353637383930)\r\n'
|
||||
'0-2:24.2.1(200512134558S)(00872.234*m3)\r\n'
|
||||
'!3AD7\r\n'
|
||||
)
|
||||
|
||||
TELEGRAM_FLUVIUS_V171_ALT = (
|
||||
'/FLU5\\253769484_A\r\n'
|
||||
'\r\n'
|
||||
'0-0:96.1.4(50217)\r\n'
|
||||
'0-0:96.1.1(3153414733313030373231333236)\r\n'
|
||||
'0-0:1.0.0(231102121548W)\r\n'
|
||||
'1-0:1.8.1(000301.548*kWh)\r\n'
|
||||
'1-0:1.8.2(000270.014*kWh)\r\n'
|
||||
'1-0:2.8.1(000000.005*kWh)\r\n'
|
||||
'1-0:2.8.2(000000.000*kWh)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'1-0:1.4.0(00.052*kW)\r\n'
|
||||
'1-0:1.6.0(231102114500W)(03.064*kW)\r\n'
|
||||
'0-0:98.1.0(4)(1-0:1.6.0)(1-0:1.6.0)(230801000000S)(632525252525W)(00.000*kW)(230901000000S)(230831181500S)(01.862*kW)(231001000000S)(230910183000S)(04.229*kW)(231101000000W)(231016130000S)(04.927*kW)\r\n'
|
||||
'1-0:1.7.0(00.338*kW)\r\n'
|
||||
'1-0:2.7.0(00.000*kW)\r\n'
|
||||
'1-0:21.7.0(00.047*kW)\r\n'
|
||||
'1-0:41.7.0(00.179*kW)\r\n'
|
||||
'1-0:61.7.0(00.111*kW)\r\n'
|
||||
'1-0:22.7.0(00.000*kW)\r\n'
|
||||
'1-0:42.7.0(00.000*kW)\r\n'
|
||||
'1-0:62.7.0(00.000*kW)\r\n'
|
||||
'1-0:32.7.0(232.9*V)\r\n'
|
||||
'1-0:52.7.0(228.1*V)\r\n'
|
||||
'1-0:72.7.0(228.1*V)\r\n'
|
||||
'1-0:31.7.0(000.27*A)\r\n'
|
||||
'1-0:51.7.0(000.88*A)\r\n'
|
||||
'1-0:71.7.0(000.52*A)\r\n'
|
||||
'0-0:96.3.10(1)\r\n'
|
||||
'0-0:17.0.0(999.9*kW)\r\n'
|
||||
'1-0:31.4.0(999*A)\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'0-1:24.1.0(003)\r\n'
|
||||
'0-1:96.1.1(37464C4F32313233303838303237)\r\n'
|
||||
'0-1:24.4.0(1)\r\n'
|
||||
'0-1:24.2.3(231102121002W)(00092.287*m3)\r\n'
|
||||
'0-2:24.1.0(007)\r\n'
|
||||
'0-2:96.1.1(3853455430303030393631313733)\r\n'
|
||||
'0-2:24.2.1(231102121532W)(00008.579*m3)\r\n'
|
||||
'!C4B0\r\n'
|
||||
)
|
||||
|
||||
# EasyMeter via COM-1 Ethernet Gateway
|
||||
# Q3D Manual (german) https://www.easymeter.com/downloads/products/zaehler/Q3D/Easymeter_Q3D_DE_2016-06-15.pdf
|
||||
# - type code on page 8
|
||||
# - D0-Specs on page 20
|
||||
#
|
||||
# last two lines are added by the COM-1 Ethernet Gateway
|
||||
|
||||
TELEGRAM_ESY5Q3DB1024_V304 = (
|
||||
'/ESY5Q3DB1024 V3.04\r\n'
|
||||
'\r\n'
|
||||
'1-0:0.0.0*255(0272031312565)\r\n'
|
||||
'1-0:1.8.0*255(00052185.7825309*kWh)\r\n'
|
||||
'1-0:2.8.0*255(00019949.3221493*kWh)\r\n'
|
||||
'1-0:21.7.0*255(000747.85*W)\r\n'
|
||||
'1-0:41.7.0*255(000737.28*W)\r\n'
|
||||
'1-0:61.7.0*255(000639.73*W)\r\n'
|
||||
'1-0:1.7.0*255(002124.86*W)\r\n'
|
||||
'1-0:96.5.5*255(80)\r\n'
|
||||
'0-0:96.1.255*255(1ESY1313002565)\r\n'
|
||||
'!\r\n'
|
||||
' 25803103\r\n'
|
||||
'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||
'\xff\xff\xff\xff\xff\r\n'
|
||||
)
|
||||
|
||||
TELEGRAM_ESY5Q3DA1004_V304 = (
|
||||
'/ESY5Q3DA1004 V3.04\r\n'
|
||||
'\r\n'
|
||||
'1-0:0.0.0*255(1336001560)\r\n'
|
||||
'1-0:1.8.0*255(00032549.5061662*kWh)\r\n'
|
||||
'1-0:21.7.0*255(000557.29*W)\r\n'
|
||||
'1-0:41.7.0*255(000521.62*W)\r\n'
|
||||
'1-0:61.7.0*255(000609.30*W)\r\n'
|
||||
'1-0:1.7.0*255(001688.21*W)\r\n'
|
||||
'1-0:96.5.5*255(80)\r\n'
|
||||
'0-0:96.1.255*255(1ESY1336001560)\r\n'
|
||||
'!\r\n'
|
||||
' 25818685\r\n'
|
||||
'DE0000000000000000000000000000003\r\n'
|
||||
)
|
||||
|
||||
TELEGRAM_SAGEMCOM_T210_D_R = (
|
||||
'/EST5\\253710000_A\r\n'
|
||||
'\r\n'
|
||||
'1-3:0.2.8(50)\r\n'
|
||||
'0-0:1.0.0(221006155014S)\r\n'
|
||||
'1-0:1.8.0(006545766*Wh)\r\n'
|
||||
'1-0:1.8.1(005017120*Wh)\r\n'
|
||||
'1-0:1.8.2(001528646*Wh)\r\n'
|
||||
'1-0:1.7.0(000000286*W)\r\n'
|
||||
'1-0:2.8.0(000000058*Wh)\r\n'
|
||||
'1-0:2.8.1(000000000*Wh)\r\n'
|
||||
'1-0:2.8.2(000000058*Wh)\r\n'
|
||||
'1-0:2.7.0(000000000*W)\r\n'
|
||||
'1-0:3.8.0(000000747*varh)\r\n'
|
||||
'1-0:3.8.1(000000000*varh)\r\n'
|
||||
'1-0:3.8.2(000000747*varh)\r\n'
|
||||
'1-0:3.7.0(000000000*var)\r\n'
|
||||
'1-0:4.8.0(003897726*varh)\r\n'
|
||||
'1-0:4.8.1(002692848*varh)\r\n'
|
||||
'1-0:4.8.2(001204878*varh)\r\n'
|
||||
'1-0:4.7.0(000000166*var)\r\n'
|
||||
'!7EF9\r\n'
|
||||
)
|
||||
|
||||
TELEGRAM_ISKRA_IE = (
|
||||
'/ISk5\2MIE5T-200\r\n'
|
||||
'\r\n'
|
||||
'1-0:0.0.0(00000000)\r\n'
|
||||
'0-0:96.1.0(09610)\r\n'
|
||||
'0-0:1.0.0(230202132747S)\r\n'
|
||||
'1-0:1.8.1(000010.181*kWh)\r\n'
|
||||
'1-0:1.8.2(000010.182*kWh)\r\n'
|
||||
'1-0:2.8.1(000010.281*kWh)\r\n'
|
||||
'1-0:2.8.2(000010.282*kWh)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'1-0:1.7.0(00.170*kW)\r\n'
|
||||
'1-0:2.7.0(00.270*kW)\r\n'
|
||||
'1-0:21.7.0(00.217*kW)\r\n'
|
||||
'1-0:41.7.0(00.417*kW)\r\n'
|
||||
'1-0:61.7.0(00.617*kW)\r\n'
|
||||
'1-0:22.7.0(00.227*kW)\r\n'
|
||||
'1-0:42.7.0(00.427*kW)\r\n'
|
||||
'1-0:62.7.0(00.627*kW)\r\n'
|
||||
'1-0:32.7.0(242.5*V)\r\n'
|
||||
'1-0:52.7.0(241.7*V)\r\n'
|
||||
'1-0:72.7.0(243.3*V)\r\n'
|
||||
'1-0:31.7.0(000*A)\r\n'
|
||||
'1-0:51.7.0(000*A)\r\n'
|
||||
'1-0:71.7.0(000*A)\r\n'
|
||||
'0-0:96.3.10(1)\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'0-1:96.1.1()\r\n'
|
||||
'!AD3B\r\n'
|
||||
)
|
||||
|
||||
# V5 telegram of EON in Hungary
|
||||
TELEGRAM_V5_EON_HU = (
|
||||
'/SAG5SAG-METER\r\n'
|
||||
'\r\n'
|
||||
'0-0:1.0.0(230724150730S)\r\n'
|
||||
'0-0:42.0.0(53414733303832323030303032313630)\r\n'
|
||||
'0-0:96.1.0(383930303832323030303032313630)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'0-0:96.3.10(1)\r\n'
|
||||
'0-0:17.0.0(90.000*kW)\r\n'
|
||||
'1-0:1.8.0(000173.640*kWh)\r\n'
|
||||
'1-0:1.8.1(000047.719*kWh)\r\n'
|
||||
'1-0:1.8.2(000125.921*kWh)\r\n'
|
||||
'1-0:1.8.3(000000.000*kWh)\r\n'
|
||||
'1-0:1.8.4(000000.000*kWh)\r\n'
|
||||
'1-0:2.8.0(000627.177*kWh)\r\n'
|
||||
'1-0:2.8.1(000401.829*kWh)\r\n'
|
||||
'1-0:2.8.2(000225.348*kWh)\r\n'
|
||||
'1-0:2.8.3(000000.000*kWh)\r\n'
|
||||
'1-0:2.8.4(000000.000*kWh)\r\n'
|
||||
'1-0:3.8.0(000000.123*kvarh)\r\n'
|
||||
'1-0:4.8.0(000303.131*kvarh)\r\n'
|
||||
'1-0:5.8.0(000000.668*kvarh)\r\n'
|
||||
'1-0:6.8.0(000000.071*kvarh)\r\n'
|
||||
'1-0:7.8.0(000160.487*kvarh)\r\n'
|
||||
'1-0:8.8.0(000143.346*kvarh)\r\n'
|
||||
'1-0:15.8.0(000800.817*kWh)\r\n'
|
||||
'1-0:32.7.0(240.4*V)\r\n'
|
||||
'1-0:52.7.0(239.1*V)\r\n'
|
||||
'1-0:72.7.0(241.2*V)\r\n'
|
||||
'1-0:31.7.0(003*A)\r\n'
|
||||
'1-0:51.7.0(004*A)\r\n'
|
||||
'1-0:71.7.0(003*A)\r\n'
|
||||
'1-0:13.7.0(4.556)\r\n'
|
||||
'1-0:33.7.0(4.591)\r\n'
|
||||
'1-0:53.7.0(4.542)\r\n'
|
||||
'1-0:73.7.0(4.552)\r\n'
|
||||
'1-0:14.7.0(50.00*Hz)\r\n'
|
||||
'1-0:1.7.0(00.000*kW)\r\n'
|
||||
'1-0:2.7.0(02.601*kW)\r\n'
|
||||
'1-0:5.7.0(00.000*kvar)\r\n'
|
||||
'1-0:6.7.0(00.000*kvar)\r\n'
|
||||
'1-0:7.7.0(00.504*kvar)\r\n'
|
||||
'1-0:8.7.0(00.000*kvar)\r\n'
|
||||
'1-0:31.4.0(200.00*A)\r\n'
|
||||
'1-0:51.4.0(200.00*A)\r\n'
|
||||
'1-0:71.4.0(200.00*A)\r\n'
|
||||
'0-0:98.1.0(230701000000S)(000040.777*kWh)(000008.950*kWh)(000031.827*kWh)(000142.250*kWh)(000111.164*kWh)(000031.086*kWh)(000000.030*kvarh)(000073.988*kvarh)(000000.205*kvarh)(000000.048*kvarh)(000039.199*kvarh)(000035.020*kvarh)(000183.027*kWh)(03.564*kW)(02.156*kW)(03.564*kW)(04.104*kW)(04.104*kW)(03.400*kW)\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'!99DA\r\n'
|
||||
)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from test.example_telegrams import TELEGRAM_V4_2
|
||||
parser = TelegramParser(telegram_specifications.V4)
|
||||
telegram = parser.parse(TELEGRAM_V4_2)
|
||||
|
||||
print(telegram)
|
||||
@@ -0,0 +1,73 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import json
|
||||
import unittest
|
||||
|
||||
from dsmr_parser import telegram_specifications, obis_references
|
||||
from dsmr_parser.objects import MbusDevice
|
||||
|
||||
|
||||
class MbusDeviceTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
v5_objects = telegram_specifications.V5['objects']
|
||||
|
||||
device_type_parser = [
|
||||
object["value_parser"]
|
||||
for object in v5_objects
|
||||
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.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.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=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.MBUS_DEVICE_TYPE.value, 3)
|
||||
self.assertEqual(self.mbus_device.MBUS_DEVICE_TYPE.unit, None)
|
||||
|
||||
self.assertEqual(self.mbus_device.MBUS_EQUIPMENT_IDENTIFIER.value,
|
||||
'4730303339303031393336393930363139')
|
||||
self.assertEqual(self.mbus_device.MBUS_EQUIPMENT_IDENTIFIER.unit, None)
|
||||
|
||||
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': 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 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'
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,88 @@
|
||||
import unittest
|
||||
|
||||
from dsmr_parser import telegram_specifications
|
||||
|
||||
from dsmr_parser.objects import ProfileGenericObject
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from dsmr_parser.parsers import ProfileGenericParser
|
||||
from dsmr_parser.profile_generic_specifications import BUFFER_TYPES
|
||||
from dsmr_parser.profile_generic_specifications import PG_HEAD_PARSERS
|
||||
from dsmr_parser.profile_generic_specifications import PG_UNIDENTIFIED_BUFFERTYPE_PARSERS
|
||||
from test.example_telegrams import TELEGRAM_V5
|
||||
|
||||
|
||||
class TestParserCornerCases(unittest.TestCase):
|
||||
""" Test instantiation of Telegram object """
|
||||
|
||||
def test_power_event_log_empty_1(self):
|
||||
# POWER_EVENT_FAILURE_LOG (1-0:99.97.0)
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5)
|
||||
|
||||
object_type = ProfileGenericObject
|
||||
testitem = telegram.POWER_EVENT_FAILURE_LOG
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.buffer_length == 0
|
||||
assert testitem.buffer_type == '0-0:96.7.19'
|
||||
buffer = testitem.buffer
|
||||
assert isinstance(testitem.buffer, list)
|
||||
assert len(buffer) == 0
|
||||
|
||||
def test_power_event_log_empty_2(self):
|
||||
pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS)
|
||||
object_type = ProfileGenericObject
|
||||
|
||||
# Power Event Log with 0 items and no object type
|
||||
pefl_line = r'1-0:99.97.0(0)()\r\n'
|
||||
testitem = pef_parser.parse(pefl_line)
|
||||
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.buffer_length == 0
|
||||
assert testitem.buffer_type is None
|
||||
buffer = testitem.buffer
|
||||
assert isinstance(testitem.buffer, list)
|
||||
assert len(buffer) == 0
|
||||
assert testitem.values == [{'value': 0, 'unit': None}, {'value': None, 'unit': None}]
|
||||
json = testitem.to_json()
|
||||
assert json == '{"buffer_length": 0, "buffer_type": null, "buffer": []}'
|
||||
|
||||
def test_power_event_log_null_values(self):
|
||||
pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS)
|
||||
object_type = ProfileGenericObject
|
||||
|
||||
# Power Event Log with 1 item and no object type and nno values for the item
|
||||
pefl_line = r'1-0:99.97.0(1)()()()\r\n'
|
||||
testitem = pef_parser.parse(pefl_line)
|
||||
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.buffer_length == 1
|
||||
assert testitem.buffer_type is None
|
||||
buffer = testitem.buffer
|
||||
assert isinstance(testitem.buffer, list)
|
||||
assert len(buffer) == 1
|
||||
assert testitem.values == [{'value': 1, 'unit': None}, {'value': None, 'unit': None},
|
||||
{'value': None, 'unit': None}, {'value': None, 'unit': None}]
|
||||
json = testitem.to_json()
|
||||
assert json == \
|
||||
'{"buffer_length": 1, "buffer_type": null, "buffer": [{"datetime": null, "value": null, "unit": null}]}'
|
||||
|
||||
def test_power_event_log_brackets_only(self):
|
||||
# POWER_EVENT_FAILURE_LOG (1-0:99.97.0)
|
||||
# Issue 57
|
||||
# Test of an ill formatted empty POWER_EVENT_FAILURE_LOG, observed on some smartmeters
|
||||
# The idea is that instead of failing, the parser converts it to an empty POWER_EVENT_FAILURE_LOG
|
||||
pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS)
|
||||
object_type = ProfileGenericObject
|
||||
|
||||
pefl_line = r'1-0:99.97.0()\r\n'
|
||||
testitem = pef_parser.parse(pefl_line)
|
||||
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.buffer_length == 0
|
||||
assert testitem.buffer_type is None
|
||||
buffer = testitem.buffer
|
||||
assert isinstance(testitem.buffer, list)
|
||||
assert len(buffer) == 0
|
||||
assert testitem.values == [{'value': 0, 'unit': None}, {'value': None, 'unit': None}]
|
||||
json = testitem.to_json()
|
||||
assert json == '{"buffer_length": 0, "buffer_type": null, "buffer": []}'
|
||||
@@ -0,0 +1,486 @@
|
||||
import json
|
||||
import unittest
|
||||
import datetime
|
||||
import pytz
|
||||
|
||||
from dsmr_parser import telegram_specifications, obis_references
|
||||
|
||||
from dsmr_parser.objects import CosemObject
|
||||
from dsmr_parser.objects import MBusObject
|
||||
from dsmr_parser.objects import ProfileGenericObject
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from test.example_telegrams import TELEGRAM_V4_2, TELEGRAM_V5_TWO_MBUS, TELEGRAM_V5
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class TelegramTest(unittest.TestCase):
|
||||
""" Test instantiation of Telegram object """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.item_names_tested = []
|
||||
super(TelegramTest, self).__init__(*args, **kwargs)
|
||||
|
||||
def verify_telegram_item(self, telegram, testitem_name, object_type, unit_val, value_type, value_val):
|
||||
testitem = eval("telegram.{}".format(testitem_name))
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.unit == unit_val
|
||||
assert isinstance(testitem.value, value_type)
|
||||
assert testitem.value == value_val
|
||||
self.item_names_tested.append(testitem_name)
|
||||
|
||||
def test_instantiate(self):
|
||||
parser = TelegramParser(telegram_specifications.V4)
|
||||
telegram = parser.parse(TELEGRAM_V4_2)
|
||||
|
||||
# P1_MESSAGE_HEADER (1-3:0.2.8)
|
||||
self.verify_telegram_item(telegram,
|
||||
'P1_MESSAGE_HEADER',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=str,
|
||||
value_val='42')
|
||||
|
||||
# P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'P1_MESSAGE_TIMESTAMP',
|
||||
CosemObject,
|
||||
unit_val=None,
|
||||
value_type=datetime.datetime,
|
||||
value_val=datetime.datetime(2016, 11, 13, 19, 57, 57, tzinfo=pytz.UTC))
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
self.verify_telegram_item(telegram,
|
||||
'ELECTRICITY_USED_TARIFF_1',
|
||||
object_type=CosemObject,
|
||||
unit_val='kWh',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('1581.123'))
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
|
||||
self.verify_telegram_item(telegram,
|
||||
'ELECTRICITY_USED_TARIFF_2',
|
||||
object_type=CosemObject,
|
||||
unit_val='kWh',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('1435.706'))
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
|
||||
self.verify_telegram_item(telegram,
|
||||
'ELECTRICITY_DELIVERED_TARIFF_1',
|
||||
object_type=CosemObject,
|
||||
unit_val='kWh',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
|
||||
self.verify_telegram_item(telegram,
|
||||
'ELECTRICITY_DELIVERED_TARIFF_2',
|
||||
object_type=CosemObject,
|
||||
unit_val='kWh',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'ELECTRICITY_ACTIVE_TARIFF',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=str,
|
||||
value_val='0002')
|
||||
|
||||
# EQUIPMENT_IDENTIFIER (0-0:96.1.1)
|
||||
self.verify_telegram_item(telegram,
|
||||
'EQUIPMENT_IDENTIFIER',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=str,
|
||||
value_val='3960221976967177082151037881335713')
|
||||
|
||||
# CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'CURRENT_ELECTRICITY_USAGE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('2.027'))
|
||||
|
||||
# CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'CURRENT_ELECTRICITY_DELIVERY',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# SHORT_POWER_FAILURE_COUNT (1-0:96.7.21)
|
||||
self.verify_telegram_item(telegram,
|
||||
'SHORT_POWER_FAILURE_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=15)
|
||||
|
||||
# LONG_POWER_FAILURE_COUNT (96.7.9)
|
||||
self.verify_telegram_item(telegram,
|
||||
'LONG_POWER_FAILURE_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=7)
|
||||
|
||||
# VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SAG_L1_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SAG_L2_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SAG_L3_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SWELL_L1_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SWELL_L2_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'VOLTAGE_SWELL_L3_COUNT',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=0)
|
||||
|
||||
# TEXT_MESSAGE_CODE (0-0:96.13.1)
|
||||
self.verify_telegram_item(telegram,
|
||||
'TEXT_MESSAGE_CODE',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=type(None),
|
||||
value_val=None)
|
||||
|
||||
# TEXT_MESSAGE (0-0:96.13.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'TEXT_MESSAGE',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=type(None),
|
||||
value_val=None)
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_CURRENT_L1',
|
||||
object_type=CosemObject,
|
||||
unit_val='A',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_CURRENT_L2',
|
||||
object_type=CosemObject,
|
||||
unit_val='A',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('6'))
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_CURRENT_L3',
|
||||
object_type=CosemObject,
|
||||
unit_val='A',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('2'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0.170'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('1.247'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0.209'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE',
|
||||
object_type=CosemObject,
|
||||
unit_val='kW',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('0'))
|
||||
|
||||
# DEVICE_TYPE (0-1:24.1.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'DEVICE_TYPE',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=int,
|
||||
value_val=3)
|
||||
|
||||
# EQUIPMENT_IDENTIFIER_GAS (0-1:96.1.0)
|
||||
self.verify_telegram_item(telegram,
|
||||
'EQUIPMENT_IDENTIFIER_GAS',
|
||||
object_type=CosemObject,
|
||||
unit_val=None,
|
||||
value_type=str,
|
||||
value_val='4819243993373755377509728609491464')
|
||||
|
||||
# HOURLY_GAS_METER_READING (0-1:24.2.1)
|
||||
self.verify_telegram_item(telegram,
|
||||
'HOURLY_GAS_METER_READING',
|
||||
object_type=MBusObject,
|
||||
unit_val='m3',
|
||||
value_type=Decimal,
|
||||
value_val=Decimal('981.443'))
|
||||
|
||||
# POWER_EVENT_FAILURE_LOG (1-0:99.97.0)
|
||||
testitem_name = 'POWER_EVENT_FAILURE_LOG'
|
||||
object_type = ProfileGenericObject
|
||||
testitem = eval("telegram.{}".format(testitem_name))
|
||||
assert isinstance(testitem, object_type)
|
||||
assert testitem.buffer_length == 3
|
||||
assert testitem.buffer_type == '0-0:96.7.19'
|
||||
buffer = testitem.buffer
|
||||
assert isinstance(testitem.buffer, list)
|
||||
assert len(buffer) == 3
|
||||
assert all([isinstance(item, MBusObject) for item in buffer])
|
||||
date0 = datetime.datetime(2000, 1, 4, 17, 3, 20, tzinfo=datetime.timezone.utc)
|
||||
date1 = datetime.datetime(1999, 12, 31, 23, 0, 1, tzinfo=datetime.timezone.utc)
|
||||
date2 = datetime.datetime(2000, 1, 1, 23, 0, 3, tzinfo=datetime.timezone.utc)
|
||||
assert buffer[0].datetime == date0
|
||||
assert buffer[1].datetime == date1
|
||||
assert buffer[2].datetime == date2
|
||||
assert buffer[0].value == 237126
|
||||
assert buffer[1].value == 2147583646
|
||||
assert buffer[2].value == 2317482647
|
||||
assert all([isinstance(item.value, int) for item in buffer])
|
||||
assert all([isinstance(item.unit, str) for item in buffer])
|
||||
assert all([(item.unit == 's') for item in buffer])
|
||||
self.item_names_tested.append(testitem_name)
|
||||
|
||||
# check if all items in telegram V4 specification are covered
|
||||
V4_name_list = [object["value_name"] for object in
|
||||
telegram_specifications.V4['objects']]
|
||||
V4_name_set = set(V4_name_list)
|
||||
item_names_tested_set = set(self.item_names_tested)
|
||||
|
||||
assert item_names_tested_set == V4_name_set
|
||||
|
||||
def test_iter(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5)
|
||||
|
||||
for obis_name, dsmr_object in telegram:
|
||||
break
|
||||
|
||||
# Verify that the iterator works for at least one value
|
||||
self.assertEqual(obis_name, "P1_MESSAGE_HEADER")
|
||||
self.assertEqual(dsmr_object.value, '50')
|
||||
|
||||
def test_mbus_devices(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5_TWO_MBUS)
|
||||
mbus_devices = telegram.MBUS_DEVICES
|
||||
|
||||
self.assertEqual(len(mbus_devices), 2)
|
||||
|
||||
mbus_device_1 = mbus_devices[0]
|
||||
self.assertEqual(mbus_device_1.MBUS_DEVICE_TYPE.value, 3)
|
||||
self.assertEqual(mbus_device_1.MBUS_EQUIPMENT_IDENTIFIER.value, None)
|
||||
self.assertEqual(mbus_device_1.MBUS_METER_READING.value, Decimal('0'))
|
||||
|
||||
mbus_device_2 = mbus_devices[1]
|
||||
self.assertEqual(mbus_device_2.MBUS_DEVICE_TYPE.value, 3)
|
||||
self.assertEqual(mbus_device_2.MBUS_EQUIPMENT_IDENTIFIER.value, '4730303339303031393336393930363139')
|
||||
self.assertEqual(mbus_device_2.MBUS_METER_READING.value, Decimal('246.138'))
|
||||
|
||||
def test_get_mbus_device_by_channel(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5_TWO_MBUS)
|
||||
|
||||
mbus_device_1 = telegram.get_mbus_device_by_channel(1)
|
||||
self.assertEqual(mbus_device_1.MBUS_DEVICE_TYPE.value, 3)
|
||||
self.assertEqual(mbus_device_1.MBUS_EQUIPMENT_IDENTIFIER.value, None)
|
||||
self.assertEqual(mbus_device_1.MBUS_METER_READING.value, Decimal('0'))
|
||||
|
||||
mbus_device_2 = telegram.get_mbus_device_by_channel(2)
|
||||
self.assertEqual(mbus_device_2.MBUS_DEVICE_TYPE.value, 3)
|
||||
self.assertEqual(mbus_device_2.MBUS_EQUIPMENT_IDENTIFIER.value, '4730303339303031393336393930363139')
|
||||
self.assertEqual(mbus_device_2.MBUS_METER_READING.value, Decimal('246.138'))
|
||||
|
||||
def test_without_mbus_devices(self):
|
||||
parser = TelegramParser(telegram_specifications.V5, apply_checksum_validation=False)
|
||||
telegram = parser.parse('')
|
||||
|
||||
self.assertFalse(hasattr(telegram, 'MBUS_DEVICES'))
|
||||
self.assertIsNone(telegram.get_mbus_device_by_channel(1))
|
||||
|
||||
def test_to_json(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5)
|
||||
json_data = json.loads(telegram.to_json())
|
||||
|
||||
self.maxDiff = None
|
||||
|
||||
self.assertEqual(
|
||||
json_data,
|
||||
{'CURRENT_ELECTRICITY_DELIVERY': {'unit': 'kW', 'value': 0.0},
|
||||
'CURRENT_ELECTRICITY_USAGE': {'unit': 'kW', 'value': 0.244},
|
||||
'ELECTRICITY_ACTIVE_TARIFF': {'unit': None, 'value': '0002'},
|
||||
'ELECTRICITY_DELIVERED_TARIFF_1': {'unit': 'kWh', 'value': 2.444},
|
||||
'ELECTRICITY_DELIVERED_TARIFF_2': {'unit': 'kWh', 'value': 0.0},
|
||||
'ELECTRICITY_USED_TARIFF_1': {'unit': 'kWh', 'value': 4.426},
|
||||
'ELECTRICITY_USED_TARIFF_2': {'unit': 'kWh', 'value': 2.399},
|
||||
'EQUIPMENT_IDENTIFIER': {'unit': None,
|
||||
'value': '4B384547303034303436333935353037'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE': {'unit': 'kW', 'value': 0.0},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE': {'unit': 'kW', 'value': 0.07},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE': {'unit': 'kW', 'value': 0.0},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE': {'unit': 'kW', 'value': 0.032},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE': {'unit': 'kW', 'value': 0.0},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE': {'unit': 'kW', 'value': 0.142},
|
||||
'INSTANTANEOUS_CURRENT_L1': {'unit': 'A', 'value': 0.48},
|
||||
'INSTANTANEOUS_CURRENT_L2': {'unit': 'A', 'value': 0.44},
|
||||
'INSTANTANEOUS_CURRENT_L3': {'unit': 'A', 'value': 0.86},
|
||||
'INSTANTANEOUS_VOLTAGE_L1': {'unit': 'V', 'value': 230.0},
|
||||
'INSTANTANEOUS_VOLTAGE_L2': {'unit': 'V', 'value': 230.0},
|
||||
'INSTANTANEOUS_VOLTAGE_L3': {'unit': 'V', 'value': 229.0},
|
||||
'LONG_POWER_FAILURE_COUNT': {'unit': None, 'value': 0},
|
||||
'MBUS_DEVICES': [{'CHANNEL_ID': 1,
|
||||
'MBUS_DEVICE_TYPE': {'unit': None, 'value': 3},
|
||||
'MBUS_EQUIPMENT_IDENTIFIER': {'unit': None,
|
||||
'value': '3232323241424344313233343536373839'},
|
||||
'MBUS_METER_READING': {'datetime': '2017-01-02T15:10:05+00:00',
|
||||
'unit': 'm3',
|
||||
'value': 0.107}},
|
||||
{'CHANNEL_ID': 2,
|
||||
'MBUS_DEVICE_TYPE': {'unit': None, 'value': 3},
|
||||
'MBUS_EQUIPMENT_IDENTIFIER': {'unit': None,
|
||||
'value': None}}],
|
||||
'P1_MESSAGE_HEADER': {'unit': None, 'value': '50'},
|
||||
'P1_MESSAGE_TIMESTAMP': {'unit': None, 'value': '2017-01-02T18:20:02+00:00'},
|
||||
'POWER_EVENT_FAILURE_LOG': {'buffer': [],
|
||||
'buffer_length': 0,
|
||||
'buffer_type': '0-0:96.7.19'},
|
||||
'SHORT_POWER_FAILURE_COUNT': {'unit': None, 'value': 13},
|
||||
'TEXT_MESSAGE': {'unit': None, 'value': None},
|
||||
'VOLTAGE_SAG_L1_COUNT': {'unit': None, 'value': 0},
|
||||
'VOLTAGE_SAG_L2_COUNT': {'unit': None, 'value': 0},
|
||||
'VOLTAGE_SAG_L3_COUNT': {'unit': None, 'value': 0},
|
||||
'VOLTAGE_SWELL_L1_COUNT': {'unit': None, 'value': 0},
|
||||
'VOLTAGE_SWELL_L2_COUNT': {'unit': None, 'value': 0},
|
||||
'VOLTAGE_SWELL_L3_COUNT': {'unit': None, 'value': 0}}
|
||||
)
|
||||
|
||||
def test_to_str(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5)
|
||||
|
||||
self.maxDiff = None
|
||||
|
||||
self.assertEqual(
|
||||
str(telegram),
|
||||
(
|
||||
'P1_MESSAGE_HEADER: 50 [None]\n'
|
||||
'P1_MESSAGE_TIMESTAMP: 2017-01-02T18:20:02+00:00 [None]\n'
|
||||
'EQUIPMENT_IDENTIFIER: 4B384547303034303436333935353037 [None]\n'
|
||||
'ELECTRICITY_USED_TARIFF_1: 4.426 [kWh]\n'
|
||||
'ELECTRICITY_USED_TARIFF_2: 2.399 [kWh]\n'
|
||||
'ELECTRICITY_DELIVERED_TARIFF_1: 2.444 [kWh]\n'
|
||||
'ELECTRICITY_DELIVERED_TARIFF_2: 0.000 [kWh]\n'
|
||||
'ELECTRICITY_ACTIVE_TARIFF: 0002 [None]\n'
|
||||
'CURRENT_ELECTRICITY_USAGE: 0.244 [kW]\n'
|
||||
'CURRENT_ELECTRICITY_DELIVERY: 0.000 [kW]\n'
|
||||
'LONG_POWER_FAILURE_COUNT: 0 [None]\n'
|
||||
'SHORT_POWER_FAILURE_COUNT: 13 [None]\n'
|
||||
'POWER_EVENT_FAILURE_LOG: buffer length: 0\n'
|
||||
' buffer type: 0-0:96.7.19\n'
|
||||
'VOLTAGE_SAG_L1_COUNT: 0 [None]\n'
|
||||
'VOLTAGE_SAG_L2_COUNT: 0 [None]\n'
|
||||
'VOLTAGE_SAG_L3_COUNT: 0 [None]\n'
|
||||
'VOLTAGE_SWELL_L1_COUNT: 0 [None]\n'
|
||||
'VOLTAGE_SWELL_L2_COUNT: 0 [None]\n'
|
||||
'VOLTAGE_SWELL_L3_COUNT: 0 [None]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L1: 230.0 [V]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L2: 230.0 [V]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L3: 229.0 [V]\n'
|
||||
'INSTANTANEOUS_CURRENT_L1: 0.48 [A]\n'
|
||||
'INSTANTANEOUS_CURRENT_L2: 0.44 [A]\n'
|
||||
'INSTANTANEOUS_CURRENT_L3: 0.86 [A]\n'
|
||||
'TEXT_MESSAGE: None [None]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: 0.070 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE: 0.032 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE: 0.142 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: 0.000 [kW]\n'
|
||||
'MBUS DEVICE (channel 1)\n'
|
||||
' MBUS_DEVICE_TYPE: 3 [None]\n'
|
||||
' MBUS_EQUIPMENT_IDENTIFIER: 3232323241424344313233343536373839 [None]\n'
|
||||
' MBUS_METER_READING: 0.107 [m3] at 2017-01-02T15:10:05+00:00\n'
|
||||
'MBUS DEVICE (channel 2)\n'
|
||||
' MBUS_DEVICE_TYPE: 3 [None]\n'
|
||||
' MBUS_EQUIPMENT_IDENTIFIER: None [None]\n'
|
||||
)
|
||||
)
|
||||
|
||||
def test_getitem(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(TELEGRAM_V5)
|
||||
|
||||
self.assertEqual(telegram[obis_references.P1_MESSAGE_HEADER].value, '50')
|
||||
@@ -0,0 +1,21 @@
|
||||
import unittest
|
||||
import tempfile
|
||||
|
||||
from dsmr_parser.clients.filereader import FileReader
|
||||
from dsmr_parser.telegram_specifications import V5
|
||||
from test.example_telegrams import TELEGRAM_V5
|
||||
|
||||
|
||||
class FileReaderTest(unittest.TestCase):
|
||||
def test_read_as_object(self):
|
||||
with tempfile.NamedTemporaryFile() as file:
|
||||
with open(file.name, "w") as f:
|
||||
f.write(TELEGRAM_V5)
|
||||
|
||||
telegrams = []
|
||||
reader = FileReader(file=file.name, telegram_specification=V5)
|
||||
# Call
|
||||
for telegram in reader.read_as_object():
|
||||
telegrams.append(telegram)
|
||||
|
||||
self.assertEqual(len(telegrams), 1)
|
||||
@@ -0,0 +1,413 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import unittest
|
||||
|
||||
import pytz
|
||||
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.exceptions import InvalidChecksumError, ParseError
|
||||
from dsmr_parser.objects import CosemObject, MBusObject, MBusObjectPeak
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from test.example_telegrams import TELEGRAM_FLUVIUS_V171, TELEGRAM_FLUVIUS_V171_ALT
|
||||
|
||||
|
||||
class TelegramParserFluviusTest(unittest.TestCase):
|
||||
""" Test parsing of a DSMR Fluvius telegram. """
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.BELGIUM_FLUVIUS)
|
||||
try:
|
||||
result = parser.parse(TELEGRAM_FLUVIUS_V171, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# BELGIUM_VERSION_INFORMATION (0-0:96.1.4)
|
||||
assert isinstance(result.BELGIUM_VERSION_INFORMATION, CosemObject)
|
||||
assert result.BELGIUM_VERSION_INFORMATION.unit is None
|
||||
assert isinstance(result.BELGIUM_VERSION_INFORMATION.value, str)
|
||||
assert result.BELGIUM_VERSION_INFORMATION.value == '50217'
|
||||
|
||||
# EQUIPMENT_IDENTIFIER (0-0:96.1.1)
|
||||
assert isinstance(result.BELGIUM_EQUIPMENT_IDENTIFIER, CosemObject)
|
||||
assert result.BELGIUM_EQUIPMENT_IDENTIFIER.unit is None
|
||||
assert isinstance(result.BELGIUM_EQUIPMENT_IDENTIFIER.value, str)
|
||||
assert result.BELGIUM_EQUIPMENT_IDENTIFIER.value == '3153414733313031303231363035'
|
||||
|
||||
# P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
|
||||
assert isinstance(result.P1_MESSAGE_TIMESTAMP, CosemObject)
|
||||
assert result.P1_MESSAGE_TIMESTAMP.unit is None
|
||||
assert isinstance(result.P1_MESSAGE_TIMESTAMP.value, datetime.datetime)
|
||||
assert result.P1_MESSAGE_TIMESTAMP.value == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 5, 12, 13, 54, 9))
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(result.ELECTRICITY_USED_TARIFF_1, CosemObject)
|
||||
assert result.ELECTRICITY_USED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(result.ELECTRICITY_USED_TARIFF_1.value, Decimal)
|
||||
assert result.ELECTRICITY_USED_TARIFF_1.value == Decimal('0.034')
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
|
||||
assert isinstance(result.ELECTRICITY_USED_TARIFF_2, CosemObject)
|
||||
assert result.ELECTRICITY_USED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(result.ELECTRICITY_USED_TARIFF_2.value, Decimal)
|
||||
assert result.ELECTRICITY_USED_TARIFF_2.value == Decimal('15.758')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
|
||||
assert isinstance(result.ELECTRICITY_DELIVERED_TARIFF_1, CosemObject)
|
||||
assert result.ELECTRICITY_DELIVERED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(result.ELECTRICITY_DELIVERED_TARIFF_1.value, Decimal)
|
||||
assert result.ELECTRICITY_DELIVERED_TARIFF_1.value == Decimal('0.000')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
|
||||
assert isinstance(result.ELECTRICITY_DELIVERED_TARIFF_2, CosemObject)
|
||||
assert result.ELECTRICITY_DELIVERED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(result.ELECTRICITY_DELIVERED_TARIFF_2.value, Decimal)
|
||||
assert result.ELECTRICITY_DELIVERED_TARIFF_2.value == Decimal('0.011')
|
||||
|
||||
# ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
|
||||
assert isinstance(result.ELECTRICITY_ACTIVE_TARIFF, CosemObject)
|
||||
assert result.ELECTRICITY_ACTIVE_TARIFF.unit is None
|
||||
assert isinstance(result.ELECTRICITY_ACTIVE_TARIFF.value, str)
|
||||
assert result.ELECTRICITY_ACTIVE_TARIFF.value == '0001'
|
||||
|
||||
# BELGIUM_CURRENT_AVERAGE_DEMAND (1-0:1.4.0)
|
||||
assert isinstance(result.BELGIUM_CURRENT_AVERAGE_DEMAND, CosemObject)
|
||||
assert result.BELGIUM_CURRENT_AVERAGE_DEMAND.unit == 'kW'
|
||||
assert isinstance(result.BELGIUM_CURRENT_AVERAGE_DEMAND.value, Decimal)
|
||||
assert result.BELGIUM_CURRENT_AVERAGE_DEMAND.value == Decimal('2.351')
|
||||
|
||||
# BELGIUM_MAXIMUM_DEMAND_MONTH (1-0:1.6.0)
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_MONTH, MBusObject)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_MONTH.unit == 'kW'
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_MONTH.value, Decimal)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_MONTH.value == Decimal('2.589')
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_MONTH.datetime, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_MONTH.datetime == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 5, 9, 13, 45, 58))
|
||||
|
||||
# BELGIUM_MAXIMUM_DEMAND_13_MONTHS (0-0:98.1.0) Value 0
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0], MBusObjectPeak)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].unit == 'kW'
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].value, Decimal)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].value == Decimal('3.695')
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].datetime, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].datetime == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 5, 1, 0, 0, 0))
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].occurred, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[0].occurred == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 4, 23, 19, 25, 38))
|
||||
# BELGIUM_MAXIMUM_DEMAND_13_MONTHS (0-0:98.1.0) Value 1
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1], MBusObjectPeak)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].unit == 'kW'
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].value, Decimal)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].value == Decimal('5.980')
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].datetime, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].datetime == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 4, 1, 0, 0, 0))
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].occurred, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[1].occurred == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 3, 5, 12, 21, 39))
|
||||
# BELGIUM_MAXIMUM_DEMAND_13_MONTHS (0-0:98.1.0) Value 2
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2], MBusObjectPeak)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].unit == 'kW'
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].value, Decimal)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].value == Decimal('4.318')
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].datetime, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].datetime == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 3, 1, 0, 0, 0))
|
||||
assert isinstance(result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].occurred, datetime.datetime)
|
||||
assert result.BELGIUM_MAXIMUM_DEMAND_13_MONTHS[2].occurred == \
|
||||
pytz.timezone("Europe/Brussels").localize(datetime.datetime(2020, 2, 10, 3, 54, 21))
|
||||
|
||||
# CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
|
||||
assert isinstance(result.CURRENT_ELECTRICITY_USAGE, CosemObject)
|
||||
assert result.CURRENT_ELECTRICITY_USAGE.unit == 'kW'
|
||||
assert isinstance(result.CURRENT_ELECTRICITY_USAGE.value, Decimal)
|
||||
assert result.CURRENT_ELECTRICITY_USAGE.value == Decimal('0.000')
|
||||
|
||||
# CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
|
||||
assert isinstance(result.CURRENT_ELECTRICITY_DELIVERY, CosemObject)
|
||||
assert result.CURRENT_ELECTRICITY_DELIVERY.unit == 'kW'
|
||||
assert isinstance(result.CURRENT_ELECTRICITY_DELIVERY.value, Decimal)
|
||||
assert result.CURRENT_ELECTRICITY_DELIVERY.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE, CosemObject)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(result.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.value, Decimal)
|
||||
assert result.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L1 (1-0:32.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L1, CosemObject)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L1.unit == 'V'
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L1.value, Decimal)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L1.value == Decimal('234.7')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L2 (1-0:52.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L2, CosemObject)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L2.unit == 'V'
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L2.value, Decimal)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L2.value == Decimal('234.7')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L3 (1-0:72.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L3, CosemObject)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L3.unit == 'V'
|
||||
assert isinstance(result.INSTANTANEOUS_VOLTAGE_L3.value, Decimal)
|
||||
assert result.INSTANTANEOUS_VOLTAGE_L3.value == Decimal('234.7')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L1, CosemObject)
|
||||
assert result.INSTANTANEOUS_CURRENT_L1.unit == 'A'
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L1.value, Decimal)
|
||||
assert result.INSTANTANEOUS_CURRENT_L1.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L2, CosemObject)
|
||||
assert result.INSTANTANEOUS_CURRENT_L2.unit == 'A'
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L2.value, Decimal)
|
||||
assert result.INSTANTANEOUS_CURRENT_L2.value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L3, CosemObject)
|
||||
assert result.INSTANTANEOUS_CURRENT_L3.unit == 'A'
|
||||
assert isinstance(result.INSTANTANEOUS_CURRENT_L3.value, Decimal)
|
||||
assert result.INSTANTANEOUS_CURRENT_L3.value == Decimal('0.000')
|
||||
|
||||
# ACTUAL_SWITCH_POSITION (0-0:96.3.10)
|
||||
assert isinstance(result.ACTUAL_SWITCH_POSITION, CosemObject)
|
||||
assert result.ACTUAL_SWITCH_POSITION.unit is None
|
||||
assert isinstance(result.ACTUAL_SWITCH_POSITION.value, int)
|
||||
assert result.ACTUAL_SWITCH_POSITION.value == 1
|
||||
|
||||
# ACTUAL_TRESHOLD_ELECTRICITY (0-0:17.0.0)
|
||||
assert isinstance(result.ACTUAL_TRESHOLD_ELECTRICITY, CosemObject)
|
||||
assert result.ACTUAL_TRESHOLD_ELECTRICITY.unit == 'kW'
|
||||
assert isinstance(result.ACTUAL_TRESHOLD_ELECTRICITY.value, Decimal)
|
||||
assert result.ACTUAL_TRESHOLD_ELECTRICITY.value == Decimal('999.9')
|
||||
|
||||
# FUSE_THRESHOLD_L1 (1-0:31.4.0)
|
||||
assert isinstance(result.FUSE_THRESHOLD_L1, CosemObject)
|
||||
assert result.FUSE_THRESHOLD_L1.unit == 'A'
|
||||
assert isinstance(result.FUSE_THRESHOLD_L1.value, Decimal)
|
||||
assert result.FUSE_THRESHOLD_L1.value == Decimal('999')
|
||||
|
||||
# TEXT_MESSAGE (0-0:96.13.0)
|
||||
assert isinstance(result.TEXT_MESSAGE, CosemObject)
|
||||
assert result.TEXT_MESSAGE.unit is None
|
||||
assert result.TEXT_MESSAGE.value is None
|
||||
|
||||
# MBUS DEVICE 1
|
||||
mbus1 = result.get_mbus_device_by_channel(1)
|
||||
|
||||
# MBUS_DEVICE_TYPE (0-1:24.1.0)
|
||||
assert isinstance(mbus1.MBUS_DEVICE_TYPE, CosemObject)
|
||||
assert mbus1.MBUS_DEVICE_TYPE.unit is None
|
||||
assert isinstance(mbus1.MBUS_DEVICE_TYPE.value, int)
|
||||
assert mbus1.MBUS_DEVICE_TYPE.value == 3
|
||||
|
||||
# MBUS_EQUIPMENT_IDENTIFIER (0-1:96.1.1)
|
||||
assert isinstance(mbus1.MBUS_EQUIPMENT_IDENTIFIER, CosemObject)
|
||||
assert mbus1.MBUS_EQUIPMENT_IDENTIFIER.unit is None
|
||||
assert isinstance(mbus1.MBUS_EQUIPMENT_IDENTIFIER.value, str)
|
||||
assert mbus1.MBUS_EQUIPMENT_IDENTIFIER.value == '37464C4F32313139303333373333'
|
||||
|
||||
# MBUS_VALVE_POSITION (0-1:24.4.0)
|
||||
assert isinstance(result.MBUS_VALVE_POSITION, CosemObject)
|
||||
assert result.MBUS_VALVE_POSITION.unit is None
|
||||
assert isinstance(result.MBUS_VALVE_POSITION.value, int)
|
||||
assert result.MBUS_VALVE_POSITION.value == 1
|
||||
|
||||
# MBUS_METER_READING (0-1:24.2.3)
|
||||
assert isinstance(mbus1.MBUS_METER_READING, MBusObject)
|
||||
assert mbus1.MBUS_METER_READING.unit == 'm3'
|
||||
assert isinstance(mbus1.MBUS_METER_READING.value, Decimal)
|
||||
assert mbus1.MBUS_METER_READING.value == Decimal('112.384')
|
||||
|
||||
# MBUS DEVICE 2
|
||||
mbus2 = result.get_mbus_device_by_channel(2)
|
||||
|
||||
# MBUS_DEVICE_TYPE (0-2:24.1.0)
|
||||
assert isinstance(mbus2.MBUS_DEVICE_TYPE, CosemObject)
|
||||
assert mbus2.MBUS_DEVICE_TYPE.unit is None
|
||||
assert isinstance(mbus2.MBUS_DEVICE_TYPE.value, int)
|
||||
assert mbus2.MBUS_DEVICE_TYPE.value == 7
|
||||
|
||||
# MBUS_EQUIPMENT_IDENTIFIER (0-2:96.1.1)
|
||||
assert isinstance(mbus2.MBUS_EQUIPMENT_IDENTIFIER, CosemObject)
|
||||
assert mbus2.MBUS_EQUIPMENT_IDENTIFIER.unit is None
|
||||
assert isinstance(mbus2.MBUS_EQUIPMENT_IDENTIFIER.value, str)
|
||||
assert mbus2.MBUS_EQUIPMENT_IDENTIFIER.value == '3853414731323334353637383930'
|
||||
|
||||
# MBUS_METER_READING (0-1:24.2.1)
|
||||
assert isinstance(mbus2.MBUS_METER_READING, MBusObject)
|
||||
assert mbus2.MBUS_METER_READING.unit == 'm3'
|
||||
assert isinstance(mbus2.MBUS_METER_READING.value, Decimal)
|
||||
assert mbus2.MBUS_METER_READING.value == Decimal('872.234')
|
||||
|
||||
def test_checksum_valid(self):
|
||||
# No exception is raised.
|
||||
TelegramParser.validate_checksum(TELEGRAM_FLUVIUS_V171)
|
||||
|
||||
def test_checksum_invalid(self):
|
||||
# Remove the electricty used data value. This causes the checksum to
|
||||
# not match anymore.
|
||||
corrupted_telegram = TELEGRAM_FLUVIUS_V171.replace(
|
||||
'1-0:1.8.1(000000.034*kWh)\r\n',
|
||||
''
|
||||
)
|
||||
|
||||
with self.assertRaises(InvalidChecksumError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
|
||||
def test_checksum_missing(self):
|
||||
# Remove the checksum value causing a ParseError.
|
||||
corrupted_telegram = TELEGRAM_FLUVIUS_V171.replace('!3AD7\r\n', '')
|
||||
with self.assertRaises(ParseError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
|
||||
def test_to_json(self):
|
||||
parser = TelegramParser(telegram_specifications.BELGIUM_FLUVIUS)
|
||||
telegram = parser.parse(TELEGRAM_FLUVIUS_V171_ALT)
|
||||
json_data = json.loads(telegram.to_json())
|
||||
|
||||
self.maxDiff = None
|
||||
|
||||
self.assertEqual(
|
||||
json_data,
|
||||
{'BELGIUM_VERSION_INFORMATION': {'value': '50217', 'unit': None},
|
||||
'BELGIUM_EQUIPMENT_IDENTIFIER': {'value': '3153414733313030373231333236', 'unit': None},
|
||||
'P1_MESSAGE_TIMESTAMP': {'value': '2023-11-02T11:15:48+00:00', 'unit': None},
|
||||
'ELECTRICITY_USED_TARIFF_1': {'value': 301.548, 'unit': 'kWh'},
|
||||
'ELECTRICITY_USED_TARIFF_2': {'value': 270.014, 'unit': 'kWh'},
|
||||
'ELECTRICITY_DELIVERED_TARIFF_1': {'value': 0.005, 'unit': 'kWh'},
|
||||
'ELECTRICITY_DELIVERED_TARIFF_2': {'value': 0.0, 'unit': 'kWh'},
|
||||
'ELECTRICITY_ACTIVE_TARIFF': {'value': '0001', 'unit': None},
|
||||
'BELGIUM_CURRENT_AVERAGE_DEMAND': {'value': 0.052, 'unit': 'kW'},
|
||||
'BELGIUM_MAXIMUM_DEMAND_MONTH': {'datetime': '2023-11-02T10:45:00+00:00',
|
||||
'value': 3.064, 'unit': 'kW'},
|
||||
'BELGIUM_MAXIMUM_DEMAND_13_MONTHS': [{'datetime': '2023-07-31T22:00:00+00:00',
|
||||
'occurred': None, 'value': 0.0, 'unit': 'kW'},
|
||||
{'datetime': '2023-08-31T22:00:00+00:00',
|
||||
'occurred': '2023-08-31T16:15:00+00:00',
|
||||
'value': 1.862, 'unit': 'kW'},
|
||||
{'datetime': '2023-09-30T22:00:00+00:00',
|
||||
'occurred': '2023-09-10T16:30:00+00:00',
|
||||
'value': 4.229, 'unit': 'kW'},
|
||||
{'datetime': '2023-10-31T23:00:00+00:00',
|
||||
'occurred': '2023-10-16T11:00:00+00:00',
|
||||
'value': 4.927, 'unit': 'kW'}],
|
||||
'CURRENT_ELECTRICITY_USAGE': {'value': 0.338, 'unit': 'kW'},
|
||||
'CURRENT_ELECTRICITY_DELIVERY': {'value': 0.0, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE': {'value': 0.047, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE': {'value': 0.179, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE': {'value': 0.111, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE': {'value': 0.0, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE': {'value': 0.0, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE': {'value': 0.0, 'unit': 'kW'},
|
||||
'INSTANTANEOUS_VOLTAGE_L1': {'value': 232.9, 'unit': 'V'},
|
||||
'INSTANTANEOUS_VOLTAGE_L2': {'value': 228.1, 'unit': 'V'},
|
||||
'INSTANTANEOUS_VOLTAGE_L3': {'value': 228.1, 'unit': 'V'},
|
||||
'INSTANTANEOUS_CURRENT_L1': {'value': 0.27, 'unit': 'A'},
|
||||
'INSTANTANEOUS_CURRENT_L2': {'value': 0.88, 'unit': 'A'},
|
||||
'INSTANTANEOUS_CURRENT_L3': {'value': 0.52, 'unit': 'A'},
|
||||
'ACTUAL_SWITCH_POSITION': {'value': 1, 'unit': None},
|
||||
'ACTUAL_TRESHOLD_ELECTRICITY': {'value': 999.9, 'unit': 'kW'},
|
||||
'FUSE_THRESHOLD_L1': {'value': 999.0, 'unit': 'A'},
|
||||
'TEXT_MESSAGE': {'value': None, 'unit': None},
|
||||
'MBUS_DEVICES': [{'MBUS_DEVICE_TYPE': {'value': 3, 'unit': None},
|
||||
'MBUS_EQUIPMENT_IDENTIFIER': {'value': '37464C4F32313233303838303237',
|
||||
'unit': None},
|
||||
'MBUS_VALVE_POSITION': {'value': 1, 'unit': None},
|
||||
'MBUS_METER_READING': {'datetime': '2023-11-02T11:10:02+00:00',
|
||||
'value': 92.287, 'unit': 'm3'},
|
||||
'CHANNEL_ID': 1},
|
||||
{'MBUS_DEVICE_TYPE': {'value': 7, 'unit': None},
|
||||
'MBUS_EQUIPMENT_IDENTIFIER': {'value': '3853455430303030393631313733',
|
||||
'unit': None},
|
||||
'MBUS_METER_READING': {'datetime': '2023-11-02T11:15:32+00:00',
|
||||
'value': 8.579, 'unit': 'm3'},
|
||||
'CHANNEL_ID': 2}]}
|
||||
)
|
||||
|
||||
def test_to_str(self):
|
||||
parser = TelegramParser(telegram_specifications.BELGIUM_FLUVIUS)
|
||||
telegram = parser.parse(TELEGRAM_FLUVIUS_V171_ALT)
|
||||
|
||||
self.assertEqual(
|
||||
str(telegram),
|
||||
(
|
||||
'BELGIUM_VERSION_INFORMATION: 50217 [None]\n'
|
||||
'BELGIUM_EQUIPMENT_IDENTIFIER: 3153414733313030373231333236 [None]\n'
|
||||
'P1_MESSAGE_TIMESTAMP: 2023-11-02T11:15:48+00:00 [None]\n'
|
||||
'ELECTRICITY_USED_TARIFF_1: 301.548 [kWh]\n'
|
||||
'ELECTRICITY_USED_TARIFF_2: 270.014 [kWh]\n'
|
||||
'ELECTRICITY_DELIVERED_TARIFF_1: 0.005 [kWh]\n'
|
||||
'ELECTRICITY_DELIVERED_TARIFF_2: 0.000 [kWh]\n'
|
||||
'ELECTRICITY_ACTIVE_TARIFF: 0001 [None]\n'
|
||||
'BELGIUM_CURRENT_AVERAGE_DEMAND: 0.052 [kW]\n'
|
||||
'BELGIUM_MAXIMUM_DEMAND_MONTH: 3.064 [kW] at 2023-11-02T10:45:00+00:00\n'
|
||||
'0.0 [kW] at 2023-07-31T22:00:00+00:00 occurred None'
|
||||
'1.862 [kW] at 2023-08-31T22:00:00+00:00 occurred 2023-08-31T16:15:00+00:00'
|
||||
'4.229 [kW] at 2023-09-30T22:00:00+00:00 occurred 2023-09-10T16:30:00+00:00'
|
||||
'4.927 [kW] at 2023-10-31T23:00:00+00:00 occurred 2023-10-16T11:00:00+00:00'
|
||||
'CURRENT_ELECTRICITY_USAGE: 0.338 [kW]\n'
|
||||
'CURRENT_ELECTRICITY_DELIVERY: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: 0.047 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE: 0.179 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE: 0.111 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: 0.000 [kW]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L1: 232.9 [V]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L2: 228.1 [V]\n'
|
||||
'INSTANTANEOUS_VOLTAGE_L3: 228.1 [V]\n'
|
||||
'INSTANTANEOUS_CURRENT_L1: 0.27 [A]\n'
|
||||
'INSTANTANEOUS_CURRENT_L2: 0.88 [A]\n'
|
||||
'INSTANTANEOUS_CURRENT_L3: 0.52 [A]\n'
|
||||
'ACTUAL_SWITCH_POSITION: 1 [None]\n'
|
||||
'ACTUAL_TRESHOLD_ELECTRICITY: 999.9 [kW]\n'
|
||||
'FUSE_THRESHOLD_L1: 999 [A]\n'
|
||||
'TEXT_MESSAGE: None [None]\n'
|
||||
'MBUS DEVICE (channel 1)\n'
|
||||
' MBUS_DEVICE_TYPE: 3 [None]\n'
|
||||
' MBUS_EQUIPMENT_IDENTIFIER: 37464C4F32313233303838303237 [None]\n'
|
||||
' MBUS_VALVE_POSITION: 1 [None]\n'
|
||||
' MBUS_METER_READING: 92.287 [m3] at 2023-11-02T11:10:02+00:00\n'
|
||||
'MBUS DEVICE (channel 2)\n'
|
||||
' MBUS_DEVICE_TYPE: 7 [None]\n'
|
||||
' MBUS_EQUIPMENT_IDENTIFIER: 3853455430303030393631313733 [None]\n'
|
||||
' MBUS_METER_READING: 8.579 [m3] at 2023-11-02T11:15:32+00:00\n'
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,177 @@
|
||||
import unittest
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from dsmr_parser.exceptions import InvalidChecksumError, ParseError
|
||||
from dsmr_parser.objects import CosemObject
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser import obis_references as obis
|
||||
from test.example_telegrams import TELEGRAM_ISKRA_IE
|
||||
|
||||
|
||||
class TelegramParserIskraIETest(unittest.TestCase):
|
||||
""" Test parsing of a Iskra IE5 telegram. """
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.ISKRA_IE)
|
||||
try:
|
||||
result = parser.parse(TELEGRAM_ISKRA_IE, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# EQUIPMENT_IDENTIFIER_GAS (0-0:96.1.0)
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER_GAS].value == '09610'
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal('10.181')
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal('10.182')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1], CosemObject)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal('10.281')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2], CosemObject)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal('10.282')
|
||||
|
||||
# ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
|
||||
assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
|
||||
assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
|
||||
assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
|
||||
assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0001'
|
||||
|
||||
# CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
|
||||
assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value, Decimal)
|
||||
assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('0.170')
|
||||
|
||||
# CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY], CosemObject)
|
||||
assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value, Decimal)
|
||||
assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0.270')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value == Decimal('0.217')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value == Decimal('0.417')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value == Decimal('0.617')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value == Decimal('0.227')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value == Decimal('0.427')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value == Decimal('0.627')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L1 (1-0:32.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L1], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L1].unit == 'V'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L1].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L1].value == Decimal('242.5')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L2 (1-0:52.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L2], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L2].unit == 'V'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L2].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L2].value == Decimal('241.7')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L3 (1-0:72.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L3], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L3].unit == 'V'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L3].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_VOLTAGE_L3].value == Decimal('243.3')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L1].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L1].value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L2].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L2].value == Decimal('0.000')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L3].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L3].value == Decimal('0.000')
|
||||
|
||||
# ACTUAL_SWITCH_POSITION (0-0:96.3.10)
|
||||
assert isinstance(result[obis.ACTUAL_SWITCH_POSITION], CosemObject)
|
||||
assert result[obis.ACTUAL_SWITCH_POSITION].unit is None
|
||||
assert isinstance(result[obis.ACTUAL_SWITCH_POSITION].value, str)
|
||||
assert result[obis.ACTUAL_SWITCH_POSITION].value == '1'
|
||||
|
||||
# TEXT_MESSAGE (0-0:96.13.0)
|
||||
assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
|
||||
assert result[obis.TEXT_MESSAGE].unit is None
|
||||
assert result[obis.TEXT_MESSAGE].value is None
|
||||
|
||||
# EQUIPMENT_IDENTIFIER (0-0:96.1.1)
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER].value is None
|
||||
|
||||
def test_checksum_valid(self):
|
||||
# No exception is raised.
|
||||
TelegramParser.validate_checksum(TELEGRAM_ISKRA_IE)
|
||||
|
||||
def test_checksum_invalid(self):
|
||||
# Remove the electricty used data value. This causes the checksum to not match anymore.
|
||||
corrupted_telegram = TELEGRAM_ISKRA_IE.replace(
|
||||
'1-0:1.8.1(000010.181*kWh)\r\n',
|
||||
''
|
||||
)
|
||||
|
||||
with self.assertRaises(InvalidChecksumError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
|
||||
def test_checksum_missing(self):
|
||||
# Remove the checksum value causing a ParseError.
|
||||
corrupted_telegram = TELEGRAM_ISKRA_IE.replace('!AD3B\r\n', '')
|
||||
with self.assertRaises(ParseError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
@@ -0,0 +1,107 @@
|
||||
from binascii import unhexlify
|
||||
from copy import deepcopy
|
||||
|
||||
import unittest
|
||||
|
||||
from dlms_cosem.exceptions import DecryptionError
|
||||
from dlms_cosem.protocol.xdlms import GeneralGlobalCipher
|
||||
from dlms_cosem.security import SecurityControlField, encrypt
|
||||
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.exceptions import ParseError
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from test.example_telegrams import TELEGRAM_SAGEMCOM_T210_D_R
|
||||
|
||||
|
||||
class TelegramParserEncryptedTest(unittest.TestCase):
|
||||
""" Test parsing of a DSML encypted DSMR v5.x telegram. """
|
||||
DUMMY_ENCRYPTION_KEY = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
DUMMY_AUTHENTICATION_KEY = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
||||
|
||||
def __generate_encrypted(self, security_suite=0, authenticated=True, encrypted=True):
|
||||
security_control = SecurityControlField(
|
||||
security_suite=security_suite, authenticated=authenticated, encrypted=encrypted
|
||||
)
|
||||
encryption_key = unhexlify(self.DUMMY_ENCRYPTION_KEY)
|
||||
authentication_key = unhexlify(self.DUMMY_AUTHENTICATION_KEY)
|
||||
system_title = "SYSTEMID".encode("ascii")
|
||||
invocation_counter = int.from_bytes(bytes.fromhex("10000001"), "big")
|
||||
plain_data = TELEGRAM_SAGEMCOM_T210_D_R.encode("ascii")
|
||||
|
||||
encrypted = encrypt(
|
||||
security_control=security_control,
|
||||
key=encryption_key,
|
||||
auth_key=authentication_key,
|
||||
system_title=system_title,
|
||||
invocation_counter=invocation_counter,
|
||||
plain_text=plain_data,
|
||||
)
|
||||
|
||||
full_frame = bytearray(GeneralGlobalCipher.TAG.to_bytes(1, "big", signed=False))
|
||||
full_frame.extend(len(system_title).to_bytes(1, "big", signed=False))
|
||||
full_frame.extend(system_title)
|
||||
full_frame.extend([0x82]) # Length of the following length bytes
|
||||
# https://github.com/pwitab/dlms-cosem/blob/739f81a58e5f07663a512d4a128851333a0ed5e6/dlms_cosem/a_xdr.py#L33
|
||||
|
||||
security_control = security_control.to_bytes()
|
||||
invocation_counter = invocation_counter.to_bytes(4, "big", signed=False)
|
||||
full_frame.extend((len(encrypted)
|
||||
+ len(invocation_counter)
|
||||
+ len(security_control)).to_bytes(2, "big", signed=False))
|
||||
full_frame.extend(security_control)
|
||||
full_frame.extend(invocation_counter)
|
||||
full_frame.extend(encrypted)
|
||||
|
||||
return full_frame
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
result = parser.parse(self.__generate_encrypted().hex(),
|
||||
self.DUMMY_ENCRYPTION_KEY,
|
||||
self.DUMMY_AUTHENTICATION_KEY)
|
||||
self.assertEqual(len(result), 18)
|
||||
|
||||
def test_damaged_frame(self):
|
||||
# If the frame is damaged decrypting fails (crc is technically not needed)
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
|
||||
generated = self.__generate_encrypted()
|
||||
generated[150] = 0x00
|
||||
generated = generated.hex()
|
||||
|
||||
with self.assertRaises(DecryptionError):
|
||||
parser.parse(generated, self.DUMMY_ENCRYPTION_KEY, self.DUMMY_AUTHENTICATION_KEY)
|
||||
|
||||
def test_plain(self):
|
||||
# If a plain request is parsed with "general_global_cipher": True it fails
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
parser.parse(TELEGRAM_SAGEMCOM_T210_D_R, self.DUMMY_ENCRYPTION_KEY, self.DUMMY_AUTHENTICATION_KEY)
|
||||
|
||||
def test_general_global_cipher_not_specified(self):
|
||||
# If a GGC frame is detected but general_global_cipher is not set it fails
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
parser = deepcopy(parser) # We do not want to change the module value
|
||||
parser.telegram_specification['general_global_cipher'] = False
|
||||
|
||||
with self.assertRaises(ParseError):
|
||||
parser.parse(self.__generate_encrypted().hex(), self.DUMMY_ENCRYPTION_KEY, self.DUMMY_AUTHENTICATION_KEY)
|
||||
|
||||
def test_only_encrypted(self):
|
||||
# Not implemented by dlms_cosem
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
|
||||
only_auth = self.__generate_encrypted(0, authenticated=False, encrypted=True).hex()
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parser.parse(only_auth, self.DUMMY_ENCRYPTION_KEY)
|
||||
|
||||
def test_only_auth(self):
|
||||
# Not implemented by dlms_cosem
|
||||
parser = TelegramParser(telegram_specifications.SAGEMCOM_T210_D_R)
|
||||
|
||||
only_auth = self.__generate_encrypted(0, authenticated=True, encrypted=False).hex()
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
parser.parse(only_auth, authentication_key=self.DUMMY_AUTHENTICATION_KEY)
|
||||
@@ -23,7 +23,10 @@ class TelegramParserV2_2Test(unittest.TestCase):
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.V2_2)
|
||||
result = parser.parse(TELEGRAM_V2_2)
|
||||
try:
|
||||
result = parser.parse(TELEGRAM_V2_2, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
|
||||
|
||||
@@ -23,7 +23,10 @@ class TelegramParserV3Test(unittest.TestCase):
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.V3)
|
||||
result = parser.parse(TELEGRAM_V3)
|
||||
try:
|
||||
result = parser.parse(TELEGRAM_V3, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
|
||||
|
||||
+29
-2
@@ -26,7 +26,10 @@ class TelegramParserV4_2Test(unittest.TestCase):
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.V4)
|
||||
result = parser.parse(TELEGRAM_V4_2)
|
||||
try:
|
||||
result = parser.parse(TELEGRAM_V4_2, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# P1_MESSAGE_HEADER (1-3:0.2.8)
|
||||
assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject)
|
||||
@@ -89,6 +92,12 @@ class TelegramParserV4_2Test(unittest.TestCase):
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value, Decimal)
|
||||
assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')
|
||||
|
||||
# SHORT_POWER_FAILURE_COUNT (1-0:96.7.21)
|
||||
assert isinstance(result[obis.SHORT_POWER_FAILURE_COUNT], CosemObject)
|
||||
assert result[obis.SHORT_POWER_FAILURE_COUNT].unit is None
|
||||
assert isinstance(result[obis.SHORT_POWER_FAILURE_COUNT].value, int)
|
||||
assert result[obis.SHORT_POWER_FAILURE_COUNT].value == 15
|
||||
|
||||
# LONG_POWER_FAILURE_COUNT (96.7.9)
|
||||
assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT], CosemObject)
|
||||
assert result[obis.LONG_POWER_FAILURE_COUNT].unit is None
|
||||
@@ -141,8 +150,26 @@ class TelegramParserV4_2Test(unittest.TestCase):
|
||||
assert result[obis.TEXT_MESSAGE].unit is None
|
||||
assert result[obis.TEXT_MESSAGE].value is None
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L1].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L1].value == Decimal('0')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L2].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L2].value == Decimal('6')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L3].unit == 'A'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_CURRENT_L3].value == Decimal('2')
|
||||
|
||||
# DEVICE_TYPE (0-x:24.1.0)
|
||||
assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
|
||||
assert isinstance(result[obis.DEVICE_TYPE], CosemObject)
|
||||
assert result[obis.DEVICE_TYPE].unit is None
|
||||
assert isinstance(result[obis.DEVICE_TYPE].value, int)
|
||||
assert result[obis.DEVICE_TYPE].value == 3
|
||||
|
||||
+185
-116
@@ -5,7 +5,6 @@ import unittest
|
||||
|
||||
import pytz
|
||||
|
||||
from dsmr_parser import obis_references as obis
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.exceptions import InvalidChecksumError, ParseError
|
||||
from dsmr_parser.objects import CosemObject, MBusObject
|
||||
@@ -27,169 +26,219 @@ class TelegramParserV5Test(unittest.TestCase):
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
result = parser.parse(TELEGRAM_V5)
|
||||
|
||||
try:
|
||||
telegram = parser.parse(TELEGRAM_V5, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
print('test: ', type(telegram.P1_MESSAGE_HEADER), telegram.P1_MESSAGE_HEADER.__dict__)
|
||||
# P1_MESSAGE_HEADER (1-3:0.2.8)
|
||||
assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject)
|
||||
assert result[obis.P1_MESSAGE_HEADER].unit is None
|
||||
assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str)
|
||||
assert result[obis.P1_MESSAGE_HEADER].value == '50'
|
||||
assert isinstance(telegram.P1_MESSAGE_HEADER, CosemObject)
|
||||
assert telegram.P1_MESSAGE_HEADER.unit is None
|
||||
assert isinstance(telegram.P1_MESSAGE_HEADER.value, str)
|
||||
assert telegram.P1_MESSAGE_HEADER.value == '50'
|
||||
|
||||
# P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
|
||||
assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP], CosemObject)
|
||||
assert result[obis.P1_MESSAGE_TIMESTAMP].unit is None
|
||||
assert isinstance(result[obis.P1_MESSAGE_TIMESTAMP].value, datetime.datetime)
|
||||
assert result[obis.P1_MESSAGE_TIMESTAMP].value == \
|
||||
assert isinstance(telegram.P1_MESSAGE_TIMESTAMP, CosemObject)
|
||||
assert telegram.P1_MESSAGE_TIMESTAMP.unit is None
|
||||
assert isinstance(telegram.P1_MESSAGE_TIMESTAMP.value, datetime.datetime)
|
||||
assert telegram.P1_MESSAGE_TIMESTAMP.value == \
|
||||
datetime.datetime(2017, 1, 2, 18, 20, 2, tzinfo=pytz.UTC)
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1], CosemObject)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_1].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_1].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_1].value == Decimal('4.426')
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_1, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_1.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_1.value == Decimal('4.426')
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2], CosemObject)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_2].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_USED_TARIFF_2].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_USED_TARIFF_2].value == Decimal('2.399')
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_2, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_2.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_2.value == Decimal('2.399')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1], CosemObject)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_1].value == Decimal('2.444')
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_1, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_1.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_1.value == Decimal('2.444')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2], CosemObject)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].unit == 'kWh'
|
||||
assert isinstance(result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value, Decimal)
|
||||
assert result[obis.ELECTRICITY_DELIVERED_TARIFF_2].value == Decimal('0')
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_2, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_2.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_2.value == Decimal('0')
|
||||
|
||||
# ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
|
||||
assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF], CosemObject)
|
||||
assert result[obis.ELECTRICITY_ACTIVE_TARIFF].unit is None
|
||||
assert isinstance(result[obis.ELECTRICITY_ACTIVE_TARIFF].value, str)
|
||||
assert result[obis.ELECTRICITY_ACTIVE_TARIFF].value == '0002'
|
||||
assert isinstance(telegram.ELECTRICITY_ACTIVE_TARIFF, CosemObject)
|
||||
assert telegram.ELECTRICITY_ACTIVE_TARIFF.unit is None
|
||||
assert isinstance(telegram.ELECTRICITY_ACTIVE_TARIFF.value, str)
|
||||
assert telegram.ELECTRICITY_ACTIVE_TARIFF.value == '0002'
|
||||
|
||||
# EQUIPMENT_IDENTIFIER (0-0:96.1.1)
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER], CosemObject)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER].unit is None
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER].value, str)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER].value == '4B384547303034303436333935353037'
|
||||
assert isinstance(telegram.EQUIPMENT_IDENTIFIER, CosemObject)
|
||||
assert telegram.EQUIPMENT_IDENTIFIER.unit is None
|
||||
assert isinstance(telegram.EQUIPMENT_IDENTIFIER.value, str)
|
||||
assert telegram.EQUIPMENT_IDENTIFIER.value == '4B384547303034303436333935353037'
|
||||
|
||||
# CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE], CosemObject)
|
||||
assert result[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_USAGE].value, Decimal)
|
||||
assert result[obis.CURRENT_ELECTRICITY_USAGE].value == Decimal('0.244')
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_USAGE, CosemObject)
|
||||
assert telegram.CURRENT_ELECTRICITY_USAGE.unit == 'kW'
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_USAGE.value, Decimal)
|
||||
assert telegram.CURRENT_ELECTRICITY_USAGE.value == Decimal('0.244')
|
||||
|
||||
# CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY], CosemObject)
|
||||
assert result[obis.CURRENT_ELECTRICITY_DELIVERY].unit == 'kW'
|
||||
assert isinstance(result[obis.CURRENT_ELECTRICITY_DELIVERY].value, Decimal)
|
||||
assert result[obis.CURRENT_ELECTRICITY_DELIVERY].value == Decimal('0')
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_DELIVERY, CosemObject)
|
||||
assert telegram.CURRENT_ELECTRICITY_DELIVERY.unit == 'kW'
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_DELIVERY.value, Decimal)
|
||||
assert telegram.CURRENT_ELECTRICITY_DELIVERY.value == Decimal('0')
|
||||
|
||||
# LONG_POWER_FAILURE_COUNT (96.7.9)
|
||||
assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT], CosemObject)
|
||||
assert result[obis.LONG_POWER_FAILURE_COUNT].unit is None
|
||||
assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT].value, int)
|
||||
assert result[obis.LONG_POWER_FAILURE_COUNT].value == 0
|
||||
assert isinstance(telegram.LONG_POWER_FAILURE_COUNT, CosemObject)
|
||||
assert telegram.LONG_POWER_FAILURE_COUNT.unit is None
|
||||
assert isinstance(telegram.LONG_POWER_FAILURE_COUNT.value, int)
|
||||
assert telegram.LONG_POWER_FAILURE_COUNT.value == 0
|
||||
|
||||
# SHORT_POWER_FAILURE_COUNT (1-0:96.7.21)
|
||||
assert isinstance(telegram.SHORT_POWER_FAILURE_COUNT, CosemObject)
|
||||
assert telegram.SHORT_POWER_FAILURE_COUNT.unit is None
|
||||
assert isinstance(telegram.SHORT_POWER_FAILURE_COUNT.value, int)
|
||||
assert telegram.SHORT_POWER_FAILURE_COUNT.value == 13
|
||||
|
||||
# VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SAG_L1_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SAG_L1_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L1_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SAG_L1_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L1_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SAG_L1_COUNT.value == 0
|
||||
|
||||
# VOLTAGE_SAG_L2_COUNT (1-0:52.32.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SAG_L2_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L2_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SAG_L2_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L2_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SAG_L2_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L2_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SAG_L2_COUNT.value == 0
|
||||
|
||||
# VOLTAGE_SAG_L3_COUNT (1-0:72.32.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SAG_L3_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SAG_L3_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SAG_L3_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L3_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SAG_L3_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SAG_L3_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SAG_L3_COUNT.value == 0
|
||||
|
||||
# VOLTAGE_SWELL_L1_COUNT (1-0:32.36.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SWELL_L1_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L1_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SWELL_L1_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L1_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SWELL_L1_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L1_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SWELL_L1_COUNT.value == 0
|
||||
|
||||
# VOLTAGE_SWELL_L2_COUNT (1-0:52.36.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SWELL_L2_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L2_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SWELL_L2_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L2_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SWELL_L2_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L2_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SWELL_L2_COUNT.value == 0
|
||||
|
||||
# VOLTAGE_SWELL_L3_COUNT (1-0:72.36.0)
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT], CosemObject)
|
||||
assert result[obis.VOLTAGE_SWELL_L3_COUNT].unit is None
|
||||
assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT].value, int)
|
||||
assert result[obis.VOLTAGE_SWELL_L3_COUNT].value == 0
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L3_COUNT, CosemObject)
|
||||
assert telegram.VOLTAGE_SWELL_L3_COUNT.unit is None
|
||||
assert isinstance(telegram.VOLTAGE_SWELL_L3_COUNT.value, int)
|
||||
assert telegram.VOLTAGE_SWELL_L3_COUNT.value == 0
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L1 (1-0:32.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L1.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L1.value == Decimal('230.0')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L2 (1-0:52.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L2.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L2.value == Decimal('230.0')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L3 (1-0:72.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L3.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L3.value == Decimal('229.0')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L1.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L1.value == Decimal('0.48')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L2.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L2.value == Decimal('0.44')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L3.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L3.value == Decimal('0.86')
|
||||
|
||||
# TEXT_MESSAGE (0-0:96.13.0)
|
||||
assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
|
||||
assert result[obis.TEXT_MESSAGE].unit is None
|
||||
assert result[obis.TEXT_MESSAGE].value is None
|
||||
|
||||
# DEVICE_TYPE (0-x:24.1.0)
|
||||
assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
|
||||
assert result[obis.DEVICE_TYPE].unit is None
|
||||
assert isinstance(result[obis.DEVICE_TYPE].value, int)
|
||||
assert result[obis.DEVICE_TYPE].value == 3
|
||||
assert isinstance(telegram.TEXT_MESSAGE, CosemObject)
|
||||
assert telegram.TEXT_MESSAGE.unit is None
|
||||
assert telegram.TEXT_MESSAGE.value is None
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE (1-0:21.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE].value == Decimal('0.070')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE.value == Decimal('0.070')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE (1-0:41.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE].value == Decimal('0.032')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE.value == Decimal('0.032')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE (1-0:61.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE].value == Decimal('0.142')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE.value == Decimal('0.142')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE (1-0:22.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE].value == Decimal('0')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE.value == Decimal('0')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE (1-0:42.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE].value == Decimal('0')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE.value == Decimal('0')
|
||||
|
||||
# INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE (1-0:62.7.0)
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE], CosemObject)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].unit == 'kW'
|
||||
assert isinstance(result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value, Decimal)
|
||||
assert result[obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE].value == Decimal('0')
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.unit == 'kW'
|
||||
assert isinstance(telegram.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE.value == Decimal('0')
|
||||
|
||||
# EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS], CosemObject)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER_GAS].unit is None
|
||||
assert isinstance(result[obis.EQUIPMENT_IDENTIFIER_GAS].value, str)
|
||||
assert result[obis.EQUIPMENT_IDENTIFIER_GAS].value == '3232323241424344313233343536373839'
|
||||
# There's only one Mbus device (gas meter) in this case. Alternatively
|
||||
# use get_mbus_device_by_channel
|
||||
gas_meter_devices = telegram.MBUS_DEVICES
|
||||
gas_meter_device = gas_meter_devices[0]
|
||||
|
||||
# HOURLY_GAS_METER_READING (0-1:24.2.1)
|
||||
assert isinstance(result[obis.HOURLY_GAS_METER_READING], MBusObject)
|
||||
assert result[obis.HOURLY_GAS_METER_READING].unit == 'm3'
|
||||
assert isinstance(result[obis.HOURLY_GAS_METER_READING].value, Decimal)
|
||||
assert result[obis.HOURLY_GAS_METER_READING].value == Decimal('0.107')
|
||||
# MBUS_DEVICE_TYPE (0-1:96.1.0)
|
||||
assert isinstance(gas_meter_device.MBUS_DEVICE_TYPE, CosemObject)
|
||||
assert gas_meter_device.MBUS_DEVICE_TYPE.unit is None
|
||||
assert isinstance(gas_meter_device.MBUS_DEVICE_TYPE.value, int)
|
||||
assert gas_meter_device.MBUS_DEVICE_TYPE.value == 3
|
||||
|
||||
# MBUS_EQUIPMENT_IDENTIFIER (0-1:96.1.0)
|
||||
assert isinstance(gas_meter_device.MBUS_EQUIPMENT_IDENTIFIER, CosemObject)
|
||||
assert gas_meter_device.MBUS_EQUIPMENT_IDENTIFIER.unit is None
|
||||
assert isinstance(gas_meter_device.MBUS_EQUIPMENT_IDENTIFIER.value, str)
|
||||
assert gas_meter_device.MBUS_EQUIPMENT_IDENTIFIER.value == '3232323241424344313233343536373839'
|
||||
|
||||
# MBUS_METER_READING (0-1:24.2.1)
|
||||
assert isinstance(gas_meter_device.MBUS_METER_READING, MBusObject)
|
||||
assert gas_meter_device.MBUS_METER_READING.unit == 'm3'
|
||||
assert isinstance(telegram.MBUS_METER_READING.value, Decimal)
|
||||
assert gas_meter_device.MBUS_METER_READING.value == Decimal('0.107')
|
||||
|
||||
def test_checksum_valid(self):
|
||||
# No exception is raised.
|
||||
@@ -208,7 +257,27 @@ class TelegramParserV5Test(unittest.TestCase):
|
||||
|
||||
def test_checksum_missing(self):
|
||||
# Remove the checksum value causing a ParseError.
|
||||
corrupted_telegram = TELEGRAM_V5.replace('!87B3\r\n', '')
|
||||
|
||||
corrupted_telegram = TELEGRAM_V5.replace('!6EEE\r\n', '')
|
||||
with self.assertRaises(ParseError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
|
||||
def test_gas_timestamp_invalid(self):
|
||||
# Issue 120
|
||||
# Sometimes a MBUS device (For ex a Gas Meter) returns an invalid timestamp
|
||||
# Instead of failing, we should just ignore the timestamp
|
||||
invalid_date_telegram = TELEGRAM_V5.replace(
|
||||
'0-1:24.2.1(170102161005W)(00000.107*m3)\r\n',
|
||||
'0-1:24.2.1(632525252525S)(00000.000)\r\n'
|
||||
)
|
||||
invalid_date_telegram = invalid_date_telegram.replace('!6EEE\r\n', '!90C2\r\n')
|
||||
parser = TelegramParser(telegram_specifications.V5)
|
||||
telegram = parser.parse(invalid_date_telegram)
|
||||
|
||||
# MBUS DEVICE 1
|
||||
mbus1 = telegram.get_mbus_device_by_channel(1)
|
||||
|
||||
# MBUS_METER_READING (0-1:24.2.1)
|
||||
assert isinstance(mbus1.MBUS_METER_READING, MBusObject)
|
||||
assert mbus1.MBUS_METER_READING.unit is None
|
||||
assert isinstance(mbus1.MBUS_METER_READING.value, Decimal)
|
||||
assert mbus1.MBUS_METER_READING.value == Decimal('0.000')
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import datetime
|
||||
import unittest
|
||||
|
||||
import pytz
|
||||
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.exceptions import InvalidChecksumError, ParseError
|
||||
from dsmr_parser.objects import CosemObject
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from test.example_telegrams import TELEGRAM_V5_EON_HU
|
||||
|
||||
|
||||
class TelegramParserV5EONHUTest(unittest.TestCase):
|
||||
""" Test parsing of a DSMR v5 EON Hungary telegram. """
|
||||
|
||||
def test_parse(self):
|
||||
parser = TelegramParser(telegram_specifications.EON_HUNGARY)
|
||||
try:
|
||||
telegram = parser.parse(TELEGRAM_V5_EON_HU, throw_ex=True)
|
||||
except Exception as ex:
|
||||
assert False, f"parse trigged an exception {ex}"
|
||||
|
||||
# P1_MESSAGE_TIMESTAMP (0-0:1.0.0)
|
||||
assert isinstance(telegram.P1_MESSAGE_TIMESTAMP, CosemObject)
|
||||
assert telegram.P1_MESSAGE_TIMESTAMP.unit is None
|
||||
assert isinstance(telegram.P1_MESSAGE_TIMESTAMP.value, datetime.datetime)
|
||||
assert telegram.P1_MESSAGE_TIMESTAMP.value == \
|
||||
pytz.timezone("Europe/Budapest").localize(datetime.datetime(2023, 7, 24, 15, 7, 30))
|
||||
|
||||
# EON_HU_COSEM_LOGICAL_DEVICE_NAME (0-0:42.0.0)
|
||||
assert isinstance(telegram.COSEM_LOGICAL_DEVICE_NAME, CosemObject)
|
||||
assert telegram.COSEM_LOGICAL_DEVICE_NAME.unit is None
|
||||
assert isinstance(telegram.COSEM_LOGICAL_DEVICE_NAME.value, str)
|
||||
assert telegram.COSEM_LOGICAL_DEVICE_NAME.value == '53414733303832323030303032313630'
|
||||
|
||||
# EON_HU_EQUIPMENT_SERIAL_NUMBER (0-0:96.1.0)
|
||||
assert isinstance(telegram.EQUIPMENT_SERIAL_NUMBER, CosemObject)
|
||||
assert telegram.EQUIPMENT_SERIAL_NUMBER.unit is None
|
||||
assert isinstance(telegram.EQUIPMENT_SERIAL_NUMBER.value, str)
|
||||
assert telegram.EQUIPMENT_SERIAL_NUMBER.value == '383930303832323030303032313630'
|
||||
|
||||
# ELECTRICITY_ACTIVE_TARIFF (0-0:96.14.0)
|
||||
assert isinstance(telegram.ELECTRICITY_ACTIVE_TARIFF, CosemObject)
|
||||
assert telegram.ELECTRICITY_ACTIVE_TARIFF.unit is None
|
||||
assert isinstance(telegram.ELECTRICITY_ACTIVE_TARIFF.value, str)
|
||||
assert telegram.ELECTRICITY_ACTIVE_TARIFF.value == '0001'
|
||||
|
||||
# ACTUAL_SWITCH_POSITION (0-0:96.3.10)
|
||||
assert isinstance(telegram.ACTUAL_SWITCH_POSITION, CosemObject)
|
||||
assert telegram.ACTUAL_SWITCH_POSITION.unit is None
|
||||
assert isinstance(telegram.ACTUAL_SWITCH_POSITION.value, str)
|
||||
assert telegram.ACTUAL_SWITCH_POSITION.value == '1'
|
||||
|
||||
# ACTUAL_TRESHOLD_ELECTRICITY (0-0:17.0.0)
|
||||
assert isinstance(telegram.ACTUAL_TRESHOLD_ELECTRICITY, CosemObject)
|
||||
assert telegram.ACTUAL_TRESHOLD_ELECTRICITY.unit == 'kW'
|
||||
assert isinstance(telegram.ACTUAL_TRESHOLD_ELECTRICITY.value, Decimal)
|
||||
assert telegram.ACTUAL_TRESHOLD_ELECTRICITY.value == Decimal('90.000')
|
||||
|
||||
# ELECTRICITY_IMPORTED_TOTAL (1-0:1.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_IMPORTED_TOTAL, CosemObject)
|
||||
assert telegram.ELECTRICITY_IMPORTED_TOTAL.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_IMPORTED_TOTAL.value, Decimal)
|
||||
assert telegram.ELECTRICITY_IMPORTED_TOTAL.value == Decimal('000173.640')
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_1 (1-0:1.8.1)
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_1, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_1.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_1.value == Decimal('000047.719')
|
||||
|
||||
# ELECTRICITY_USED_TARIFF_2 (1-0:1.8.2)
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_2, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_2.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_2.value == Decimal('000125.921')
|
||||
|
||||
# EON_HU_ELECTRICITY_USED_TARIFF_3 (1-0:1.8.3)
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_3, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_3.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_3.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_3.value == Decimal('000000.000')
|
||||
|
||||
# EON_HU_ELECTRICITY_USED_TARIFF_4 (1-0:1.8.4)
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_4, CosemObject)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_4.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_USED_TARIFF_4.value, Decimal)
|
||||
assert telegram.ELECTRICITY_USED_TARIFF_4.value == Decimal('000000.000')
|
||||
|
||||
# ELECTRICITY_EXPORTED_TOTAL (1-0:2.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_EXPORTED_TOTAL, CosemObject)
|
||||
assert telegram.ELECTRICITY_EXPORTED_TOTAL.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_EXPORTED_TOTAL.value, Decimal)
|
||||
assert telegram.ELECTRICITY_EXPORTED_TOTAL.value == Decimal('000627.177')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_1 (1-0:2.8.1)
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_1, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_1.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_1.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_1.value == Decimal('000401.829')
|
||||
|
||||
# ELECTRICITY_DELIVERED_TARIFF_2 (1-0:2.8.2)
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_2, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_2.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_2.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_2.value == Decimal('000225.348')
|
||||
|
||||
# EON_HU_ELECTRICITY_DELIVERED_TARIFF_3 (1-0:2.8.3)
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_3, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_3.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_3.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_3.value == Decimal('000000.000')
|
||||
|
||||
# EON_HU_ELECTRICITY_DELIVERED_TARIFF_4 (1-0:2.8.4)
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_4, CosemObject)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_4.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_DELIVERED_TARIFF_4.value, Decimal)
|
||||
assert telegram.ELECTRICITY_DELIVERED_TARIFF_4.value == Decimal('000000.000')
|
||||
|
||||
# ELECTRICITY_REACTIVE_IMPORTED_TOTAL (1-0:3.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_IMPORTED_TOTAL, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_IMPORTED_TOTAL.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_IMPORTED_TOTAL.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_IMPORTED_TOTAL.value == Decimal('000000.123')
|
||||
|
||||
# ELECTRICITY_REACTIVE_EXPORTED_TOTAL (1-0:4.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_EXPORTED_TOTAL, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_EXPORTED_TOTAL.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_EXPORTED_TOTAL.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_EXPORTED_TOTAL.value == Decimal('000303.131')
|
||||
|
||||
# EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q1 (1-0:5.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q1, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q1.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q1.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q1.value == Decimal('000000.668')
|
||||
|
||||
# EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q2 (1-0:6.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q2, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q2.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q2.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q2.value == Decimal('000000.071')
|
||||
|
||||
# EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q3 (1-0:7.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q3, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q3.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q3.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q3.value == Decimal('000160.487')
|
||||
|
||||
# EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q4 (1-0:8.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q4, CosemObject)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q4.unit == 'kvarh'
|
||||
assert isinstance(telegram.ELECTRICITY_REACTIVE_TOTAL_Q4.value, Decimal)
|
||||
assert telegram.ELECTRICITY_REACTIVE_TOTAL_Q4.value == Decimal('000143.346')
|
||||
|
||||
# EON_HU_ELECTRICITY_COMBINED (1-0:15.8.0)
|
||||
assert isinstance(telegram.ELECTRICITY_COMBINED, CosemObject)
|
||||
assert telegram.ELECTRICITY_COMBINED.unit == 'kWh'
|
||||
assert isinstance(telegram.ELECTRICITY_COMBINED.value, Decimal)
|
||||
assert telegram.ELECTRICITY_COMBINED.value == Decimal('000800.817')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L2 (1-0:32.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L1.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L1.value == Decimal('240.4')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L2 (1-0:52.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L2.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L2.value == Decimal('239.1')
|
||||
|
||||
# INSTANTANEOUS_VOLTAGE_L3 (1-0:72.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L3.unit == 'V'
|
||||
assert isinstance(telegram.INSTANTANEOUS_VOLTAGE_L3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_VOLTAGE_L3.value == Decimal('241.2')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L1.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L1.value == Decimal('003')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L2.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L2.value == Decimal('004')
|
||||
|
||||
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L3.unit == 'A'
|
||||
assert isinstance(telegram.INSTANTANEOUS_CURRENT_L3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_CURRENT_L3.value == Decimal('003')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL (1-0:13.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_TOTAL, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_TOTAL.unit is None
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_TOTAL.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_TOTAL.value == Decimal('4.556')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_POWER_FACTOR_L1 (1-0:33.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L1.unit is None
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L1.value == Decimal('4.591')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_POWER_FACTOR_L2 (1-0:53.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L2.unit is None
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L2.value == Decimal('4.542')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_POWER_FACTOR_L3 (1-0:73.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L3.unit is None
|
||||
assert isinstance(telegram.INSTANTANEOUS_POWER_FACTOR_L3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_POWER_FACTOR_L3.value == Decimal('4.552')
|
||||
|
||||
# EON_HU_FREQUENCY (1-0:14.7.0)
|
||||
assert isinstance(telegram.FREQUENCY, CosemObject)
|
||||
assert telegram.FREQUENCY.unit == "Hz"
|
||||
assert isinstance(telegram.FREQUENCY.value, Decimal)
|
||||
assert telegram.FREQUENCY.value == Decimal('50.00')
|
||||
|
||||
# CURRENT_ELECTRICITY_USAGE (1-0:1.7.0)
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_USAGE, CosemObject)
|
||||
assert telegram.CURRENT_ELECTRICITY_USAGE.unit == 'kW'
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_USAGE.value, Decimal)
|
||||
assert telegram.CURRENT_ELECTRICITY_USAGE.value == Decimal('00.000')
|
||||
|
||||
# CURRENT_ELECTRICITY_DELIVERY (1-0:2.7.0)
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_DELIVERY, CosemObject)
|
||||
assert telegram.CURRENT_ELECTRICITY_DELIVERY.unit == 'kW'
|
||||
assert isinstance(telegram.CURRENT_ELECTRICITY_DELIVERY.value, Decimal)
|
||||
assert telegram.CURRENT_ELECTRICITY_DELIVERY.value == Decimal('02.601')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q1 (1-0:5.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q1, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q1.unit == 'kvar'
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q1.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q1.value == Decimal('00.000')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q2 (1-0:6.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q2, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q2.unit == 'kvar'
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q2.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q2.value == Decimal('00.000')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q3 (1-0:7.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q3, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q3.unit == 'kvar'
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q3.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q3.value == Decimal('00.504')
|
||||
|
||||
# EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q4 (1-0:8.7.0)
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q4, CosemObject)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q4.unit == 'kvar'
|
||||
assert isinstance(telegram.INSTANTANEOUS_REACTIVE_POWER_Q4.value, Decimal)
|
||||
assert telegram.INSTANTANEOUS_REACTIVE_POWER_Q4.value == Decimal('00.000')
|
||||
|
||||
# FUSE_THRESHOLD_L1 (1-0:31.4.0)
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L1, CosemObject)
|
||||
assert telegram.FUSE_THRESHOLD_L1.unit == 'A'
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L1.value, Decimal)
|
||||
assert telegram.FUSE_THRESHOLD_L1.value == Decimal('200.00')
|
||||
|
||||
# FUSE_THRESHOLD_L2 (1-0:31.4.0)
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L2, CosemObject)
|
||||
assert telegram.FUSE_THRESHOLD_L2.unit == 'A'
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L2.value, Decimal)
|
||||
assert telegram.FUSE_THRESHOLD_L2.value == Decimal('200.00')
|
||||
|
||||
# FUSE_THRESHOLD_L3 (1-0:31.4.0)
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L3, CosemObject)
|
||||
assert telegram.FUSE_THRESHOLD_L3.unit == 'A'
|
||||
assert isinstance(telegram.FUSE_THRESHOLD_L3.value, Decimal)
|
||||
assert telegram.FUSE_THRESHOLD_L3.value == Decimal('200.00')
|
||||
|
||||
# TEXT_MESSAGE (0-0:96.13.0)
|
||||
assert isinstance(telegram.TEXT_MESSAGE, CosemObject)
|
||||
assert telegram.TEXT_MESSAGE.unit is None
|
||||
assert telegram.TEXT_MESSAGE.value is None
|
||||
|
||||
def test_checksum_valid(self):
|
||||
# No exception is raised.
|
||||
TelegramParser.validate_checksum(TELEGRAM_V5_EON_HU)
|
||||
|
||||
def test_checksum_invalid(self):
|
||||
# Remove the electricty used data value. This causes the checksum to
|
||||
# not match anymore.
|
||||
corrupted_telegram = TELEGRAM_V5_EON_HU.replace(
|
||||
'1-0:1.8.1(000047.719*kWh)\r\n',
|
||||
''
|
||||
)
|
||||
|
||||
with self.assertRaises(InvalidChecksumError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
|
||||
def test_checksum_missing(self):
|
||||
# Remove the checksum value causing a ParseError.
|
||||
corrupted_telegram = TELEGRAM_V5_EON_HU.replace('!99DA\r\n', '')
|
||||
with self.assertRaises(ParseError):
|
||||
TelegramParser.validate_checksum(corrupted_telegram)
|
||||
+27
-8
@@ -3,10 +3,8 @@ from unittest.mock import Mock
|
||||
import unittest
|
||||
|
||||
from dsmr_parser import obis_references as obis
|
||||
from dsmr_parser import telegram_specifications
|
||||
from dsmr_parser.parsers import TelegramParser
|
||||
from dsmr_parser.clients.protocol import DSMRProtocol
|
||||
|
||||
from dsmr_parser.clients.protocol import create_dsmr_protocol
|
||||
from dsmr_parser.objects import Telegram
|
||||
|
||||
TELEGRAM_V2_2 = (
|
||||
'/ISk5\2MT382-1004\r\n'
|
||||
@@ -35,9 +33,10 @@ TELEGRAM_V2_2 = (
|
||||
class ProtocolTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
telegram_parser = TelegramParser(telegram_specifications.V2_2)
|
||||
self.protocol = DSMRProtocol(None, telegram_parser,
|
||||
telegram_callback=Mock())
|
||||
new_protocol, _ = create_dsmr_protocol('2.2',
|
||||
telegram_callback=Mock(),
|
||||
keep_alive_interval=1)
|
||||
self.protocol = new_protocol()
|
||||
|
||||
def test_complete_packet(self):
|
||||
"""Protocol should assemble incoming lines into complete packet."""
|
||||
@@ -45,10 +44,30 @@ class ProtocolTest(unittest.TestCase):
|
||||
self.protocol.data_received(TELEGRAM_V2_2.encode('ascii'))
|
||||
|
||||
telegram = self.protocol.telegram_callback.call_args_list[0][0][0]
|
||||
assert isinstance(telegram, dict)
|
||||
assert isinstance(telegram, Telegram)
|
||||
|
||||
assert float(telegram[obis.CURRENT_ELECTRICITY_USAGE].value) == 1.01
|
||||
assert telegram[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
|
||||
|
||||
assert float(telegram[obis.GAS_METER_READING].value) == 1.001
|
||||
assert telegram[obis.GAS_METER_READING].unit == 'm3'
|
||||
|
||||
def test_receive_packet(self):
|
||||
"""Protocol packet reception."""
|
||||
|
||||
mock_transport = Mock()
|
||||
self.protocol.connection_made(mock_transport)
|
||||
assert not self.protocol._active
|
||||
|
||||
self.protocol.data_received(TELEGRAM_V2_2.encode('ascii'))
|
||||
assert self.protocol._active
|
||||
|
||||
# 1st call of keep_alive resets 'active' flag
|
||||
self.protocol.keep_alive()
|
||||
assert not self.protocol._active
|
||||
|
||||
# 2nd call of keep_alive should close the transport
|
||||
self.protocol.keep_alive()
|
||||
mock_transport.close.assert_called_once()
|
||||
|
||||
self.protocol.connection_lost(None)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
from unittest.mock import Mock
|
||||
|
||||
import unittest
|
||||
|
||||
from dsmr_parser import obis_references as obis
|
||||
from dsmr_parser.clients.rfxtrx_protocol import create_rfxtrx_dsmr_protocol, PACKETTYPE_DSMR, SUBTYPE_P1
|
||||
from dsmr_parser.objects import Telegram
|
||||
|
||||
TELEGRAM_V2_2 = (
|
||||
'/ISk5\2MT382-1004\r\n'
|
||||
'\r\n'
|
||||
'0-0:96.1.1(00000000000000)\r\n'
|
||||
'1-0:1.8.1(00001.001*kWh)\r\n'
|
||||
'1-0:1.8.2(00001.001*kWh)\r\n'
|
||||
'1-0:2.8.1(00001.001*kWh)\r\n'
|
||||
'1-0:2.8.2(00001.001*kWh)\r\n'
|
||||
'0-0:96.14.0(0001)\r\n'
|
||||
'1-0:1.7.0(0001.01*kW)\r\n'
|
||||
'1-0:2.7.0(0000.00*kW)\r\n'
|
||||
'0-0:17.0.0(0999.00*kW)\r\n'
|
||||
'0-0:96.3.10(1)\r\n'
|
||||
'0-0:96.13.1()\r\n'
|
||||
'0-0:96.13.0()\r\n'
|
||||
'0-1:24.1.0(3)\r\n'
|
||||
'0-1:96.1.0(000000000000)\r\n'
|
||||
'0-1:24.3.0(161107190000)(00)(60)(1)(0-1:24.2.1)(m3)\r\n'
|
||||
'(00001.001)\r\n'
|
||||
'0-1:24.4.0(1)\r\n'
|
||||
'!\r\n'
|
||||
)
|
||||
|
||||
OTHER_RF_PACKET = b'\x03\x01\x02\x03'
|
||||
|
||||
|
||||
def encode_telegram_as_RF_packets(telegram):
|
||||
data = b''
|
||||
|
||||
for line in telegram.split('\n'):
|
||||
packet_data = (line + '\n').encode('ascii')
|
||||
packet_header = bytes(bytearray([
|
||||
len(packet_data) + 3, # excluding length byte
|
||||
PACKETTYPE_DSMR,
|
||||
SUBTYPE_P1,
|
||||
0 # seq num (ignored)
|
||||
]))
|
||||
|
||||
data += packet_header + packet_data
|
||||
# other RF packets can pass by on the line
|
||||
data += OTHER_RF_PACKET
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class RFXtrxProtocolTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
new_protocol, _ = create_rfxtrx_dsmr_protocol('2.2',
|
||||
telegram_callback=Mock(),
|
||||
keep_alive_interval=1)
|
||||
self.protocol = new_protocol()
|
||||
|
||||
def test_complete_packet(self):
|
||||
"""Protocol should assemble incoming lines into complete packet."""
|
||||
|
||||
data = encode_telegram_as_RF_packets(TELEGRAM_V2_2)
|
||||
# send data broken up in two parts
|
||||
self.protocol.data_received(data[0:200])
|
||||
self.protocol.data_received(data[200:])
|
||||
|
||||
telegram = self.protocol.telegram_callback.call_args_list[0][0][0]
|
||||
assert isinstance(telegram, Telegram)
|
||||
|
||||
assert float(telegram[obis.CURRENT_ELECTRICITY_USAGE].value) == 1.01
|
||||
assert telegram[obis.CURRENT_ELECTRICITY_USAGE].unit == 'kW'
|
||||
|
||||
assert float(telegram[obis.GAS_METER_READING].value) == 1.001
|
||||
assert telegram[obis.GAS_METER_READING].unit == 'm3'
|
||||
Reference in New Issue
Block a user