Skip to content

Commit

Permalink
fix: toggle_override adjustments for firmware > 4.1.7 (#194)
Browse files Browse the repository at this point in the history
* fix: toggle_override adjustments for firmware > 4.1.7

* more test coverage

* more coverage
  • Loading branch information
firstof9 committed Mar 6, 2023
1 parent 5c36c78 commit 65bbc18
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 4 deletions.
27 changes: 24 additions & 3 deletions openevsehttp/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import datetime
import json
import logging
from typing import Any, Callable, Union, Dict
from typing import Any, Callable, Dict, Union

import aiohttp # type: ignore
from aiohttp.client_exceptions import ContentTypeError, ServerTimeoutError
Expand Down Expand Up @@ -358,12 +358,26 @@ async def toggle_override(self) -> None:
"""Toggle the manual override status."""
# 3.x: use RAPI commands $FE (enable) and $FS (sleep)
# 4.x: use HTTP API call
if self._version_check("4.0.0"):
lower = "4.0.0"
upper = "4.1.7"
if self._version_check(lower, upper):
url = f"{self.url}override"

_LOGGER.debug("Toggling manual override %s", url)
response = await self.process_request(url=url, method="patch")
_LOGGER.debug("Toggle response: %s", response)
# Firmware > 4.1.7 use alternative method
elif self._version_check(upper):
_LOGGER.debug("Checking override status.")
override = await self.get_override()
if override["state"] == "active":
_LOGGER.debug("Disabling override.")
result = await self.set_override("disabled")
_LOGGER.debug("Disable response: %s", result)
else:
_LOGGER.debug("Enabling override.")
result = await self.set_override("active")
_LOGGER.debug("Enable response: %s", result)
else:
# Older firmware use RAPI commands
_LOGGER.debug("Toggling manual override via RAPI")
Expand Down Expand Up @@ -480,14 +494,17 @@ async def firmware_check(self) -> dict | None:
response["release_url"] = message["html_url"]
return response

def _version_check(self, min_version: str) -> bool:
def _version_check(self, min_version: str, max_version: str = "") -> bool:
"""Return bool if minimum version is met."""
if "version" not in self._config:
# Throw warning if we can't find the version
_LOGGER.warning("Unable to find firmware version.")
return False
cutoff = AwesomeVersion(min_version)
current = ""
limit = ""
if max_version != "":
limit = AwesomeVersion(max_version)

_LOGGER.debug("Detected firmware: %s", self._config["version"])

Expand All @@ -500,6 +517,10 @@ def _version_check(self, min_version: str) -> bool:
else:
current = AwesomeVersion(self._config["version"])

if limit:
if cutoff <= current <= limit:
return True
return False
if current >= cutoff:
return True
return False
Expand Down
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ def test_charger_dev(mock_aioclient):
return main.OpenEVSE(TEST_TLD)


@pytest.fixture(name="test_charger_new")
def test_charger_new(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-new.json"),
)
return main.OpenEVSE(TEST_TLD)


@pytest.fixture(name="test_charger_broken")
def test_charger_broken(mock_aioclient):
"""Load the charger data."""
Expand Down
67 changes: 67 additions & 0 deletions tests/fixtures/v4_json/config-new.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"firmware": "7.1.3",
"protocol": "-",
"espflash": 4194304,
"wifi_serial": "1234567890AB",
"version": "4.1.8",
"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,
"divert_enabled": true,
"pause_uses_disabled": false,
"mqtt_protocol": "mqtt",
"charge_mode": "fast"
}
63 changes: 62 additions & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,9 @@ async def test_get_manual_override(fixture, expected, request):
# assert status == expected


async def test_toggle_override(test_charger, test_charger_dev, mock_aioclient, caplog):
async def test_toggle_override(
test_charger, test_charger_dev, test_charger_new, mock_aioclient, caplog
):
"""Test v4 Status reply."""
await test_charger.update()
mock_aioclient.patch(
Expand All @@ -649,6 +651,65 @@ async def test_toggle_override(test_charger, test_charger_dev, mock_aioclient, c
assert "Stripping 'dev' from version." in caplog.text
assert "Toggling manual override http" in caplog.text

value = {
"state": "active",
"charge_current": 0,
"max_current": 0,
"energy_limit": 0,
"time_limit": 0,
"auto_release": True,
}
mock_aioclient.get(
TEST_URL_OVERRIDE,
status=200,
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 "Checking override status." in caplog.text
assert "Disabling override." in caplog.text
assert "Toggling manual override http" in caplog.text

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=json.dumps(value),
)
mock_aioclient.post(
TEST_URL_OVERRIDE,
status=200,
body='{"msg": "OK"}',
)
mock_aioclient.patch(
TEST_URL_OVERRIDE,
status=200,
body="OK",
)
with caplog.at_level(logging.DEBUG):
await test_charger_new.toggle_override()
assert "Enabling override." in caplog.text


async def test_toggle_override_v2(test_charger_v2, mock_aioclient, caplog):
"""Test v4 Status reply."""
Expand Down

0 comments on commit 65bbc18

Please sign in to comment.