From 10056371bf328cc589f07a6dfa8335ff5d954885 Mon Sep 17 00:00:00 2001 From: Joakim Olsson Date: Wed, 7 Jul 2021 11:27:41 +0200 Subject: [PATCH] feat: add SSO fault codes --- custom_components/ferroamp/const.py | 14 +++ custom_components/ferroamp/sensor.py | 23 +++-- tests/test_sensor.py | 141 ++++++++++++++++++++++++++- 3 files changed, 167 insertions(+), 11 deletions(-) diff --git a/custom_components/ferroamp/const.py b/custom_components/ferroamp/const.py index 54d69de..8162e49 100644 --- a/custom_components/ferroamp/const.py +++ b/custom_components/ferroamp/const.py @@ -28,3 +28,17 @@ for trouble shooting the battery, or call Ferroamp Support.""", "Not a fault, just an indication that Battery Manufacturer is not Ferroamp", ] + +SSO_FAULT_CODES = [ + 'Unknown fault code', + 'Unknown fault code', + 'Unknown fault code', + 'Unknown fault code', + 'UNDERVOLTAGE', + 'OVERVOLTAGE', + 'OVERHEAT', + 'Unknown fault code', + 'Unknown fault code', + 'Unknown fault code', + 'POWERLIMITING' +] diff --git a/custom_components/ferroamp/sensor.py b/custom_components/ferroamp/sensor.py index 3c05cda..07a74fb 100644 --- a/custom_components/ferroamp/sensor.py +++ b/custom_components/ferroamp/sensor.py @@ -36,7 +36,8 @@ DATA_LISTENERS, DOMAIN, ESO_FAULT_CODES, - MANUFACTURER + MANUFACTURER, + SSO_FAULT_CODES ) _LOGGER = logging.getLogger(__name__) @@ -207,14 +208,13 @@ def sso_event_received(msg): config_id, model=model ), - StringValFerroampSensor( + FaultcodeFerroampSensor( f"{device_name} Faultcode", "faultcode", - "", - "mdi:traffic-light", device_id, device_name, interval, + SSO_FAULT_CODES, config_id, model=model ), @@ -1027,10 +1027,17 @@ def update_state_from_events(self, events): if temp is not None: self._state = temp x = int(temp, 16) - for i, code in enumerate(self._fault_codes): - v = 1 << i - if x & v == v: - self.attrs[i] = code + if x == 0: + self.attrs[0] = "No errors" + else: + if 0 in self.attrs: + del self.attrs[0] + for i, code in enumerate(self._fault_codes): + v = 1 << i + if x & v == v: + self.attrs[i + 1] = code + elif i+1 in self.attrs: + del self.attrs[i + 1] def ehub_sensors(slug, name, interval, precision_battery, precision_energy, precision_frequency, config_id): diff --git a/tests/test_sensor.py b/tests/test_sensor.py index ca8c3e6..288d71b 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -794,7 +794,7 @@ async def test_setting_eso_sensor_values_via_mqtt_message(hass, mqtt_mock): 'friendly_name': 'Ferroamp ESO 1 Faultcode', 'icon': 'mdi:traffic-light', 'unit_of_measurement': '', - 7: 'Not a fault, just an indication that Battery Manufacturer is not Ferroamp' + 8: 'Not a fault, just an indication that Battery Manufacturer is not Ferroamp' } state = hass.states.get("sensor.ferroamp_eso_1_relay_status") @@ -1002,7 +1002,8 @@ async def test_setting_sso_sensor_values_via_mqtt_message(hass, mqtt_mock): assert state.attributes == { 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', 'icon': 'mdi:traffic-light', - 'unit_of_measurement': '' + 'unit_of_measurement': '', + 0: 'No errors' } state = hass.states.get("sensor.ferroamp_sso_12345678_relay_status") @@ -1094,7 +1095,8 @@ async def test_trim_part_no_from_sso_id(hass, mqtt_mock): assert state.attributes == { 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', 'icon': 'mdi:traffic-light', - 'unit_of_measurement': '' + 'unit_of_measurement': '', + 0: 'No errors' } state = hass.states.get("sensor.ferroamp_sso_12345678_relay_status") @@ -1169,6 +1171,139 @@ async def test_migrate_old_sso_entities(hass, mqtt_mock): } +async def test_sso_fault_codes(hass, mqtt_mock): + config_entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_NAME: "Ferroamp", + CONF_PREFIX: "extapi" + }, + options={ + CONF_INTERVAL: 1 + }, + version=1, + unique_id="ferroamp", + ) + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + topic = "extapi/data/sso" + async_fire_mqtt_message(hass, topic, """{ + "relaystatus": {"val": "0"}, + "temp": {"val": "6.482"}, + "wpv": {"val": "843516404273"}, + "ts": {"val": "2021-03-08T08:22:42UTC"}, + "udc": {"val": "769.872"}, + "faultcode": {"val": "0"}, + "ipv": {"val": "4.826"}, + "upv": {"val": "653.012"}, + "id": {"val": "12345678"} + }""") + await hass.async_block_till_done() + + state = hass.states.get("sensor.ferroamp_sso_12345678_faultcode") + assert state.state == "0" + assert state.attributes == { + 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', + 'icon': 'mdi:traffic-light', + 'unit_of_measurement': '', + 0: 'No errors' + } + + time.sleep(1.1) + async_fire_mqtt_message(hass, topic, """{ + "relaystatus": {"val": "0"}, + "temp": {"val": "6.482"}, + "wpv": {"val": "843516404273"}, + "ts": {"val": "2021-03-08T08:22:42UTC"}, + "udc": {"val": "769.872"}, + "faultcode": {"val": "10"}, + "ipv": {"val": "4.826"}, + "upv": {"val": "653.012"}, + "id": {"val": "12345678"} + }""") + await hass.async_block_till_done() + + state = hass.states.get("sensor.ferroamp_sso_12345678_faultcode") + assert state.state == "10" + assert state.attributes == { + 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', + 'icon': 'mdi:traffic-light', + 'unit_of_measurement': '', + 5: 'UNDERVOLTAGE' + } + + time.sleep(1.1) + async_fire_mqtt_message(hass, topic, """{ + "relaystatus": {"val": "0"}, + "temp": {"val": "6.482"}, + "wpv": {"val": "843516404273"}, + "ts": {"val": "2021-03-08T08:22:42UTC"}, + "udc": {"val": "769.872"}, + "faultcode": {"val": "20"}, + "ipv": {"val": "4.826"}, + "upv": {"val": "653.012"}, + "id": {"val": "12345678"} + }""") + await hass.async_block_till_done() + + state = hass.states.get("sensor.ferroamp_sso_12345678_faultcode") + assert state.state == "20" + assert state.attributes == { + 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', + 'icon': 'mdi:traffic-light', + 'unit_of_measurement': '', + 6: 'OVERVOLTAGE' + } + + time.sleep(1.1) + async_fire_mqtt_message(hass, topic, """{ + "relaystatus": {"val": "0"}, + "temp": {"val": "6.482"}, + "wpv": {"val": "843516404273"}, + "ts": {"val": "2021-03-08T08:22:42UTC"}, + "udc": {"val": "769.872"}, + "faultcode": {"val": "40"}, + "ipv": {"val": "4.826"}, + "upv": {"val": "653.012"}, + "id": {"val": "12345678"} + }""") + await hass.async_block_till_done() + + state = hass.states.get("sensor.ferroamp_sso_12345678_faultcode") + assert state.state == "40" + assert state.attributes == { + 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', + 'icon': 'mdi:traffic-light', + 'unit_of_measurement': '', + 7: 'OVERHEAT' + } + + time.sleep(1.1) + async_fire_mqtt_message(hass, topic, """{ + "relaystatus": {"val": "0"}, + "temp": {"val": "6.482"}, + "wpv": {"val": "843516404273"}, + "ts": {"val": "2021-03-08T08:22:42UTC"}, + "udc": {"val": "769.872"}, + "faultcode": {"val": "400"}, + "ipv": {"val": "4.826"}, + "upv": {"val": "653.012"}, + "id": {"val": "12345678"} + }""") + await hass.async_block_till_done() + + state = hass.states.get("sensor.ferroamp_sso_12345678_faultcode") + assert state.state == "400" + assert state.attributes == { + 'friendly_name': 'Ferroamp SSO 12345678 Faultcode', + 'icon': 'mdi:traffic-light', + 'unit_of_measurement': '', + 11: 'POWERLIMITING' + } + + async def test_restore_state(hass, mqtt_mock): mock_restore_cache( hass,