From e5a7a3b5d0d3cfdc5b6664ce0ac76519e01d8088 Mon Sep 17 00:00:00 2001 From: RogerSelwyn Date: Sat, 26 Aug 2023 11:41:43 +0100 Subject: [PATCH 1/6] Add stop/start charge services --- custom_components/monta/binary_sensor.py | 31 ++++++++++++++++++-- custom_components/monta/services.yaml | 15 ++++++++++ custom_components/monta/translations/en.json | 10 +++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 custom_components/monta/services.yaml diff --git a/custom_components/monta/binary_sensor.py b/custom_components/monta/binary_sensor.py index eafdaa7..082ed6d 100644 --- a/custom_components/monta/binary_sensor.py +++ b/custom_components/monta/binary_sensor.py @@ -3,12 +3,14 @@ import logging -from homeassistant.helpers.entity import generate_entity_id +import voluptuous as vol from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, BinarySensorEntityDescription, ) +from homeassistant.helpers import entity_platform +from homeassistant.helpers.entity import generate_entity_id from .const import DOMAIN from .coordinator import MontaDataUpdateCoordinator @@ -40,6 +42,10 @@ async def async_setup_entry(hass, entry, async_add_devices): for entity_description in ENTITY_DESCRIPTIONS ) + platform = entity_platform.async_get_current_platform() + platform.async_register_entity_service("start_charge", {}, "start_charge") + platform.async_register_entity_service("stop_charge", {}, "stop_charge") + class MontaBinarySensor(MontaEntity, BinarySensorEntity): """monta binary_sensor class.""" @@ -63,4 +69,25 @@ def __init__( @property def is_on(self) -> bool: """Return true if the binary_sensor is on.""" - return self.coordinator.data[self.charge_point_id].get(self.entity_description.key, False) + return self.coordinator.data[self.charge_point_id].get( + self.entity_description.key, False + ) + + async def start_charge(self): + """Start charge.""" + if ( + self.coordinator.data[self.charge_point_id]["state"] == "available" + and self.coordinator.data[self.charge_point_id][self.entity_description.key] + ): + await self.coordinator.async_start_charge(self.charge_point_id) + return + + raise vol.Invalid("Charger not plugged in and available for charge") + + async def stop_charge(self): + """Stop charge.""" + if self.coordinator.data[self.charge_point_id]["state"].startswith("busy"): + await self.coordinator.async_stop_charge(self.charge_point_id) + return + + raise vol.Invalid("Charger not currently charging") diff --git a/custom_components/monta/services.yaml b/custom_components/monta/services.yaml new file mode 100644 index 0000000..03b6ca3 --- /dev/null +++ b/custom_components/monta/services.yaml @@ -0,0 +1,15 @@ +start_charge: + target: + device: + integration: monta + entity: + integration: monta + domain: binary_sensor + +stop_charge: + target: + device: + integration: monta + entity: + integration: monta + domain: binary_sensor diff --git a/custom_components/monta/translations/en.json b/custom_components/monta/translations/en.json index 4a2b336..2b877f0 100644 --- a/custom_components/monta/translations/en.json +++ b/custom_components/monta/translations/en.json @@ -14,5 +14,15 @@ "connection": "Unable to connect to the server.", "unknown": "Unknown error occurred." } + }, + "services": { + "start_charge": { + "description": "Start charge on selected charger", + "name": "Start Charge" + }, + "stop_charge": { + "description": "Stop charge on selected charger.", + "name": "Stop Charge" + } } } \ No newline at end of file From 51a10490e7cad0d3b250943b7d12d775448f2609 Mon Sep 17 00:00:00 2001 From: Nick Nissen Date: Mon, 25 Sep 2023 18:45:16 +0000 Subject: [PATCH 2/6] Refactor start/stop charge into its own module --- custom_components/monta/__init__.py | 4 ++ custom_components/monta/binary_sensor.py | 24 --------- custom_components/monta/services.py | 54 ++++++++++++++++++++ custom_components/monta/services.yaml | 28 +++++----- custom_components/monta/translations/en.json | 8 +-- 5 files changed, 76 insertions(+), 42 deletions(-) create mode 100644 custom_components/monta/services.py diff --git a/custom_components/monta/__init__.py b/custom_components/monta/__init__.py index a3afa13..1b03eac 100644 --- a/custom_components/monta/__init__.py +++ b/custom_components/monta/__init__.py @@ -14,6 +14,7 @@ from .api import MontaApiClient from .const import DOMAIN, STORAGE_KEY, STORAGE_VERSION from .coordinator import MontaDataUpdateCoordinator +from .services import async_setup_services PLATFORMS: list[Platform] = [ Platform.SENSOR, @@ -39,6 +40,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await coordinator.async_config_entry_first_refresh() await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + + await async_setup_services(hass, entry) + entry.async_on_unload(entry.add_update_listener(async_reload_entry)) return True diff --git a/custom_components/monta/binary_sensor.py b/custom_components/monta/binary_sensor.py index 082ed6d..9824175 100644 --- a/custom_components/monta/binary_sensor.py +++ b/custom_components/monta/binary_sensor.py @@ -3,7 +3,6 @@ import logging -import voluptuous as vol from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, @@ -42,10 +41,6 @@ async def async_setup_entry(hass, entry, async_add_devices): for entity_description in ENTITY_DESCRIPTIONS ) - platform = entity_platform.async_get_current_platform() - platform.async_register_entity_service("start_charge", {}, "start_charge") - platform.async_register_entity_service("stop_charge", {}, "stop_charge") - class MontaBinarySensor(MontaEntity, BinarySensorEntity): """monta binary_sensor class.""" @@ -72,22 +67,3 @@ def is_on(self) -> bool: return self.coordinator.data[self.charge_point_id].get( self.entity_description.key, False ) - - async def start_charge(self): - """Start charge.""" - if ( - self.coordinator.data[self.charge_point_id]["state"] == "available" - and self.coordinator.data[self.charge_point_id][self.entity_description.key] - ): - await self.coordinator.async_start_charge(self.charge_point_id) - return - - raise vol.Invalid("Charger not plugged in and available for charge") - - async def stop_charge(self): - """Stop charge.""" - if self.coordinator.data[self.charge_point_id]["state"].startswith("busy"): - await self.coordinator.async_stop_charge(self.charge_point_id) - return - - raise vol.Invalid("Charger not currently charging") diff --git a/custom_components/monta/services.py b/custom_components/monta/services.py new file mode 100644 index 0000000..da92d56 --- /dev/null +++ b/custom_components/monta/services.py @@ -0,0 +1,54 @@ +"""Monta components services.""" + +import logging +from collections.abc import Awaitable, Callable + +import voluptuous as vol +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, ServiceCall + +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + +TServiceHandler = Callable[[ServiceCall], Awaitable[None]] + +has_id_schema = vol.Schema({vol.Required("charge_point_id"): int}) + + +async def async_setup_services(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Set up services for the Monta component.""" + + _LOGGER.debug("Set up services") + + coordinator = hass.data[DOMAIN][entry.entry_id] + + async def service_handle_stop_charging(service_call: ServiceCall) -> None: + charge_point_id = service_call.data["charge_point_id"] + _LOGGER.debug("Called stop charging for %s", charge_point_id) + + if coordinator.data[charge_point_id]["state"].startswith("busy"): + await coordinator.async_stop_charge(charge_point_id) + return + + raise vol.Invalid("Charger not currently charging") + + async def service_handle_start_charging(service_call: ServiceCall) -> None: + charge_point_id = service_call.data["charge_point_id"] + _LOGGER.debug("Called start charging for %s", charge_point_id) + + if coordinator.data[charge_point_id]["state"] == "available": + await coordinator.async_start_charge(charge_point_id) + return + + raise vol.Invalid("Charger not currently charging") + + # LIST OF SERVICES + services: list[tuple[str, vol.Schema, TServiceHandler]] = [ + ("start_charging", has_id_schema, service_handle_start_charging), + ("stop_charging", has_id_schema, service_handle_stop_charging), + ] + + # Register the services + for name, schema, handler in services: + hass.services.async_register(DOMAIN, name, handler, schema=schema) diff --git a/custom_components/monta/services.yaml b/custom_components/monta/services.yaml index 03b6ca3..dee52e8 100644 --- a/custom_components/monta/services.yaml +++ b/custom_components/monta/services.yaml @@ -1,15 +1,15 @@ -start_charge: - target: - device: - integration: monta - entity: - integration: monta - domain: binary_sensor +start_charging: + description: "Start charging" + fields: + charge_point_id: + required: true + description: "The charger point id" + example: 1234 -stop_charge: - target: - device: - integration: monta - entity: - integration: monta - domain: binary_sensor +stop_charging: + description: "Stop charging" + fields: + charge_point_id: + required: true + description: "The charger point id" + example: 1234 diff --git a/custom_components/monta/translations/en.json b/custom_components/monta/translations/en.json index 2b877f0..5242c5f 100644 --- a/custom_components/monta/translations/en.json +++ b/custom_components/monta/translations/en.json @@ -16,13 +16,13 @@ } }, "services": { - "start_charge": { + "start_charging": { "description": "Start charge on selected charger", - "name": "Start Charge" + "name": "Start charging" }, - "stop_charge": { + "stop_charging": { "description": "Stop charge on selected charger.", - "name": "Stop Charge" + "name": "Stop charging" } } } \ No newline at end of file From e5cef5614fd18b8d223145fdd3b96c62029a2016 Mon Sep 17 00:00:00 2001 From: Nick Nissen Date: Mon, 25 Sep 2023 19:05:35 +0000 Subject: [PATCH 3/6] [rufffix] Remove unused import --- custom_components/monta/binary_sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/monta/binary_sensor.py b/custom_components/monta/binary_sensor.py index 9824175..7b5bdef 100644 --- a/custom_components/monta/binary_sensor.py +++ b/custom_components/monta/binary_sensor.py @@ -8,7 +8,7 @@ BinarySensorEntity, BinarySensorEntityDescription, ) -from homeassistant.helpers import entity_platform + from homeassistant.helpers.entity import generate_entity_id from .const import DOMAIN From 20b162150086ce1b2f30fe8be1c4fb200114c77a Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Sep 2023 13:12:15 +0200 Subject: [PATCH 4/6] Added missing translations --- custom_components/monta/translations/en.json | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/custom_components/monta/translations/en.json b/custom_components/monta/translations/en.json index 5242c5f..cac0a0e 100644 --- a/custom_components/monta/translations/en.json +++ b/custom_components/monta/translations/en.json @@ -18,11 +18,21 @@ "services": { "start_charging": { "description": "Start charge on selected charger", - "name": "Start charging" + "name": "Start charging", + "fields": { + "charge_point_id": { + "name": "Charge point id", + "description": "The ID of the charger." + } }, "stop_charging": { "description": "Stop charge on selected charger.", - "name": "Stop charging" + "name": "Stop charging", + "fields": { + "charge_point_id": { + "name": "Charge point id", + "description": "The ID of the charger." + } } } -} \ No newline at end of file +} From a8aa1b58db7dd7ac2265ceaf7239d101ee069415 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Sep 2023 13:17:01 +0200 Subject: [PATCH 5/6] Fix json syntax error --- custom_components/monta/translations/en.json | 75 ++++++++++---------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/custom_components/monta/translations/en.json b/custom_components/monta/translations/en.json index cac0a0e..ec64638 100644 --- a/custom_components/monta/translations/en.json +++ b/custom_components/monta/translations/en.json @@ -1,38 +1,41 @@ { - "config": { - "step": { - "user": { - "description": "Client id and secret are obtained from https://portal2.monta.app/applications", - "data": { - "client_id": "Client id", - "client_secret": "client secret" - } - } - }, - "error": { - "auth": "Client id/client secret is wrong.", - "connection": "Unable to connect to the server.", - "unknown": "Unknown error occurred." - } - }, - "services": { - "start_charging": { - "description": "Start charge on selected charger", - "name": "Start charging", - "fields": { - "charge_point_id": { - "name": "Charge point id", - "description": "The ID of the charger." - } - }, - "stop_charging": { - "description": "Stop charge on selected charger.", - "name": "Stop charging", - "fields": { - "charge_point_id": { - "name": "Charge point id", - "description": "The ID of the charger." - } - } - } + "config": { + "step": { + "user": { + "description": "Client id and secret are obtained from https://portal2.monta.app/applications", + "data": { + "client_id": "Client id", + "client_secret": "client secret" + } + } + }, + "error": { + "auth": "Client id/client secret is wrong.", + "connection": "Unable to connect to the server.", + "unknown": "Unknown error occurred." + } + }, + "services": { + "start_charging": { + "description": "Start charge on selected charger", + "name": "Start charging", + "fields": { + "charge_point_id": { + "name": "Charge point id", + "description": "The ID of the charger." + } + + }, + "stop_charging": { + "description": "Stop charge on selected charger.", + "name": "Stop charging", + "fields": { + "charge_point_id": { + "name": "Charge point id", + "description": "The ID of the charger." + } + } + } + } + } } From 7c451f39bc3334c11b0cbbc898d537fd91e8a628 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 26 Sep 2023 13:19:36 +0200 Subject: [PATCH 6/6] More fixing --- custom_components/monta/translations/en.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/custom_components/monta/translations/en.json b/custom_components/monta/translations/en.json index ec64638..93b05f1 100644 --- a/custom_components/monta/translations/en.json +++ b/custom_components/monta/translations/en.json @@ -25,15 +25,15 @@ "description": "The ID of the charger." } - }, - "stop_charging": { - "description": "Stop charge on selected charger.", - "name": "Stop charging", - "fields": { - "charge_point_id": { - "name": "Charge point id", - "description": "The ID of the charger." - } + } + }, + "stop_charging": { + "description": "Stop charge on selected charger.", + "name": "Stop charging", + "fields": { + "charge_point_id": { + "name": "Charge point id", + "description": "The ID of the charger." } } }