From af1055ebbaa8421428cdb2e9e4241d08ef92d510 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 12 Dec 2023 17:01:29 -0700 Subject: [PATCH] fix: filter firmware strings (#298) * fix: filter firmware strings * missing index * linting * define variable for use * more linting * update tests * formatting --- openevsehttp/__main__.py | 18 ++++- tests/conftest.py | 16 +++++ .../v4_json/config-extra-version.json | 66 +++++++++++++++++++ tests/test_main.py | 55 ++++++++-------- 4 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 tests/fixtures/v4_json/config-extra-version.json diff --git a/openevsehttp/__main__.py b/openevsehttp/__main__.py index a5d9bba..6bbeece 100644 --- a/openevsehttp/__main__.py +++ b/openevsehttp/__main__.py @@ -5,6 +5,7 @@ import datetime import json import logging +import re from typing import Any, Callable, Dict, Union import aiohttp # type: ignore @@ -120,7 +121,11 @@ async def process_request( _LOGGER.warning("Non JSON response: %s", message) if resp.status == 400: - _LOGGER.error("Error 400: %s", message["msg"]) + if "msg" in message.keys(): + index = "msg" + elif "error" in message.keys(): + index = "error" + _LOGGER.error("Error 400: %s", message[index]) raise ParseJSONError if resp.status == 401: _LOGGER.error("Authentication error: %s", message) @@ -552,7 +557,16 @@ def _version_check(self, min_version: str, max_version: str = "") -> bool: if max_version != "": limit = AwesomeVersion(max_version) + firmware_filtered = None + + try: + firmware_search = re.search("\\d\\.\\d\\.\\d", self._config["version"]) + if firmware_search is not None: + firmware_filtered = firmware_search[0] + except Exception: # pylint: disable=broad-exception-caught + _LOGGER.warning("Non-standard versioning string.") _LOGGER.debug("Detected firmware: %s", self._config["version"]) + _LOGGER.debug("Filtered firmware: %s", firmware_filtered) if "dev" in self._config["version"]: value = self._config["version"] @@ -562,7 +576,7 @@ def _version_check(self, min_version: str, max_version: str = "") -> bool: elif "master" in self._config["version"]: value = "dev" else: - value = self._config["version"] + value = firmware_filtered current = AwesomeVersion(value) diff --git a/tests/conftest.py b/tests/conftest.py index 73ac412..1ca45a3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -139,6 +139,22 @@ def test_charger_unknown_semver(mock_aioclient): return main.OpenEVSE(TEST_TLD) +@pytest.fixture(name="test_charger_modified_ver") +def test_charger_modified_ver(mock_aioclient): + """Load the charger data.""" + mock_aioclient.get( + TEST_URL_STATUS, + status=200, + body=load_fixture("v4_json/status.json"), + ) + mock_aioclient.get( + TEST_URL_CONFIG, + status=200, + body=load_fixture("v4_json/config-extra-version.json"), + ) + return main.OpenEVSE(TEST_TLD) + + @pytest.fixture(name="test_charger_v2") def test_charger_v2(mock_aioclient): """Load the charger data.""" diff --git a/tests/fixtures/v4_json/config-extra-version.json b/tests/fixtures/v4_json/config-extra-version.json new file mode 100644 index 0000000..fcbe0b5 --- /dev/null +++ b/tests/fixtures/v4_json/config-extra-version.json @@ -0,0 +1,66 @@ +{ + "firmware": "7.1.3", + "protocol": "-", + "espflash": 4194304, + "wifi_serial": "1234567890AB", + "version": "v5.0.1_modified", + "diodet": 0, + "gfcit": 0, + "groundt": 0, + "relayt": 0, + "ventt": 0, + "tempt": 0, + "service": 2, + "scale": 220, + "offset": 0, + "max_current_soft": 48, + "min_current_hard": 6, + "max_current_hard": 48, + "mqtt_supported_protocols": [ + "mqtt", + "mqtts" + ], + "http_supported_protocols": [ + "http", + "https" + ], + "ssid": "Datanode-IoT", + "pass": "_DUMMY_PASSWORD", + "www_username": "", + "www_password": "", + "hostname": "openevse-7b2c", + "sntp_hostname": "0.us.pool.ntp.org", + "time_zone": "America/Phoenix|MST7", + "emoncms_server": "https://emoncms.collective.lan/", + "emoncms_node": "openevse", + "emoncms_apikey": "_DUMMY_PASSWORD", + "emoncms_fingerprint": "", + "mqtt_server": "192.168.1.198", + "mqtt_port": 1883, + "mqtt_topic": "openevse", + "mqtt_user": "devices", + "mqtt_pass": "_DUMMY_PASSWORD", + "mqtt_solar": "", + "mqtt_grid_ie": "home-assistant/power/watts", + "mqtt_vrms": "home-assistant/solar/watts", + "mqtt_announce_topic": "openevse/announce/7b2c", + "ohm": "", + "divert_PV_ratio": 1.1, + "divert_attack_smoothing_factor": 0.4, + "divert_decay_smoothing_factor": 0.05, + "divert_min_charge_time": 600, + "tesla_username": "", + "tesla_password": "", + "tesla_vehidx": -1, + "led_brightness": 128, + "flags": 522, + "emoncms_enabled": false, + "mqtt_enabled": true, + "mqtt_reject_unauthorized": true, + "ohm_enabled": false, + "sntp_enabled": true, + "tesla_enabled": false, + "pause_uses_disabled": false, + "mqtt_protocol": "mqtt", + "charge_mode": "fast" + } diff --git a/tests/test_main.py b/tests/test_main.py index d7abb8b..c6d2009 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -647,7 +647,7 @@ async def test_toggle_override( test_charger, test_charger_dev, test_charger_new, - test_charger_unknown_semver, + test_charger_modified_ver, mock_aioclient, caplog, ): @@ -657,17 +657,19 @@ async def test_toggle_override( TEST_URL_OVERRIDE, status=200, body="OK", + repeat=True, + ) + mock_aioclient.post( + TEST_URL_OVERRIDE, + status=200, + body='{"msg": "OK"}', + repeat=True, ) with caplog.at_level(logging.DEBUG): await test_charger.toggle_override() assert "Toggling manual override http" in caplog.text await test_charger_dev.update() - mock_aioclient.patch( - TEST_URL_OVERRIDE, - status=200, - body="OK", - ) with caplog.at_level(logging.DEBUG): await test_charger_dev.toggle_override() assert "Stripping 'dev' from version." in caplog.text @@ -687,18 +689,7 @@ async def test_toggle_override( body=json.dumps(value), ) - mock_aioclient.post( - TEST_URL_OVERRIDE, - status=200, - body='{"msg": "OK"}', - ) - await test_charger_new.update() - mock_aioclient.patch( - TEST_URL_OVERRIDE, - status=200, - body="OK", - ) with caplog.at_level(logging.DEBUG): await test_charger_new.toggle_override() assert "Toggling manual override http" in caplog.text @@ -716,19 +707,31 @@ async def test_toggle_override( status=200, body=json.dumps(value), ) - mock_aioclient.post( - TEST_URL_OVERRIDE, - status=200, - body='{"msg": "OK"}', - ) - mock_aioclient.patch( + + with caplog.at_level(logging.DEBUG): + await test_charger_new.toggle_override() + assert "Toggling manual override http" in caplog.text + + await test_charger_modified_ver.update() + + value = { + "state": "disabled", + "charge_current": 0, + "max_current": 0, + "energy_limit": 0, + "time_limit": 0, + "auto_release": True, + } + mock_aioclient.get( TEST_URL_OVERRIDE, status=200, - body="OK", + body=json.dumps(value), ) + with caplog.at_level(logging.DEBUG): - await test_charger_new.toggle_override() - assert "Toggling manual override http" in caplog.text + await test_charger_modified_ver.toggle_override() + assert "Detected firmware: v5.0.1_modified" in caplog.text + assert "Filtered firmware: 5.0.1" in caplog.text async def test_toggle_override_v2(test_charger_v2, mock_aioclient, caplog):