Skip to content

Commit

Permalink
feat: create async_charge_current to parse the charge_current (#391)
Browse files Browse the repository at this point in the history
* feat: create async_charge_current to parse the charge_current

* update tests

* update tests

* formatting

* more test updates

* adjust list claims to check claims target endpoint
  • Loading branch information
firstof9 authored Nov 19, 2024
1 parent baa5882 commit 3b17141
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 5 deletions.
22 changes: 20 additions & 2 deletions openevsehttp/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,13 +815,17 @@ async def release_claim(self, client: int = CLIENT) -> Any:
response = await self.process_request(url=url, method="delete") # noqa: E501
return response

async def list_claims(self) -> Any:
async def list_claims(self, target: bool | None = None) -> Any:
"""List all claims."""
if not self._version_check("4.1.0"):
_LOGGER.debug("Feature not supported for older firmware.")
raise UnsupportedFeature

url = f"{self.url}claims"
target_check = ""
if target:
target_check = "/target"

url = f"{self.url}claims{target_check}"

_LOGGER.debug("Getting claims on %s", url)
response = await self.process_request(url=url, method="get") # noqa: E501
Expand Down Expand Up @@ -922,6 +926,20 @@ def max_current_soft(self) -> int | None:
return self._config["max_current_soft"]
return self._status["pilot"]

@property
async def async_charge_current(self) -> int | None:
"""Return the charge current."""
try:
claims = None
claims = await self.list_claims(target=True)
except UnsupportedFeature:
pass
if claims is not None and "charge_current" in claims["properties"].keys():
return claims["properties"]["charge_current"]
if self._config is not None and "max_current_soft" in self._config:
return self._config["max_current_soft"]
return self._status["pilot"]

@property
def max_current(self) -> int | None:
"""Return the max current."""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

PROJECT_DIR = Path(__file__).parent.resolve()
README_FILE = PROJECT_DIR / "README.md"
VERSION = "0.1.63"
VERSION = "0.1.64"

setup(
name="python-openevse-http",
Expand Down
25 changes: 25 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
TEST_URL_STATUS = "http://openevse.test.tld/status"
TEST_URL_CONFIG = "http://openevse.test.tld/config"
TEST_URL_RAPI = "http://openevse.test.tld/r"
TEST_URL_WS = "ws://openevse.test.tld/ws"
TEST_TLD = "openevse.test.tld"


Expand All @@ -27,6 +28,12 @@ def test_charger_auth(mock_aioclient):
status=200,
body=load_fixture("v4_json/config.json"),
)
mock_aioclient.get(
TEST_URL_WS,
status=200,
body=load_fixture("v4_json/status.json"),
repeat=True,
)
return main.OpenEVSE(TEST_TLD, user="testuser", pwd="fakepassword")


Expand Down Expand Up @@ -57,6 +64,12 @@ def test_charger(mock_aioclient):
status=200,
body=load_fixture("v4_json/config.json"),
)
mock_aioclient.get(
TEST_URL_WS,
status=200,
body=load_fixture("v4_json/status.json"),
repeat=True,
)
return main.OpenEVSE(TEST_TLD)


Expand All @@ -73,6 +86,12 @@ def test_charger_dev(mock_aioclient):
status=200,
body=load_fixture("v4_json/config-dev.json"),
)
mock_aioclient.get(
TEST_URL_WS,
status=200,
body=load_fixture("v4_json/status.json"),
repeat=True,
)
return main.OpenEVSE(TEST_TLD)


Expand All @@ -89,6 +108,12 @@ def test_charger_new(mock_aioclient):
status=200,
body=load_fixture("v4_json/config-new.json"),
)
mock_aioclient.get(
TEST_URL_WS,
status=200,
body=load_fixture("v4_json/status-new.json"),
repeat=True,
)
return main.OpenEVSE(TEST_TLD)


Expand Down
69 changes: 67 additions & 2 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
UnsupportedFeature,
)
from tests.common import load_fixture
from openevsehttp.websocket import SIGNAL_CONNECTION_STATE, STATE_CONNECTED

pytestmark = pytest.mark.asyncio

Expand All @@ -31,6 +32,7 @@
TEST_URL_LIMIT = "http://openevse.test.tld/limit"
TEST_URL_WS = "ws://openevse.test.tld/ws"
TEST_URL_CLAIMS = "http://openevse.test.tld/claims"
TEST_URL_CLAIMS_TARGET = "http://openevse.test.tld/claims/target"
TEST_URL_GITHUB_v4 = (
"https://api.github.com/repos/OpenEVSE/ESP32_WiFi_V4.x/releases/latest"
)
Expand All @@ -46,6 +48,20 @@ async def test_get_status_auth(test_charger_auth):
assert status == "sleeping"


async def test_ws_state(test_charger):
"""Test v4 Status reply."""
await test_charger.update()
value = test_charger.ws_state
assert value == None


async def test_update_status(test_charger):
"""Test v4 Status reply."""
data = json.loads(load_fixture("v4_json/status.json"))
await test_charger._update_status("data", data, None)
assert test_charger._status == data


async def test_get_status_auth_err(test_charger_auth_err):
"""Test v4 Status reply."""
with pytest.raises(main.AuthenticationError):
Expand Down Expand Up @@ -110,6 +126,13 @@ async def test_send_command_parse_err(test_charger_auth, mock_aioclient):
status = await test_charger_auth.send_command("test")
assert status is None

mock_aioclient.post(
TEST_URL_RAPI, status=400, body='{"error": "Could not parse JSON"}'
)
with pytest.raises(main.ParseJSONError):
status = await test_charger_auth.send_command("test")
assert status is None


async def test_send_command_auth_err(test_charger_auth, mock_aioclient):
"""Test v4 Status reply."""
Expand Down Expand Up @@ -947,7 +970,7 @@ async def test_test_and_get(test_charger, test_charger_v2, mock_aioclient, caplo
assert "Older firmware detected, missing serial." in caplog.text


async def test_restart(test_charger_modified_ver, mock_aioclient, caplog):
async def test_restart_wifi(test_charger_modified_ver, mock_aioclient, caplog):
"""Test v4 set divert mode."""
await test_charger_modified_ver.update()
mock_aioclient.post(
Expand Down Expand Up @@ -1057,7 +1080,9 @@ async def test_firmware_check(
assert firmware is None


async def test_evse_restart(test_charger_v2, mock_aioclient, caplog):
async def test_evse_restart(
test_charger_v2, test_charger_modified_ver, mock_aioclient, caplog
):
"""Test EVSE module restart."""
await test_charger_v2.update()
value = {"cmd": "OK", "ret": "$OK^20"}
Expand All @@ -1070,6 +1095,16 @@ async def test_evse_restart(test_charger_v2, mock_aioclient, caplog):
await test_charger_v2.restart_evse()
assert "EVSE Restart response: $OK^20" in caplog.text

await test_charger_modified_ver.update()
mock_aioclient.post(
TEST_URL_RESTART,
status=200,
body='{"msg": "restart evse"}',
)
with caplog.at_level(logging.DEBUG):
await test_charger_modified_ver.restart_evse()
assert "Restarting EVSE module via HTTP" in caplog.text


@pytest.mark.parametrize(
"fixture, expected", [("test_charger", True), ("test_charger_v2", None)]
Expand Down Expand Up @@ -1869,3 +1904,33 @@ async def test_set_led_brightness(
with caplog.at_level(logging.DEBUG):
await test_charger_v2.set_led_brightness(255)
assert "Feature not supported for older firmware." in caplog.text


async def test_async_charge_current(
test_charger, test_charger_v2, mock_aioclient, caplog
):
"""Test async_charge_current function."""
await test_charger.update()
mock_aioclient.get(
TEST_URL_CLAIMS_TARGET,
status=200,
body='{"properties":{"state":"disabled","charge_current":28,"max_current":23,"auto_release":false},"claims":{"state":65540,"charge_current":65537,"max_current":65548}}',
repeat=False,
)

value = await test_charger.async_charge_current
assert value == 28

mock_aioclient.get(
TEST_URL_CLAIMS_TARGET,
status=200,
body='{"properties":{"state":"disabled","max_current":23,"auto_release":false},"claims":{"state":65540,"charge_current":65537,"max_current":65548}}',
repeat=False,
)

value = await test_charger.async_charge_current
assert value == 48

await test_charger_v2.update()
value = await test_charger_v2.async_charge_current
assert value == 25

0 comments on commit 3b17141

Please sign in to comment.