[renault] Add channel for pausing/resuming charging (#14527)

* Adding Pause-Resume Endpoint

Signed-off-by: fifipil909 <vincent.pilate@gmail.com>
This commit is contained in:
fifipil909 2023-03-10 23:32:24 +01:00 committed by GitHub
parent 505a651992
commit 8e9bc3124e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 0 deletions

View File

@ -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

View File

@ -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";

View File

@ -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) {

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -16,6 +16,7 @@
<channel id="plugstatus" typeId="plugstatus"/>
<channel id="chargingstatus" typeId="chargingstatus"/>
<channel id="chargingmode" typeId="chargingmode"/>
<channel id="pause" typeId="pause"/>
<channel id="chargingremainingtime" typeId="chargingremainingtime"/>
<channel id="estimatedrange" typeId="estimatedrange"/>
<channel id="odometer" typeId="odometer"/>
@ -148,6 +149,12 @@
</options>
</state>
</channel-type>
<channel-type id="pause">
<item-type>Switch</item-type>
<label>Pause Charge</label>
<description>Pause or resume the charge.</description>
<state readOnly="false"></state>
</channel-type>
<channel-type id="chargingremainingtime">
<item-type>Number:Time</item-type>
<label>Charging Time Remaining</label>