From 5bfc8940f4831049b5180d7f578620260a3a6ed9 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 12 Dec 2020 15:27:54 -0800 Subject: [PATCH] [miio] Elimate several SAT warnings (#9289) * [miio] eliminate warnings from mapdraw * [miio] clean warnings from basic handler * [miio] avoid apache commons warning in utils * [miio] eliminate warnings from micloudconnector Signed-off-by: Marcel Verpaalen --- .../openhab/binding/miio/internal/Utils.java | 19 +++- .../basic/MiIoDatabaseWatchService.java | 6 +- .../miio/internal/cloud/MiCloudConnector.java | 91 +++++++++++-------- .../internal/handler/MiIoBasicHandler.java | 31 ++++--- .../miio/internal/robot/RRMapDraw.java | 14 ++- .../miio/internal/robot/RRMapFileParser.java | 23 ++--- 6 files changed, 110 insertions(+), 74 deletions(-) diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java index bd277afa4..0da6bcea2 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java @@ -13,14 +13,19 @@ package org.openhab.binding.miio.internal; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.NoSuchFileException; -import org.apache.commons.io.IOUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import com.google.gson.JsonElement; import com.google.gson.JsonIOException; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; @@ -90,12 +95,16 @@ public final class Utils { } } - public static JsonObject convertFileToJSON(URL fileName) throws JsonIOException, JsonSyntaxException, IOException { + public static JsonObject convertFileToJSON(URL fileName) throws JsonIOException, JsonSyntaxException, + JsonParseException, IOException, URISyntaxException, NoSuchFileException { JsonObject jsonObject = new JsonObject(); JsonParser parser = new JsonParser(); - JsonElement jsonElement = parser.parse(IOUtils.toString(fileName)); - jsonObject = jsonElement.getAsJsonObject(); - return jsonObject; + try (InputStream inputStream = fileName.openStream(); + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + JsonElement jsonElement = parser.parse(reader); + jsonObject = jsonElement.getAsJsonObject(); + return jsonObject; + } } public static String minLengthString(String string, int length) { diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoDatabaseWatchService.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoDatabaseWatchService.java index 8735d2cbb..c6dc11eb6 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoDatabaseWatchService.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoDatabaseWatchService.java @@ -18,6 +18,7 @@ import static org.openhab.binding.miio.internal.MiIoBindingConstants.BINDING_DAT import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; @@ -43,9 +44,8 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonIOException; import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; +import com.google.gson.JsonParseException; /** * The {@link MiIoDatabaseWatchService} creates a registry of database file per ModelId @@ -118,7 +118,7 @@ public class MiIoDatabaseWatchService extends AbstractWatchService { for (String id : devdb.getDevice().getId()) { workingDatabaseList.put(id, db); } - } catch (JsonIOException | JsonSyntaxException | IOException e) { + } catch (JsonParseException | IOException | URISyntaxException e) { logger.debug("Error while processing database '{}': {}", db, e.getMessage()); } databaseList = workingDatabaseList; diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java index 5077294b0..c5bb05021 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java @@ -52,6 +52,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; @@ -154,22 +155,26 @@ public class MiCloudConnector { String mapResponse = request(url, map); logger.trace("response: {}", mapResponse); String errorMsg = ""; - JsonElement response = PARSER.parse(mapResponse); - if (response.isJsonObject()) { - logger.debug("Received JSON message {}", response.toString()); - if (response.getAsJsonObject().has("result") && response.getAsJsonObject().get("result").isJsonObject()) { - JsonObject jo = response.getAsJsonObject().get("result").getAsJsonObject(); - if (jo.has("url")) { - String mapUrl = jo.get("url").getAsString(); - return mapUrl != null ? mapUrl : ""; + try { + JsonElement response = PARSER.parse(mapResponse); + if (response.isJsonObject()) { + logger.debug("Received JSON message {}", response); + if (response.getAsJsonObject().has("result") + && response.getAsJsonObject().get("result").isJsonObject()) { + JsonObject jo = response.getAsJsonObject().get("result").getAsJsonObject(); + if (jo.has("url")) { + return jo.get("url").getAsString(); + } else { + errorMsg = "Could not get url"; + } } else { - errorMsg = "Could not get url"; + errorMsg = "Could not get result"; } } else { - errorMsg = "Could not get result"; + errorMsg = "Received message is invalid JSON"; } - } else { - errorMsg = "Received message is invalid JSON"; + } catch (ClassCastException | IllegalStateException e) { + errorMsg = "Received message could not be parsed"; } logger.debug("{}: {}", errorMsg, mapResponse); return ""; @@ -209,11 +214,13 @@ public class MiCloudConnector { if (resp.isJsonObject()) { final JsonObject jor = resp.getAsJsonObject(); if (jor.has("result")) { - devicesList = GSON.fromJson(jor.get("result"), CloudDeviceListDTO.class).getCloudDevices(); - - for (CloudDeviceDTO device : devicesList) { - device.setServer(country); - logger.debug("Xiaomi cloud info: {}", device); + CloudDeviceListDTO cdl = GSON.fromJson(jor.get("result"), CloudDeviceListDTO.class); + if (cdl != null) { + devicesList.addAll(cdl.getCloudDevices()); + for (CloudDeviceDTO device : devicesList) { + device.setServer(country); + logger.debug("Xiaomi cloud info: {}", device); + } } } else { logger.debug("Response missing result: '{}'", response); @@ -222,6 +229,7 @@ public class MiCloudConnector { logger.debug("Response is not a json object: '{}'", response); } } catch (JsonSyntaxException | IllegalStateException | ClassCastException e) { + loginFailedCounter++; logger.info("Error while parsing devices: {}", e.getMessage()); } return devicesList; @@ -238,6 +246,7 @@ public class MiCloudConnector { } } catch (MiCloudException e) { logger.info("{}", e.getMessage()); + loginFailedCounter++; } return ""; } @@ -260,6 +269,7 @@ public class MiCloudConnector { if (this.serviceToken.isEmpty() || this.userId.isEmpty()) { throw new MiCloudException("Cannot execute request. service token or userId missing"); } + loginFailedCounterCheck(); startClient(); logger.debug("Send request: {} to {}", params.get("data"), url); Request request = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); @@ -305,10 +315,13 @@ public class MiCloudConnector { } catch (HttpResponseException e) { serviceToken = ""; logger.debug("Error while executing request to {} :{}", url, e.getMessage()); + loginFailedCounter++; } catch (InterruptedException | TimeoutException | ExecutionException | IOException e) { logger.debug("Error while executing request to {} :{}", url, e.getMessage()); + loginFailedCounter++; } catch (MiIoCryptoException e) { logger.debug("Error while decrypting response of request to {} :{}", url, e.getMessage(), e); + loginFailedCounter++; } return ""; } @@ -339,16 +352,22 @@ public class MiCloudConnector { logger.info("Error logging on to Xiaomi cloud ({}): {}", loginFailedCounter, e.getMessage()); loginFailedCounter++; serviceToken = ""; - if (loginFailedCounter > 10) { - logger.info("Repeated errors logging on to Xiaomi cloud. Cleaning stored cookies"); - dumpCookies(".xiaomi.com", true); - dumpCookies(".mi.com", true); - } + loginFailedCounterCheck(); return false; } return true; } + void loginFailedCounterCheck() { + if (loginFailedCounter > 10) { + logger.info("Repeated errors logging on to Xiaomi cloud. Cleaning stored cookies"); + dumpCookies(".xiaomi.com", true); + dumpCookies(".mi.com", true); + serviceToken = ""; + loginFailedCounter = 0; + } + } + protected boolean loginRequest() throws MiCloudException { try { startClient(); @@ -360,7 +379,6 @@ public class MiCloudConnector { location = sign; // seems we already have login location } final ContentResponse responseStep3 = loginStep3(location); - switch (responseStep3.getStatus()) { case HttpStatus.FORBIDDEN_403: throw new MiCloudException("Access denied. Did you set the correct api-key and/or username?"); @@ -375,7 +393,7 @@ public class MiCloudConnector { throw new MiCloudException("Cannot logon to Xiaomi cloud: " + e.getMessage(), e); } catch (MiIoCryptoException e) { throw new MiCloudException("Error decrypting. Cannot logon to Xiaomi cloud: " + e.getMessage(), e); - } catch (MalformedURLException e) { + } catch (MalformedURLException | JsonParseException e) { throw new MiCloudException("Error getting logon URL. Cannot logon to Xiaomi cloud: " + e.getMessage(), e); } } @@ -396,22 +414,21 @@ public class MiCloudConnector { logger.trace("Xiaomi Login step 1 response = {}", responseStep1); try { JsonElement resp = new JsonParser().parse(parseJson(content)); - if (resp.getAsJsonObject().has("_sign")) { + if (resp.isJsonObject() && resp.getAsJsonObject().has("_sign")) { String sign = resp.getAsJsonObject().get("_sign").getAsString(); logger.trace("Xiaomi Login step 1 sign = {}", sign); return sign; } else { - logger.trace("Xiaomi Login _sign missing. Maybe still has login cookie."); + logger.debug("Xiaomi Login _sign missing. Maybe still has login cookie."); return ""; } - - } catch (JsonSyntaxException | NullPointerException e) { + } catch (JsonParseException | IllegalStateException | ClassCastException e) { throw new MiCloudException("Error getting logon sign. Cannot parse response: " + e.getMessage(), e); } } - private String loginStep2(String sign) - throws MiIoCryptoException, InterruptedException, TimeoutException, ExecutionException, MiCloudException { + private String loginStep2(String sign) throws MiIoCryptoException, InterruptedException, TimeoutException, + ExecutionException, MiCloudException, JsonSyntaxException, JsonParseException { String passToken; String cUserId; @@ -442,7 +459,9 @@ public class MiCloudConnector { JsonElement resp2 = new JsonParser().parse(parseJson(content2)); CloudLoginDTO jsonResp = GSON.fromJson(resp2, CloudLoginDTO.class); - + if (jsonResp == null) { + throw new MiCloudException("Error getting logon details from step 2: " + content2); + } ssecurity = jsonResp.getSsecurity(); userId = jsonResp.getUserId(); cUserId = jsonResp.getcUserId(); @@ -492,9 +511,9 @@ public class MiCloudConnector { if (logger.isTraceEnabled()) { try { URI uri = URI.create(url); - if (uri != null) { - logger.trace("Cookie dump for {}", uri); - CookieStore cs = httpClient.getCookieStore(); + logger.trace("Cookie dump for {}", uri); + CookieStore cs = httpClient.getCookieStore(); + if (cs != null) { List cookies = cs.get(uri); for (HttpCookie cookie : cookies) { logger.trace("Cookie ({}) : {} --> {} (path: {}. Removed: {})", cookie.getDomain(), @@ -504,9 +523,9 @@ public class MiCloudConnector { } } } else { - logger.trace("Could not create URI from {}", url); + logger.trace("Could not create cookiestore from {}", url); } - } catch (IllegalArgumentException | NullPointerException e) { + } catch (IllegalArgumentException e) { logger.trace("Error dumping cookies from {}: {}", url, e.getMessage(), e); } } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java index 1b87375b6..787d75fa1 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import javax.measure.Unit; @@ -134,7 +135,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { } logger.debug("Locating action for {} channel '{}': '{}'", getThing().getUID(), channelUID.getId(), command); if (!actions.isEmpty()) { - MiIoBasicChannel miIoBasicChannel = actions.get(channelUID); + final MiIoBasicChannel miIoBasicChannel = actions.get(channelUID); if (miIoBasicChannel != null) { int valuePos = 0; for (MiIoDeviceAction action : miIoBasicChannel.getActions()) { @@ -254,8 +255,8 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { } else { logger.debug("Channel Id {} not in mapping.", channelUID.getId()); if (logger.isTraceEnabled()) { - for (ChannelUID a : actions.keySet()) { - logger.trace("Available entries: {} : {}", a, actions.get(a).getFriendlyName()); + for (Entry a : actions.entrySet()) { + logger.trace("Available entries: {} : {}", a.getKey(), a.getValue().getFriendlyName()); } } } @@ -641,19 +642,21 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { default: if (refreshListCustomCommands.containsKey(response.getMethod())) { logger.debug("Processing custom refresh command response for !{}", response.getMethod()); - MiIoBasicChannel ch = refreshListCustomCommands.get(response.getMethod()); - if (response.getResult().isJsonArray()) { - JsonArray cmdResponse = response.getResult().getAsJsonArray(); - final String transformation = ch.getTransfortmation(); - if (transformation == null || transformation.isBlank()) { - updateChannel(ch, ch.getChannel(), - cmdResponse.get(0).isJsonPrimitive() ? cmdResponse.get(0) - : new JsonPrimitive(cmdResponse.get(0).toString())); + final MiIoBasicChannel ch = refreshListCustomCommands.get(response.getMethod()); + if (ch != null) { + if (response.getResult().isJsonArray()) { + JsonArray cmdResponse = response.getResult().getAsJsonArray(); + final String transformation = ch.getTransfortmation(); + if (transformation == null || transformation.isBlank()) { + JsonElement response0 = cmdResponse.get(0); + updateChannel(ch, ch.getChannel(), response0.isJsonPrimitive() ? response0 + : new JsonPrimitive(response0.toString())); + } else { + updateChannel(ch, ch.getChannel(), cmdResponse); + } } else { - updateChannel(ch, ch.getChannel(), cmdResponse); + updateChannel(ch, ch.getChannel(), new JsonPrimitive(response.getResult().toString())); } - } else { - updateChannel(ch, ch.getChannel(), new JsonPrimitive(response.getResult().toString())); } } break; diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java index 2ba7c20eb..bc3c877cc 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java @@ -36,6 +36,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import javax.imageio.ImageIO; @@ -196,7 +197,8 @@ public class RRMapDraw { private void drawPath(Graphics2D g2d, float scale) { Stroke stroke = new BasicStroke(0.5f * scale); g2d.setStroke(stroke); - for (Integer pathType : rmfp.getPaths().keySet()) { + for (Entry> path : rmfp.getPaths().entrySet()) { + Integer pathType = path.getKey(); switch (pathType) { case RRMapFileParser.PATH: if (!multicolor) { @@ -216,7 +218,7 @@ public class RRMapDraw { } float prvX = 0; float prvY = 0; - for (float[] point : rmfp.getPaths().get(pathType)) { + for (float[] point : path.getValue()) { float x = toXCoord(point[0]) * scale; float y = toYCoord(point[1]) * scale; if (prvX > 1) { @@ -244,8 +246,8 @@ public class RRMapDraw { } private void drawNoGo(Graphics2D g2d, float scale) { - for (Integer area : rmfp.getAreas().keySet()) { - for (float[] point : rmfp.getAreas().get(area)) { + for (Map.Entry> area : rmfp.getAreas().entrySet()) { + for (float[] point : area.getValue()) { float x = toXCoord(point[0]) * scale; float y = toYCoord(point[1]) * scale; float x1 = toXCoord(point[2]) * scale; @@ -262,10 +264,11 @@ public class RRMapDraw { noGo.lineTo(x, y); g2d.setColor(COLOR_NO_GO_ZONES); g2d.fill(noGo); - g2d.setColor(area == 9 ? Color.RED : Color.WHITE); + g2d.setColor(area.getKey() == 9 ? Color.RED : Color.WHITE); g2d.draw(noGo); } } + ; } private void drawWalls(Graphics2D g2d, float scale) { @@ -419,6 +422,7 @@ public class RRMapDraw { } private @Nullable URL getImageUrl(String image) { + final Bundle bundle = this.bundle; if (bundle != null) { return bundle.getEntry("images/" + image); } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java index 095d06bb0..d0aa22128 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -333,25 +334,25 @@ public class RRMapFileParser { pw.printf("Charger pos:\tX: %.0f\tY: %.0f\r\n", getChargerX(), getChargerY()); pw.printf("Robo pos:\tX: %.0f\tY: %.0f\tAngle: %d\r\n", getRoboX(), getRoboY(), getRoboA()); pw.printf("Goto:\tX: %.0f\tY: %.0f\r\n", getGotoX(), getGotoY()); - for (Integer area : areas.keySet()) { - pw.print(area == NO_GO_AREAS ? "No Go zones:\t" : "MFBZS zones:\t"); - pw.printf("%d\r\n", areas.get(area).size()); - printAreaDetails(areas.get(area), pw); + for (Entry> area : areas.entrySet()) { + pw.print(area.getKey() == NO_GO_AREAS ? "No Go zones:\t" : "MFBZS zones:\t"); + pw.printf("%d\r\n", area.getValue().size()); + printAreaDetails(area.getValue(), pw); } pw.printf("Walls:\t%d\r\n", walls.size()); printAreaDetails(walls, pw); pw.printf("Zones:\t%d\r\n", zones.size()); printAreaDetails(zones, pw); - for (Integer obstacleType : obstacles.keySet()) { - pw.printf("Obstacles Type (%d):\t%d\r\n", obstacleType, obstacles.get(obstacleType).size()); - printObstacleDetails(obstacles.get(obstacleType), pw); + for (Entry> obstacleType : obstacles.entrySet()) { + pw.printf("Obstacles Type (%d):\t%d\r\n", obstacleType.getKey(), obstacleType.getValue().size()); + printObstacleDetails(obstacleType.getValue(), pw); } pw.printf("Blocks:\t%d\r\n", blocks.length); pw.print("Paths:"); - for (Integer p : pathsDetails.keySet()) { - pw.printf("\r\nPath type:\t%d", p); - for (String detail : pathsDetails.get(p).keySet()) { - pw.printf(" %s: %d", detail, pathsDetails.get(p).get(detail)); + for (Entry> pathDetail : pathsDetails.entrySet()) { + pw.printf("\r\nPath type:\t%d", pathDetail.getKey()); + for (String detail : pathDetail.getValue().keySet()) { + pw.printf(" %s: %d", detail, pathDetail.getValue().get(detail)); } } pw.println();