Repository: XKNX/xknx

Issue:
Missing DPT's for water meters
**Description of problem:**

Seems we are missing DPT types for water meters.

- [ ] using xknx standalone
- [X] using Home-Assistant knx plugin

**Version information:**
- xknx / Home-Assistant release with the issue:
- last working xknx / Home-Assistant release (if known):

**KNX installation:**
<!--
Please provide details about your installation.
- Manufacturer and model of relevant actors, sensors or interfaces.
- if you have access to ETS:
  - provide relevant group address parameters (DPT, Flags)
  - if applicable: excerpt of bus monitor output
-->

**Problem-relevant `xknx.yaml` or `configuration.yaml` entries (fill out even if it seems unimportant):**

**Traceback (if applicable):**
````
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/setup.py", line 213, in _async_setup_component
    result = await task
  File "/usr/src/homeassistant/homeassistant/components/knx/__init__.py", line 141, in async_setup
    create_knx_device(
  File "/usr/src/homeassistant/homeassistant/components/knx/factory.py", line 56, in create_knx_device
    return _create_sensor(knx_module, config)
  File "/usr/src/homeassistant/homeassistant/components/knx/factory.py", line 214, in _create_sensor
    return XknxSensor(
  File "/usr/local/lib/python3.8/site-packages/xknx/devices/sensor.py", line 28, in __init__
    self.sensor_value = RemoteValueSensor(
  File "/usr/local/lib/python3.8/site-packages/xknx/remote_value/remote_value_sensor.py", line 29, in __init__
    raise ConversionError("invalid value type", value_type=value_type, device_name=device_name)
xknx.exceptions.exception.ConversionError: <ConversionError description="invalid value type" device_name="Vattenmätare Räknare" value_type="12.1200"/>
````

Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/33425616/badge)](https://coveralls.io/builds/33425616)

Coverage increased (+0.02%) to 92.138% when pulling **94490bdee06d975b533e156c62711a42c64baae9 on marvin-w:feature/add_new_sensor_types** into **cfa66087ba48350c62b93dfcfa651020978f51ea on XKNX:master**.


Patch:
diff --git a/xknx/dpt/dpt_4byte_int.py b/xknx/dpt/dpt_4byte_int.py
index f62dfa9b..ba1d2a38 100644
--- a/xknx/dpt/dpt_4byte_int.py
+++ b/xknx/dpt/dpt_4byte_int.py
@@ -76,6 +76,24 @@ class DPT4ByteSigned(DPT4ByteUnsigned):
     _struct_format = ">i"
 
 
+class DPTVolumeLiquidLitre(DPT4ByteUnsigned):
+    """DPT 12.1200 DPT_VolumeLiquid_Litre (water/gas total consumption)."""
+
+    dpt_main_number = 12
+    dpt_sub_number = 1200
+    value_type = "volume_liquid_litre"
+    unit = "l"
+
+
+class DPTVolumeM3(DPT4ByteUnsigned):
+    """DPT 12.1201 DPT_Volume_m3 (water/gas total consumption volume)."""
+
+    dpt_main_number = 12
+    dpt_sub_number = 1201
+    value_type = "volume_m3"
+    unit = "m³"
+
+
 class DPTValue4Count(DPT4ByteSigned):
     """DPT 13.001 DPT_Value_4_Count (pulse)."""
 


Test patch:
diff --git a/requirements/testing.txt b/requirements/testing.txt
index 8df099d9..da90d7e5 100644
--- a/requirements/testing.txt
+++ b/requirements/testing.txt
@@ -7,7 +7,7 @@ flake8-isort==4.0.0
 pydocstyle==5.1.1
 pylint==2.6.0
 pylint-strict-informational==0.1
-pytest==6.0.1
+pytest==6.0.2
 pytest-cov==2.10.1
 pytest-timeout==1.4.2
 setuptools==50.3.0
diff --git a/test/devices_tests/sensor_test.py b/test/devices_tests/sensor_test.py
index 7b50415c..cadb56fd 100644
--- a/test/devices_tests/sensor_test.py
+++ b/test/devices_tests/sensor_test.py
@@ -66,6 +66,47 @@ class TestSensor(unittest.TestCase):
         self.assertEqual(sensor.unit_of_measurement(), "m/s²")
         self.assertEqual(sensor.ha_device_class(), None)
 
+    def test_str_volume_liquid_litre(self):
+        """Test resolve state with volume liquid sensor."""
+        xknx = XKNX(loop=self.loop)
+        sensor = Sensor(
+            xknx,
+            "TestSensor",
+            group_address_state="1/2/3",
+            value_type="volume_liquid_litre",
+        )
+        sensor.sensor_value.payload = DPTArray(
+            (
+                0x00,
+                0x00,
+                0x01,
+                0x00,
+            )
+        )
+
+        self.assertEqual(sensor.resolve_state(), 256)
+        self.assertEqual(sensor.unit_of_measurement(), "l")
+        self.assertEqual(sensor.ha_device_class(), None)
+
+    def test_str_volume_m3(self):
+        """Test resolve state with volume m3 sensor."""
+        xknx = XKNX(loop=self.loop)
+        sensor = Sensor(
+            xknx, "TestSensor", group_address_state="1/2/3", value_type="volume_m3"
+        )
+        sensor.sensor_value.payload = DPTArray(
+            (
+                0x00,
+                0x00,
+                0x01,
+                0x00,
+            )
+        )
+
+        self.assertEqual(sensor.resolve_state(), 256)
+        self.assertEqual(sensor.unit_of_measurement(), "m³")
+        self.assertEqual(sensor.ha_device_class(), None)
+
     def test_str_acceleration_angular(self):
         """Test resolve state with acceleration_angular sensor."""
         xknx = XKNX(loop=self.loop)