[miio] add new custom refresh methods (#10957)
* Improve matching the command responses to the sending channel * Use newer method to get device list using `device_list_page` * Adding the ability to send custom requests to cloud * Adding the ability to send custom commands with additional elements in the json Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
This commit is contained in:
parent
c0ab022e4e
commit
072a6045c2
bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(",,", ",");
|
||||
|
Loading…
x
Reference in New Issue
Block a user