From fd6f0ac35b16b26dd0f1e062f422d2a0e64359ad Mon Sep 17 00:00:00 2001 From: Nathan Marlor Date: Fri, 27 Jan 2023 07:45:34 +0000 Subject: [PATCH] Fixes before release --- README.md | 4 + custom_components/foxess_em/__init__.py | 5 +- custom_components/foxess_em/const.py | 2 +- .../foxess_em/forecast/forecast_controller.py | 10 +- .../foxess_em/fox/fox_cloud_service.py | 92 +++++++++++-------- 5 files changed, 68 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index d0cc0c8..deb4e5d 100755 --- a/README.md +++ b/README.md @@ -182,6 +182,10 @@ Battery = blue / Load = pink / Solar = orange / Grid = green
Service Calls +- Start force charge now +- Start force charge at off-peak +- Stop force charge + ![Service](images/service.png)

diff --git a/custom_components/foxess_em/__init__.py b/custom_components/foxess_em/__init__.py index ddc2ead..40cdfad 100755 --- a/custom_components/foxess_em/__init__.py +++ b/custom_components/foxess_em/__init__.py @@ -130,7 +130,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): average_controller.add_update_listener(battery_controller) hass.services.async_register( - DOMAIN, "start_force_charge", fox_service.start_force_charge_now + DOMAIN, "start_force_charge_now", fox_service.start_force_charge_now + ) + hass.services.async_register( + DOMAIN, "start_force_charge_off_peak", fox_service.start_force_charge_off_peak ) hass.services.async_register( DOMAIN, "stop_force_charge", fox_service.stop_force_charge diff --git a/custom_components/foxess_em/const.py b/custom_components/foxess_em/const.py index 5de110c..8ebe9e3 100755 --- a/custom_components/foxess_em/const.py +++ b/custom_components/foxess_em/const.py @@ -3,7 +3,7 @@ NAME = "foxess_em" DOMAIN = "foxess_em" DOMAIN_DATA = f"{DOMAIN}_data" -VERSION = "1.6.0b3" +VERSION = "1.6.0" ISSUE_URL = "https://github.com/nathanmarlor/foxess_em/issues" diff --git a/custom_components/foxess_em/forecast/forecast_controller.py b/custom_components/foxess_em/forecast/forecast_controller.py index a159d7a..f1ad6e4 100755 --- a/custom_components/foxess_em/forecast/forecast_controller.py +++ b/custom_components/foxess_em/forecast/forecast_controller.py @@ -64,12 +64,14 @@ async def _setup_refresh(self, *args): now.replace(hour=_START_HOUR, minute=0, second=0, microsecond=0).time() ) - if api_available == 0 or now > default_end: - return - - if now < default_start: # default first refresh is used + # default first refresh is used + if now < default_start: api_available -= 1 + # no api calls left or somehow landed after the final refresh + if api_available < 1 or now > default_end: + return + minutes_diff = int((default_end - actual_start).seconds / 60) interval = int(minutes_diff / api_available) for i in range(1, api_available + 1): diff --git a/custom_components/foxess_em/fox/fox_cloud_service.py b/custom_components/foxess_em/fox/fox_cloud_service.py index e925c60..16991e1 100755 --- a/custom_components/foxess_em/fox/fox_cloud_service.py +++ b/custom_components/foxess_em/fox/fox_cloud_service.py @@ -46,7 +46,7 @@ async def start_force_charge_now(self, *args) -> None: stop = now.replace(hour=23, minute=59).time() device_sn = await self.device_serial_number() - query = self._build_single_charge_query(device_sn, True, start, stop) + query = self._build_start_single_charge_query(device_sn, start, stop) await self._start_force_charge(query) @@ -55,22 +55,16 @@ async def start_force_charge_off_peak(self, *args) -> None: device_sn = await self.device_serial_number() if self._off_peak_start > self._off_peak_end: # Off-peak period crosses midnight - before_midnight = time(hour=23, minute=59) - after_midnight = time(hour=0, minute=1) - query = self._build_double_charge_query( + query = self._build_start_double_charge_query( device_sn, - True, self._off_peak_start, - before_midnight, - after_midnight, self._off_peak_end, ) else: - query = self._build_single_charge_query( + query = self._build_start_single_charge_query( device_sn, - True, self._off_peak_start, self._off_peak_end, ) @@ -96,12 +90,7 @@ async def stop_force_charge(self, *args) -> None: # pylint: disable=unused-argu try: device_sn = await self.device_serial_number() - query = self._build_single_charge_query( - device_sn, - False, - self._off_peak_start, - self._off_peak_end, - ) + query = self._build_stop_charge_query(device_sn) await self._api.async_post_data( f"{_BASE_URL}{_SET_TIMES}", @@ -148,18 +137,43 @@ def _build_min_soc_query(self, device_sn: str, soc: int) -> dict: """Build min SoC query object""" return {"sn": device_sn, "minGridSoc": soc, "minSoc": self._user_min_soc * 100} - def _build_single_charge_query( - self, device_sn: str, start_stop: bool, start_time: time, end_time: time + def _build_stop_charge_query(self, device_sn: str) -> dict: + """Build stop charge query""" + + query = { + "sn": device_sn, + "times": [ + { + "tip": "", + "enableCharge": False, + "enableGrid": False, + "startTime": {"hour": 0, "minute": 0}, + "endTime": {"hour": 0, "minute": 0}, + }, + { + "tip": "", + "enableCharge": False, + "enableGrid": False, + "startTime": {"hour": 0, "minute": 0}, + "endTime": {"hour": 0, "minute": 0}, + }, + ], + } + + return query + + def _build_start_single_charge_query( + self, device_sn: str, start_time: time, end_time: time ) -> dict: - """Build device query object""" + """Build single time charg query""" query = { "sn": device_sn, "times": [ { "tip": "", - "enableCharge": start_stop, - "enableGrid": start_stop, + "enableCharge": True, + "enableGrid": True, "startTime": { "hour": str(start_time.hour).zfill(2), "minute": str(start_time.minute).zfill(2), @@ -181,44 +195,44 @@ def _build_single_charge_query( return query - def _build_double_charge_query( + def _build_start_double_charge_query( self, device_sn: str, - start_stop: bool, - first_start_time: time, - first_end_time: time, - second_start_time: time, - second_end_time: time, + start_time: time, + stop_time: time, ) -> dict: - """Build device query object""" + """Build double time charge query""" + + before_midnight = time(hour=23, minute=59) + after_midnight = time(hour=0, minute=1) query = { "sn": device_sn, "times": [ { "tip": "", - "enableCharge": start_stop, - "enableGrid": start_stop, + "enableCharge": True, + "enableGrid": True, "startTime": { - "hour": str(first_start_time.hour).zfill(2), - "minute": str(first_start_time.minute).zfill(2), + "hour": str(start_time.hour).zfill(2), + "minute": str(start_time.minute).zfill(2), }, "endTime": { - "hour": str(first_end_time.hour).zfill(2), - "minute": str(first_end_time.minute).zfill(2), + "hour": str(before_midnight.hour).zfill(2), + "minute": str(before_midnight.minute).zfill(2), }, }, { "tip": "", - "enableCharge": start_stop, - "enableGrid": start_stop, + "enableCharge": True, + "enableGrid": True, "startTime": { - "hour": str(second_start_time.hour).zfill(2), - "minute": str(second_start_time.minute).zfill(2), + "hour": str(after_midnight.hour).zfill(2), + "minute": str(after_midnight.minute).zfill(2), }, "endTime": { - "hour": str(second_end_time.hour).zfill(2), - "minute": str(second_end_time.minute).zfill(2), + "hour": str(stop_time.hour).zfill(2), + "minute": str(stop_time.minute).zfill(2), }, }, ],