diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java index 9e974d799..626b7515c 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java @@ -124,6 +124,14 @@ public class CloudConnector { return cl.sendRPCCommand(device, country.trim().toLowerCase(), command.getCommandString()); } + public String sendCloudCommand(String urlPart, String country, String parameters) throws MiCloudException { + final @Nullable MiCloudConnector cl = this.cloudConnector; + if (cl == null || !isConnected()) { + throw new MiCloudException("Cannot execute request. Cloud service not available"); + } + return cl.request(urlPart, country, parameters); + } + public @Nullable RawType getMap(String mapId, String country) throws MiCloudException { logger.debug("Getting vacuum map {} from Xiaomi cloud server: '{}'", mapId, country); String mapCountry; 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 3ecabee39..38fb7143e 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 @@ -237,7 +237,7 @@ public class MiCloudConnector { public String getDeviceString(String country) { String resp; try { - resp = request("/home/device_list", country, "{\"getVirtualModel\":false,\"getHuamiDevices\":0}"); + resp = request("/home/device_list_page", country, "{\"getVirtualModel\":false,\"getHuamiDevices\":1}"); logger.trace("Get devices response: {}", resp); if (resp.length() > 2) { CloudUtil.saveDeviceInfoFile(resp, country, logger); @@ -260,7 +260,7 @@ public class MiCloudConnector { String url = urlPart.trim(); url = getApiUrl(country) + (url.startsWith("/app") ? url.substring(4) : url); String response = request(url, params); - logger.debug("Request to {} server {}. Response: {}", country, urlPart, response); + logger.debug("Request to '{}' server '{}'. Response: '{}'", country, urlPart, response); return response; } @@ -270,7 +270,7 @@ public class MiCloudConnector { } loginFailedCounterCheck(); startClient(); - logger.debug("Send request: {} to {}", params.get("data"), url); + logger.debug("Send request to {} with data '{}'", url, params.get("data")); Request request = httpClient.newRequest(url).timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS); request.agent(USERAGENT); request.header("x-xiaomi-protocal-flag-cli", "PROTOCAL-HTTP2"); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java index b14d6ddaa..0d37746e1 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java @@ -112,11 +112,11 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi protected boolean handleCommandsChannels(ChannelUID channelUID, Command command) { if (channelUID.getId().equals(CHANNEL_COMMAND)) { - cmds.put(sendCommand(command.toString(), ""), command.toString()); + cmds.put(sendCommand(command.toString()), channelUID.getId()); return true; } if (channelUID.getId().equals(CHANNEL_RPC)) { - cmds.put(sendCommand(command.toString(), cloudServer), command.toString()); + cmds.put(sendCommand(command.toString(), cloudServer), channelUID.getId()); return true; } return false; @@ -553,12 +553,11 @@ public abstract class MiIoAbstractHandler extends BaseThingHandler implements Mi break; } if (cmds.containsKey(response.getId())) { - if (response.getCloudServer().isBlank()) { - updateState(CHANNEL_COMMAND, new StringType(response.getResponse().toString())); - } else { - updateState(CHANNEL_RPC, new StringType(response.getResponse().toString())); + String channel = cmds.get(response.getId()); + if (channel != null && (CHANNEL_COMMAND.contentEquals(channel) || CHANNEL_RPC.contentEquals(channel))) { + updateState(channel, new StringType(response.getResponse().toString())); + cmds.remove(response.getId()); } - cmds.remove(response.getId()); } } catch (Exception e) { logger.debug("Error while handing message {}", response.getResponse(), 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 2abc7db32..3b81c3db3 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 @@ -328,7 +328,17 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { getThing().getUID()); continue; } - sendCommand(miChannel.getChannelCustomRefreshCommand()); + String cmd = miChannel.getChannelCustomRefreshCommand(); + if (!cmd.startsWith("/")) { + cmds.put(sendCommand(miChannel.getChannelCustomRefreshCommand()), miChannel.getChannel()); + } else { + if (cloudServer.isBlank()) { + logger.debug("Cloudserver empty. Skipping refresh for {} channel '{}'", getThing().getUID(), + miChannel.getChannel()); + } else { + cmds.put(sendCommand(cmd, cloudServer), miChannel.getChannel()); + } + } } } @@ -515,6 +525,16 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { return null; } + private @Nullable MiIoBasicChannel getCustomRefreshChannel(String channelName) { + for (MiIoBasicChannel refreshEntry : refreshListCustomCommands.values()) { + if (refreshEntry.getChannel().equals(channelName)) { + return refreshEntry; + } + } + logger.trace("Did not find channel for {} in {}", channelName, refreshList); + return null; + } + private void updatePropsFromJsonArray(MiIoSendCommand response) { JsonArray res = response.getResult().getAsJsonArray(); JsonArray para = JsonParser.parseString(response.getCommandString()).getAsJsonObject().get("params") @@ -679,10 +699,11 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { } break; default: - if (refreshListCustomCommands.containsKey(response.getMethod())) { + String channel = cmds.get(response.getId()); + if (channel != null) { logger.debug("Processing custom refresh command response for '{}' - {}", response.getMethod(), response.getResult()); - final MiIoBasicChannel ch = refreshListCustomCommands.get(response.getMethod()); + final MiIoBasicChannel ch = getCustomRefreshChannel(channel); if (ch != null) { if (response.getResult().isJsonArray()) { JsonArray cmdResponse = response.getResult().getAsJsonArray(); @@ -698,6 +719,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler { updateChannel(ch, ch.getChannel(), new JsonPrimitive(response.getResult().toString())); } } + cmds.remove(response.getId()); } break; } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java index bc0335865..7be4bd454 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java @@ -146,9 +146,17 @@ public class MiIoAsyncCommunication { if (cmdId > MAX_ID) { id.set(0); } - fullCommand.addProperty("id", cmdId); - fullCommand.addProperty("method", command); - fullCommand.add("params", JsonParser.parseString(params)); + if (command.startsWith("{") && command.endsWith("}")) { + fullCommand = JsonParser.parseString(command).getAsJsonObject(); + fullCommand.addProperty("id", cmdId); + if (!fullCommand.has("params") && !params.isBlank()) { + fullCommand.add("params", JsonParser.parseString(params)); + } + } else { + fullCommand.addProperty("id", cmdId); + fullCommand.addProperty("method", command); + fullCommand.add("params", JsonParser.parseString(params)); + } MiIoSendCommand sendCmd = new MiIoSendCommand(cmdId, MiIoCommand.getCommand(command), fullCommand, cloudServer); concurrentLinkedQueue.add(sendCmd); @@ -163,7 +171,7 @@ public class MiIoAsyncCommunication { sendPing(ip); } return cmdId; - } catch (JsonSyntaxException e) { + } catch (JsonSyntaxException | IllegalStateException e) { logger.warn("Send command '{}' with parameters {} -> {} (Device: {}) gave error {}", command, params, ip, deviceId, e.getMessage()); throw e; @@ -177,11 +185,24 @@ public class MiIoAsyncCommunication { if (miIoSendCommand.getCloudServer().isBlank()) { decryptedResponse = sendCommand(miIoSendCommand.getCommandString(), token, ip, deviceId); } else { - decryptedResponse = cloudConnector.sendRPCCommand(Utils.getHexId(deviceId), - miIoSendCommand.getCloudServer(), miIoSendCommand); - logger.debug("Command {} send via cloudserver {}", miIoSendCommand.getCommandString(), - miIoSendCommand.getCloudServer()); - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + if (!miIoSendCommand.getMethod().startsWith("/")) { + decryptedResponse = cloudConnector.sendRPCCommand(Utils.getHexId(deviceId), + miIoSendCommand.getCloudServer(), miIoSendCommand); + logger.debug("Command {} send via cloudserver {}", miIoSendCommand.getCommandString(), + miIoSendCommand.getCloudServer()); + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + } else { + String data = miIoSendCommand.getParams().isJsonArray() + && miIoSendCommand.getParams().getAsJsonArray().size() > 0 + ? miIoSendCommand.getParams().getAsJsonArray().get(0).toString() + : ""; + logger.debug("Custom cloud request send to url '{}' with data '{}'", miIoSendCommand.getMethod(), + data); + decryptedResponse = cloudConnector.sendCloudCommand(miIoSendCommand.getMethod(), + miIoSendCommand.getCloudServer(), data); + miIoSendCommand.setResponse(JsonParser.parseString(decryptedResponse).getAsJsonObject()); + return miIoSendCommand; + } } // hack due to avoid invalid json errors from some misbehaving device firmwares decryptedResponse = decryptedResponse.replace(",,", ",");