From 8e9bc3124ec4b750151c6869c39ced881cf7b8fc Mon Sep 17 00:00:00 2001 From: fifipil909 <36625767+fifipil909@users.noreply.github.com> Date: Fri, 10 Mar 2023 23:32:24 +0100 Subject: [PATCH] [renault] Add channel for pausing/resuming charging (#14527) * Adding Pause-Resume Endpoint Signed-off-by: fifipil909 --- bundles/org.openhab.binding.renault/README.md | 5 ++++ .../internal/RenaultBindingConstants.java | 1 + .../binding/renault/internal/api/Car.java | 9 +++++++ .../internal/api/MyRenaultHttpSession.java | 10 +++++++ .../internal/handler/RenaultHandler.java | 26 +++++++++++++++++++ .../resources/OH-INF/i18n/renault.properties | 1 + .../resources/OH-INF/thing/thing-types.xml | 7 +++++ 7 files changed, 59 insertions(+) diff --git a/bundles/org.openhab.binding.renault/README.md b/bundles/org.openhab.binding.renault/README.md index 0f4eb18adc7..66352f27377 100644 --- a/bundles/org.openhab.binding.renault/README.md +++ b/bundles/org.openhab.binding.renault/README.md @@ -37,6 +37,7 @@ You require your MyRenault credential, locale and VIN for your MyRenault registe | batterylevel | Number | State of the battery in % | Yes | | batterystatusupdated | DateTime | Timestamp of the last battery status update | Yes | | chargingmode | String | Charging mode. always_charging or schedule_mode | No | +| pause | Switch | Pause the charge. | No | | chargingstatus | String | Charging status | Yes | | chargingremainingtime | Number:Time | Charging time remaining | Yes | | plugstatus | String | Status of charging plug | Yes | @@ -59,6 +60,9 @@ The "externaltemperature" only works on a few cars. The "hvactargettemperature" is used by the hvacstatus ON command for pre-conditioning the car. This seams to only allow values 19, 20 and 21 or else the pre-conditioning command will not work. +The 'pause' and 'chargingmode' may not work on some cars. +As an example, 'chargingmode' does not work on Dacia Spring cars. + The Kamereon API Key changes periodically, which causes a communication error. To fix this error update the API Key in the bindings configuration. The new key value can hopefully be found in the renault-api project: [KAMEREON_APIKEY value](https://github.com/hacf-fr/renault-api/blob/main/src/renault_api/const.py) or in the openHAB forums. @@ -77,6 +81,7 @@ sitemap renaultcar label="Renault Car" { Default icon="poweroutlet" item=RenaultCar_PlugStatus Default icon="switch" item=RenaultCar_ChargingStatus Selection icon="switch" item=RenaultCar_ChargingMode mappings=[SCHEDULE_MODE="Schedule mode",ALWAYS_CHARGING="Instant charge"] + Default icon="switch" item=RenaultCar_Pause Default item=RenaultCar_ChargingTimeRemaining Default icon="pressure" item=RenaultCar_EstimatedRange Default icon="pressure" item=RenaultCar_Odometer diff --git a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/RenaultBindingConstants.java b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/RenaultBindingConstants.java index 3333eaee404..a887217983d 100644 --- a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/RenaultBindingConstants.java +++ b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/RenaultBindingConstants.java @@ -34,6 +34,7 @@ public class RenaultBindingConstants { public static final String CHANNEL_BATTERY_LEVEL = "batterylevel"; public static final String CHANNEL_BATTERY_STATUS_UPDATED = "batterystatusupdated"; public static final String CHANNEL_CHARGING_MODE = "chargingmode"; + public static final String CHANNEL_PAUSE = "pause"; public static final String CHANNEL_CHARGING_STATUS = "chargingstatus"; public static final String CHANNEL_CHARGING_REMAINING_TIME = "chargingremainingtime"; public static final String CHANNEL_ESTIMATED_RANGE = "estimatedrange"; diff --git a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/Car.java b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/Car.java index e712ea3ef89..0d08fa13aac 100644 --- a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/Car.java +++ b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/Car.java @@ -45,6 +45,7 @@ public class Car { private boolean disableHvac = false; private boolean disableLockStatus = false; + private boolean pausemode = false; private ChargingStatus chargingStatus = ChargingStatus.UNKNOWN; private ChargingMode chargingMode = ChargingMode.UNKNOWN; private PlugStatus plugStatus = PlugStatus.UNKNOWN; @@ -298,6 +299,10 @@ public class Car { return chargingMode; } + public boolean getPauseMode() { + return pausemode; + } + public @Nullable Integer getChargingRemainingTime() { return chargingRemainingTime; } @@ -346,6 +351,10 @@ public class Car { } } + public void setPauseMode(boolean pausemode) { + this.pausemode = pausemode; + } + private @Nullable JsonObject getAttributes(JsonObject responseJson) throws IllegalStateException, ClassCastException { if (responseJson.get("data") != null && responseJson.get("data").getAsJsonObject().get("attributes") != null) { diff --git a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/MyRenaultHttpSession.java b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/MyRenaultHttpSession.java index 8d31d3b26e5..98de8383e78 100644 --- a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/MyRenaultHttpSession.java +++ b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/api/MyRenaultHttpSession.java @@ -274,6 +274,16 @@ public class MyRenaultHttpSession { "{\"data\":{\"type\":\"ChargeMode\",\"attributes\":{\"action\":\"" + apiMode + "\"}}}"); } + public void actionPause(boolean mode) + throws RenaultForbiddenException, RenaultNotImplementedException, RenaultActionException { + + final String apiMode = mode ? "pause" : "resume"; + final String path = "/commerce/v1/accounts/" + kamereonaccountId + "/kamereon/kcm/v1/vehicles/" + config.vin + + "/charge/pause-resume?country=" + getCountry(config); + postKamereonRequest(path, + "{\"data\":{\"type\":\"ChargePauseResume\",\"attributes\":{\"action\":\"" + apiMode + "\"}}}"); + } + private void postKamereonRequest(final String path, final String content) throws RenaultForbiddenException, RenaultNotImplementedException, RenaultActionException { Request request = httpClient.newRequest(this.constants.getKamereonRootUrl() + path).method(HttpMethod.POST) diff --git a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/handler/RenaultHandler.java b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/handler/RenaultHandler.java index 7484c173feb..5f2420a70bd 100644 --- a/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/handler/RenaultHandler.java +++ b/bundles/org.openhab.binding.renault/src/main/java/org/openhab/binding/renault/internal/handler/RenaultHandler.java @@ -205,6 +205,32 @@ public class RenaultHandler extends BaseThingHandler { } } break; + case RenaultBindingConstants.CHANNEL_PAUSE: + if (command instanceof RefreshType) { + reschedulePollingJob(); + } else if (command instanceof OnOffType) { + try { + MyRenaultHttpSession httpSession = new MyRenaultHttpSession(this.config, httpClient); + try { + boolean pause = OnOffType.ON == command; + httpSession.initSesssion(car); + httpSession.actionPause(pause); + car.setPauseMode(pause); + updateState(CHANNEL_PAUSE, OnOffType.from(command.toString())); + } catch (InterruptedException e) { + logger.warn("Error My Renault Http Session.", e); + Thread.currentThread().interrupt(); + } catch (RenaultForbiddenException | RenaultNotImplementedException | RenaultActionException + | RenaultException | RenaultUpdateException | ExecutionException | TimeoutException e) { + logger.warn("Error during action set pause.", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } catch (IllegalArgumentException e) { + logger.warn("Invalid Pause Mode {}.", command.toString()); + return; + } + } + break; default: if (command instanceof RefreshType) { reschedulePollingJob(); diff --git a/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/i18n/renault.properties b/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/i18n/renault.properties index 72572fe32a0..789a0220685 100644 --- a/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/i18n/renault.properties +++ b/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/i18n/renault.properties @@ -62,6 +62,7 @@ channel-type.renault.chargingmode.label = Charging Mode channel-type.renault.chargingmode.state.option.UNKNOWN = Unknown channel-type.renault.chargingmode.state.option.SCHEDULE_MODE = Schedule mode channel-type.renault.chargingmode.state.option.ALWAYS_CHARGING = Instant charge +channel-type.renault.pause.label = Pause channel-type.renault.chargingremainingtime.label = Charging Time Remaining channel-type.renault.chargingstatus.label = Charging Status channel-type.renault.chargingstatus.state.option.NOT_IN_CHARGE = Not charging diff --git a/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/thing/thing-types.xml index 3e517231be0..5be829c2c9d 100644 --- a/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.renault/src/main/resources/OH-INF/thing/thing-types.xml @@ -16,6 +16,7 @@ + @@ -148,6 +149,12 @@ + + Switch + + Pause or resume the charge. + + Number:Time