From 80c2efa9f2865982ea223bd488d4e3252bdbfc1d Mon Sep 17 00:00:00 2001
From: Robert Chmielowiec <robert+github@chmielowiec.net>
Date: Wed, 27 Jan 2021 14:10:58 +0100
Subject: [PATCH] Add total energy, preheater and RMOT sensors to comfoconnect
 (#45373)

---
 .coveragerc                                   |  2 +-
 .../components/comfoconnect/sensor.py         | 48 ++++++++--
 requirements_test_all.txt                     |  3 +
 tests/components/comfoconnect/__init__.py     |  1 +
 tests/components/comfoconnect/test_sensor.py  | 93 +++++++++++++++++++
 5 files changed, 137 insertions(+), 10 deletions(-)
 create mode 100644 tests/components/comfoconnect/__init__.py
 create mode 100644 tests/components/comfoconnect/test_sensor.py

diff --git a/.coveragerc b/.coveragerc
index da6cfd2a3b9..4faf71102f8 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -144,7 +144,7 @@ omit =
     homeassistant/components/co2signal/*
     homeassistant/components/coinbase/*
     homeassistant/components/comed_hourly_pricing/sensor.py
-    homeassistant/components/comfoconnect/*
+    homeassistant/components/comfoconnect/fan.py
     homeassistant/components/concord232/alarm_control_panel.py
     homeassistant/components/concord232/binary_sensor.py
     homeassistant/components/control4/__init__.py
diff --git a/homeassistant/components/comfoconnect/sensor.py b/homeassistant/components/comfoconnect/sensor.py
index d1003d59229..53075beecaf 100644
--- a/homeassistant/components/comfoconnect/sensor.py
+++ b/homeassistant/components/comfoconnect/sensor.py
@@ -3,6 +3,7 @@ import logging
 
 from pycomfoconnect import (
     SENSOR_BYPASS_STATE,
+    SENSOR_CURRENT_RMOT,
     SENSOR_DAYS_TO_REPLACE_FILTER,
     SENSOR_FAN_EXHAUST_DUTY,
     SENSOR_FAN_EXHAUST_FLOW,
@@ -15,7 +16,9 @@ from pycomfoconnect import (
     SENSOR_HUMIDITY_OUTDOOR,
     SENSOR_HUMIDITY_SUPPLY,
     SENSOR_POWER_CURRENT,
+    SENSOR_POWER_TOTAL,
     SENSOR_PREHEATER_POWER_CURRENT,
+    SENSOR_PREHEATER_POWER_TOTAL,
     SENSOR_TEMPERATURE_EXHAUST,
     SENSOR_TEMPERATURE_EXTRACT,
     SENSOR_TEMPERATURE_OUTDOOR,
@@ -27,9 +30,11 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA
 from homeassistant.const import (
     ATTR_DEVICE_CLASS,
     CONF_RESOURCES,
+    DEVICE_CLASS_ENERGY,
     DEVICE_CLASS_HUMIDITY,
     DEVICE_CLASS_POWER,
     DEVICE_CLASS_TEMPERATURE,
+    ENERGY_KILO_WATT_HOUR,
     PERCENTAGE,
     POWER_WATT,
     TEMP_CELSIUS,
@@ -46,6 +51,7 @@ ATTR_AIR_FLOW_EXHAUST = "air_flow_exhaust"
 ATTR_AIR_FLOW_SUPPLY = "air_flow_supply"
 ATTR_BYPASS_STATE = "bypass_state"
 ATTR_CURRENT_HUMIDITY = "current_humidity"
+ATTR_CURRENT_RMOT = "current_rmot"
 ATTR_CURRENT_TEMPERATURE = "current_temperature"
 ATTR_DAYS_TO_REPLACE_FILTER = "days_to_replace_filter"
 ATTR_EXHAUST_FAN_DUTY = "exhaust_fan_duty"
@@ -55,7 +61,9 @@ ATTR_EXHAUST_TEMPERATURE = "exhaust_temperature"
 ATTR_OUTSIDE_HUMIDITY = "outside_humidity"
 ATTR_OUTSIDE_TEMPERATURE = "outside_temperature"
 ATTR_POWER_CURRENT = "power_usage"
+ATTR_POWER_TOTAL = "power_total"
 ATTR_PREHEATER_POWER_CURRENT = "preheater_power_usage"
+ATTR_PREHEATER_POWER_TOTAL = "preheater_power_total"
 ATTR_SUPPLY_FAN_DUTY = "supply_fan_duty"
 ATTR_SUPPLY_FAN_SPEED = "supply_fan_speed"
 ATTR_SUPPLY_HUMIDITY = "supply_humidity"
@@ -74,7 +82,7 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
         ATTR_LABEL: "Inside Temperature",
         ATTR_UNIT: TEMP_CELSIUS,
-        ATTR_ICON: "mdi:thermometer",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_TEMPERATURE_EXTRACT,
         ATTR_MULTIPLIER: 0.1,
     },
@@ -82,14 +90,22 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
         ATTR_LABEL: "Inside Humidity",
         ATTR_UNIT: PERCENTAGE,
-        ATTR_ICON: "mdi:water-percent",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_HUMIDITY_EXTRACT,
     },
+    ATTR_CURRENT_RMOT: {
+        ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
+        ATTR_LABEL: "Current RMOT",
+        ATTR_UNIT: TEMP_CELSIUS,
+        ATTR_ICON: None,
+        ATTR_ID: SENSOR_CURRENT_RMOT,
+        ATTR_MULTIPLIER: 0.1,
+    },
     ATTR_OUTSIDE_TEMPERATURE: {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
         ATTR_LABEL: "Outside Temperature",
         ATTR_UNIT: TEMP_CELSIUS,
-        ATTR_ICON: "mdi:thermometer",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_TEMPERATURE_OUTDOOR,
         ATTR_MULTIPLIER: 0.1,
     },
@@ -97,14 +113,14 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
         ATTR_LABEL: "Outside Humidity",
         ATTR_UNIT: PERCENTAGE,
-        ATTR_ICON: "mdi:water-percent",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_HUMIDITY_OUTDOOR,
     },
     ATTR_SUPPLY_TEMPERATURE: {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
         ATTR_LABEL: "Supply Temperature",
         ATTR_UNIT: TEMP_CELSIUS,
-        ATTR_ICON: "mdi:thermometer",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_TEMPERATURE_SUPPLY,
         ATTR_MULTIPLIER: 0.1,
     },
@@ -112,7 +128,7 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
         ATTR_LABEL: "Supply Humidity",
         ATTR_UNIT: PERCENTAGE,
-        ATTR_ICON: "mdi:water-percent",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_HUMIDITY_SUPPLY,
     },
     ATTR_SUPPLY_FAN_SPEED: {
@@ -147,7 +163,7 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
         ATTR_LABEL: "Exhaust Temperature",
         ATTR_UNIT: TEMP_CELSIUS,
-        ATTR_ICON: "mdi:thermometer",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_TEMPERATURE_EXHAUST,
         ATTR_MULTIPLIER: 0.1,
     },
@@ -155,7 +171,7 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
         ATTR_LABEL: "Exhaust Humidity",
         ATTR_UNIT: PERCENTAGE,
-        ATTR_ICON: "mdi:water-percent",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_HUMIDITY_EXHAUST,
     },
     ATTR_AIR_FLOW_SUPPLY: {
@@ -190,9 +206,16 @@ SENSOR_TYPES = {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
         ATTR_LABEL: "Power usage",
         ATTR_UNIT: POWER_WATT,
-        ATTR_ICON: "mdi:flash",
+        ATTR_ICON: None,
         ATTR_ID: SENSOR_POWER_CURRENT,
     },
+    ATTR_POWER_TOTAL: {
+        ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
+        ATTR_LABEL: "Power total",
+        ATTR_UNIT: ENERGY_KILO_WATT_HOUR,
+        ATTR_ICON: None,
+        ATTR_ID: SENSOR_POWER_TOTAL,
+    },
     ATTR_PREHEATER_POWER_CURRENT: {
         ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER,
         ATTR_LABEL: "Preheater power usage",
@@ -200,6 +223,13 @@ SENSOR_TYPES = {
         ATTR_ICON: None,
         ATTR_ID: SENSOR_PREHEATER_POWER_CURRENT,
     },
+    ATTR_PREHEATER_POWER_TOTAL: {
+        ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY,
+        ATTR_LABEL: "Preheater power total",
+        ATTR_UNIT: ENERGY_KILO_WATT_HOUR,
+        ATTR_ICON: None,
+        ATTR_ID: SENSOR_PREHEATER_POWER_TOTAL,
+    },
 }
 
 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index b3fef08aa67..ed4f0bdac97 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -672,6 +672,9 @@ pycfdns==1.2.1
 # homeassistant.components.cast
 pychromecast==7.7.2
 
+# homeassistant.components.comfoconnect
+pycomfoconnect==0.4
+
 # homeassistant.components.coolmaster
 pycoolmasternet-async==0.1.2
 
diff --git a/tests/components/comfoconnect/__init__.py b/tests/components/comfoconnect/__init__.py
new file mode 100644
index 00000000000..8da47b510be
--- /dev/null
+++ b/tests/components/comfoconnect/__init__.py
@@ -0,0 +1 @@
+"""Tests for the comfoconnect component."""
diff --git a/tests/components/comfoconnect/test_sensor.py b/tests/components/comfoconnect/test_sensor.py
new file mode 100644
index 00000000000..3ae078cccef
--- /dev/null
+++ b/tests/components/comfoconnect/test_sensor.py
@@ -0,0 +1,93 @@
+"""Tests for the comfoconnect sensor platform."""
+# import json
+from unittest.mock import patch
+
+import pytest
+
+from homeassistant.components.sensor import DOMAIN
+from homeassistant.setup import async_setup_component
+
+from tests.common import assert_setup_component
+
+COMPONENT = "comfoconnect"
+VALID_CONFIG = {
+    COMPONENT: {"host": "1.2.3.4"},
+    DOMAIN: {
+        "platform": COMPONENT,
+        "resources": [
+            "current_humidity",
+            "current_temperature",
+            "supply_fan_duty",
+            "power_usage",
+            "preheater_power_total",
+        ],
+    },
+}
+
+
+@pytest.fixture
+def mock_bridge_discover():
+    """Mock the bridge discover method."""
+    with patch("pycomfoconnect.bridge.Bridge.discover") as mock_bridge_discover:
+        mock_bridge_discover.return_value[0].uuid.hex.return_value = "00"
+        yield mock_bridge_discover
+
+
+@pytest.fixture
+def mock_comfoconnect_command():
+    """Mock the ComfoConnect connect method."""
+    with patch(
+        "pycomfoconnect.comfoconnect.ComfoConnect._command"
+    ) as mock_comfoconnect_command:
+        yield mock_comfoconnect_command
+
+
+@pytest.fixture
+async def setup_sensor(hass, mock_bridge_discover, mock_comfoconnect_command):
+    """Set up demo sensor component."""
+    with assert_setup_component(1, DOMAIN):
+        await async_setup_component(hass, DOMAIN, VALID_CONFIG)
+        await hass.async_block_till_done()
+
+
+async def test_sensors(hass, setup_sensor):
+    """Test the sensors."""
+    state = hass.states.get("sensor.comfoairq_inside_humidity")
+    assert state is not None
+
+    assert state.name == "ComfoAirQ Inside Humidity"
+    assert state.attributes.get("unit_of_measurement") == "%"
+    assert state.attributes.get("device_class") == "humidity"
+    assert state.attributes.get("icon") is None
+
+    state = hass.states.get("sensor.comfoairq_inside_temperature")
+    assert state is not None
+
+    assert state.name == "ComfoAirQ Inside Temperature"
+    assert state.attributes.get("unit_of_measurement") == "°C"
+    assert state.attributes.get("device_class") == "temperature"
+    assert state.attributes.get("icon") is None
+
+    state = hass.states.get("sensor.comfoairq_supply_fan_duty")
+    assert state is not None
+
+    assert state.name == "ComfoAirQ Supply Fan Duty"
+    assert state.attributes.get("unit_of_measurement") == "%"
+    assert state.attributes.get("device_class") is None
+    assert state.attributes.get("icon") == "mdi:fan"
+
+    state = hass.states.get("sensor.comfoairq_power_usage")
+    assert state is not None
+
+    assert state.name == "ComfoAirQ Power usage"
+    assert state.attributes.get("unit_of_measurement") == "W"
+    assert state.attributes.get("device_class") == "power"
+    assert state.attributes.get("icon") is None
+
+    state = hass.states.get("sensor.comfoairq_preheater_power_total")
+    assert state is not None
+
+    assert state.name == "ComfoAirQ Preheater power total"
+    assert state.attributes.get("unit_of_measurement") == "kWh"
+    assert state.attributes.get("device_class") == "energy"
+    assert state.attributes.get("icon") is None
-- 
GitLab