From eadf63fa174293fbd3147d61fb597b3c06b72a4a Mon Sep 17 00:00:00 2001 From: Martin Grassl Date: Wed, 22 Jan 2025 21:01:37 +0100 Subject: [PATCH] [mybmw] Fix charging statistics URL (#18153) * [mybmw] add stop charging command Signed-off-by: Martin Grassl --- .../handler/auth/MyBMWTokenController.java | 50 ++++++++++++------- .../mybmw/internal/handler/auth/Token.java | 11 +++- .../handler/backend/MyBMWHttpProxy.java | 10 ++-- .../mybmw/internal/utils/BimmerConstants.java | 4 ++ 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/MyBMWTokenController.java b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/MyBMWTokenController.java index e90861f97a3..e56fc6bb7bf 100644 --- a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/MyBMWTokenController.java +++ b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/MyBMWTokenController.java @@ -25,8 +25,6 @@ import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.OAUTH_END import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.OCP_APIM_KEYS; import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.REFRESH_TOKEN; import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.REGION_CHINA; -import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.REGION_NORTH_AMERICA; -import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.REGION_ROW; import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.USER_AGENT; import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.X_USER_AGENT; import static org.openhab.binding.mybmw.internal.utils.HTTPConstants.AUTHORIZATION; @@ -110,7 +108,7 @@ public class MyBMWTokenController { this.httpClient = httpClient; } - public void setBridgeConfiguration(MyBMWBridgeConfiguration bridgeConfiguration) { + public synchronized void setBridgeConfiguration(MyBMWBridgeConfiguration bridgeConfiguration) { this.bridgeConfiguration = bridgeConfiguration; } @@ -122,9 +120,22 @@ public class MyBMWTokenController { * * @return token */ - public Token getToken() { - if (!bridgeConfiguration.getHcaptchatoken().isBlank()) { + public synchronized Token getToken() { + + logger.trace("getToken, current token {}", token.toString()); + + if (REGION_CHINA.equals(bridgeConfiguration.getRegion()) && !token.isValid()) { + // in China no hcaptchatoken is required + boolean tokenUpdateSuccess = false; + tokenUpdateSuccess = getAndUpdateTokenChina(); + if (!tokenUpdateSuccess) { + logger.warn("Authorization failed!"); + } + } else if (!bridgeConfiguration.getHcaptchatoken().isBlank()) { // if the hcaptchastring is available, then a new login is triggered + + logger.trace("initial login, using captchatoken {}", bridgeConfiguration.getHcaptchatoken()); + boolean tokenCreationSuccess = getInitialToken(); if (!tokenCreationSuccess) { @@ -138,22 +149,15 @@ public class MyBMWTokenController { } else if (!token.isValid() && !Constants.EMPTY.equals(token.getRefreshToken())) { // if the token is invalid, try to refresh the token boolean tokenUpdateSuccess = false; - switch (bridgeConfiguration.getRegion()) { - case REGION_CHINA: - tokenUpdateSuccess = getAndUpdateTokenChina(); - break; - case REGION_NORTH_AMERICA: - case REGION_ROW: - tokenUpdateSuccess = getUpdatedToken(); - break; - default: - logger.warn("Region {} not supported", bridgeConfiguration.getRegion()); - break; - } + tokenUpdateSuccess = getUpdatedToken(); + if (!tokenUpdateSuccess) { logger.warn("Authorization failed!"); } } + + logger.trace("getToken, new token {}", token.toString()); + return token; } @@ -166,6 +170,9 @@ public class MyBMWTokenController { * @return true if the token was successfully updated */ private synchronized boolean getInitialToken() { + + logger.trace("get initial token"); + try { /* * Step 1) Get basic values for further queries @@ -254,6 +261,8 @@ public class MyBMWTokenController { AuthResponse ar = JsonStringDeserializer.deserializeString(codeResponse.getContentAsString(), AuthResponse.class); + logger.trace("Login response: {}", ar.toString()); + token.setType(ar.tokenType); token.setToken(ar.accessToken); token.setExpiration(ar.expiresIn); @@ -273,6 +282,9 @@ public class MyBMWTokenController { * @return true if token has successfully been refreshed */ private synchronized boolean getUpdatedToken() { + + logger.trace("getUpdatedToken"); + try { /* * Step 1) Get basic values for further queries @@ -303,6 +315,8 @@ public class MyBMWTokenController { AuthResponse ar = JsonStringDeserializer.deserializeString(codeResponse.getContentAsString(), AuthResponse.class); + logger.trace("Refresh response: {}", ar.toString()); + token.setToken(ar.accessToken); token.setExpiration(ar.expiresIn); token.setRefreshToken(ar.refreshToken); @@ -310,7 +324,7 @@ public class MyBMWTokenController { return true; } catch (Exception e) { - logger.warn("Refresh Exception: {}", e.getMessage()); + logger.warn("Refresh Exception: ", e); } return false; } diff --git a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/Token.java b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/Token.java index 4c362a95575..c688699831d 100644 --- a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/Token.java +++ b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/auth/Token.java @@ -67,13 +67,20 @@ public class Token { this.gcid = gcid; } + /** + * check if the token is valid - for enough buffer it is not valid if it expires in <10s + * + * @return + */ public boolean isValid() { return (!token.equals(Constants.EMPTY) && !tokenType.equals(Constants.EMPTY) - && !refreshToken.equals(Constants.EMPTY) && (this.expiration - System.currentTimeMillis() / 1000) > 1); + && !refreshToken.equals(Constants.EMPTY) && (this.expiration - System.currentTimeMillis() / 1000) > 10); } @Override public String toString() { - return tokenType + Constants.COLON + token + Constants.COLON + isValid(); + return "Token [token=" + token + ", tokenType=" + tokenType + ", refreshToken=" + refreshToken + ", gcid=" + + gcid + ", expiration=" + expiration + "] - is valid " + isValid() + ", will expire in s " + + (this.expiration - System.currentTimeMillis() / 1000); } } diff --git a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/backend/MyBMWHttpProxy.java b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/backend/MyBMWHttpProxy.java index f6ad93518be..6587b6bd76f 100644 --- a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/backend/MyBMWHttpProxy.java +++ b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/handler/backend/MyBMWHttpProxy.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.mybmw.internal.handler.backend; -import static org.openhab.binding.mybmw.internal.utils.BimmerConstants.APP_VERSIONS; - import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -178,7 +176,7 @@ public class MyBMWHttpProxy implements MyBMWProxy { */ public byte[] requestImage(String vin, String brand, ImageProperties props) throws NetworkException { final String localImageUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(bridgeConfiguration.getRegion()) - + "/eadrax-ics/v3/presentation/vehicles/" + vin + "/images?carView=" + props.viewport; + + BimmerConstants.IMAGE_URL.replace(BimmerConstants.PARAM_VIN, vin) + props.viewport; return get(localImageUrl, brand, vin, HTTPConstants.CONTENT_TYPE_IMAGE); } @@ -232,7 +230,7 @@ public class MyBMWHttpProxy implements MyBMWProxy { chargeStatisticsParams.put("currentDate", Converter.getCurrentISOTime()); String params = UrlEncoded.encode(chargeStatisticsParams, StandardCharsets.UTF_8, false); String chargeStatisticsUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(bridgeConfiguration.getRegion()) - + "/eadrax-chs/v1/charging-statistics?" + params; + + BimmerConstants.CHARGING_STATISTICS + params; byte[] chargeStatisticsResponse = get(chargeStatisticsUrl, brand, vin, HTTPConstants.CONTENT_TYPE_JSON); String chargeStatisticsResponseString = new String(chargeStatisticsResponse); return chargeStatisticsResponseString; @@ -264,7 +262,7 @@ public class MyBMWHttpProxy implements MyBMWProxy { chargeSessionsParams.put("include_date_picker", "true"); String params = UrlEncoded.encode(chargeSessionsParams, StandardCharsets.UTF_8, false); String chargeSessionsUrl = "https://" + BimmerConstants.EADRAX_SERVER_MAP.get(bridgeConfiguration.getRegion()) - + "/eadrax-chs/v1/charging-sessions?" + params; + + BimmerConstants.CHARGING_SESSIONS + params; byte[] chargeSessionsResponse = get(chargeSessionsUrl, brand, vin, HTTPConstants.CONTENT_TYPE_JSON); String chargeSessionsResponseString = new String(chargeSessionsResponse); return chargeSessionsResponseString; @@ -369,7 +367,7 @@ public class MyBMWHttpProxy implements MyBMWProxy { req.header(HttpHeader.AUTHORIZATION, myBMWTokenController.getToken().getBearerToken()); req.header(HTTPConstants.HEADER_X_USER_AGENT, String.format(BimmerConstants.X_USER_AGENT, brand.toLowerCase(), - APP_VERSIONS.get(bridgeConfiguration.getRegion()), bridgeConfiguration.getRegion())); + BimmerConstants.APP_VERSIONS.get(bridgeConfiguration.getRegion()), bridgeConfiguration.getRegion())); req.header(HttpHeader.ACCEPT_LANGUAGE, bridgeConfiguration.getLanguage()); req.header(HttpHeader.ACCEPT, contentType); req.header(HTTPConstants.HEADER_BMW_VIN, vin); diff --git a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/utils/BimmerConstants.java b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/utils/BimmerConstants.java index 01e8b972169..a5c3db29f1a 100644 --- a/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/utils/BimmerConstants.java +++ b/bundles/org.openhab.binding.mybmw/src/main/java/org/openhab/binding/mybmw/internal/utils/BimmerConstants.java @@ -82,4 +82,8 @@ public interface BimmerConstants { static final String API_VEHICLES = "/eadrax-vcs/v4/vehicles"; static final String API_REMOTE_SERVICE_BASE_URL = "/eadrax-vrccs/v3/presentation/remote-commands/"; // '/{vin}/{service_type}' static final String API_POI = "/eadrax-dcs/v1/send-to-car/send-to-car"; + static final String CHARGING_STATISTICS = "/eadrax-chs/v2/charging-statistics?"; + static final String CHARGING_SESSIONS = "/eadrax-chs/v2/charging-sessions?"; + static final String PARAM_VIN = "$vin$"; + static final String IMAGE_URL = "/eadrax-ics/v3/presentation/vehicles/" + PARAM_VIN + "/images?carView="; }