Skip to content

Commit

Permalink
[miio] add miot protocol & conditions (openhab#7404)
Browse files Browse the repository at this point in the history
* [miio] add miot protocol & conditions

* Add miot protocol handling openhab#7276
* Add first 2 miot devices (airpurifiers mb3 & ma4)
* Add conditional commands
* Change brightness to dimmers openhab#4388
* Apply conditions for dimmers
* Remove obsolete (pre)parameters from actions

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
  • Loading branch information
marcelrv authored and andrewfg committed Aug 31, 2020
1 parent b8b2618 commit b0cdb04
Show file tree
Hide file tree
Showing 25 changed files with 2,223 additions and 215 deletions.
380 changes: 290 additions & 90 deletions bundles/org.openhab.binding.miio/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum MiIoCommand {
SET_BRIGHT("set_bright"),
SET_WIFI_LET("set_wifi_led"),
SET_FAVORITE("set_level_favorite"),
ACTION("action"),

// vacuum commands
START_VACUUM("app_start"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public enum MiIoDevices {
AIR_PURIFIERMA1("zhimi.airpurifier.ma1", "Mi Air Purifier MS1", THING_TYPE_BASIC),
AIR_PURIFIERMA2("zhimi.airpurifier.ma2", "Mi Air Purifier MS2", THING_TYPE_BASIC),
AIR_PURIFIERMA4("zhimi.airpurifier.ma4", "Mi Air Purifier 3", THING_TYPE_BASIC),
AIR_PURIFIERMMB3("zhimi.airpurifier.mb3", "Mi Air Purifier 3", THING_TYPE_BASIC),
AIR_PURIFIERSA1("zhimi.airpurifier.sa1", "Mi Air Purifier Super", THING_TYPE_BASIC),
AIR_PURIFIERSA2("zhimi.airpurifier.sa2", "Mi Air Purifier Super 2", THING_TYPE_BASIC),
AIRFRESH_T2017("dmaker.airfresh.t2017", "Mi Fresh Air Ventilator", THING_TYPE_BASIC),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.miio.internal.basic;

import java.util.Map;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;

/**
* Conditional Execution of rules
*
* @author Marcel Verpaalen - Initial contribution
*/
@NonNullByDefault
public class ActionConditions {
private static final Logger LOGGER = LoggerFactory.getLogger(ActionConditions.class);

/**
* Check if it matches the firmware version.
*
* @param condition
* @param deviceVariables
* @param value
* @return value in case firmware is matching, return null if not
*/
private static @Nullable JsonElement firmwareCheck(MiIoDeviceActionCondition condition,
Map<String, Object> deviceVariables, @Nullable JsonElement value) {
// TODO: placeholder for firmware version check to allow for firmware dependent actions
return value;
}

/**
* Check if the value is a valid brightness between 1-99.
* If <1 returns Off, if >99 returns On to activate the power On/Off switch
*
* @param value
* @return
*/
private static @Nullable JsonElement brightness(@Nullable JsonElement value) {
if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) {
int intVal = value.getAsInt();
if (intVal > 99) {
return new JsonPrimitive("on");
}
if (intVal < 1) {
return new JsonPrimitive("off");
}
} else {
LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value);
}
return null;
}

/**
* Check if the value is a valid brightness between 1-99 which can be send to brightness channel.
* If not returns a null
*
* @param value
* @return
*/
private static @Nullable JsonElement brightnessExists(@Nullable JsonElement value) {
if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) {
int intVal = value.getAsInt();
if (intVal > 0 && intVal < 99) {
return value;
}
} else {
LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value);
}
return null;
}

public static @Nullable JsonElement executeAction(MiIoDeviceActionCondition condition,
Map<String, Object> deviceVariables, @Nullable JsonElement value) {
switch (condition.getName().toUpperCase()) {
case "FIRMWARE":
return firmwareCheck(condition, deviceVariables, value);
case "BRIGHTNESSEXISTING":
return brightnessExists(value);
case "BRIGHTNESSONOFF":
return brightness(value);
default:
LOGGER.debug("Condition {} not found. Returning '{}'", condition,
value != null ? value.toString() : "");
return value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ public class MiIoBasicChannel {
@SerializedName("property")
@Expose
private @Nullable String property;
@SerializedName("siid")
@Expose
private @Nullable Integer siid;
@SerializedName("piid")
@Expose
private @Nullable Integer piid;
@SerializedName("friendlyName")
@Expose
private @Nullable String friendlyName;
Expand Down Expand Up @@ -69,6 +75,40 @@ public void setProperty(String property) {
this.property = property;
}

public int getSiid() {
final Integer siid = this.siid;
if (siid != null) {
return siid.intValue();
} else {
return 0;
}
}

public void setSiid(Integer siid) {
this.siid = siid;
}

public int getPiid() {
final Integer piid = this.piid;
if (piid != null) {
return piid.intValue();
} else {
return 0;
}
}

public void setPiid(Integer piid) {
this.piid = piid;
}

public boolean isMiOt() {
if (piid != null && siid != null && (getPiid() != 0 || getSiid() != 0)) {
return true;
} else {
return false;
}
}

public String getFriendlyName() {
final String fn = friendlyName;
return (fn == null || type == null || fn.isEmpty()) ? getChannel() : fn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,12 @@ public class MiIoDeviceAction {
@SerializedName("parameterType")
@Expose
private CommandParameterType commandParameterType = CommandParameterType.EMPTY;
@SerializedName("preCommandParameter1")
@SerializedName("parameters")
@Expose
private @Nullable String preCommandParameter1;
@SerializedName("parameter1")
@Expose
private @Nullable String parameter1;
@SerializedName("parameter2")
@Expose
private @Nullable String parameter2;
@SerializedName("parameter3")
@Expose
private @Nullable String parameter3;
private @Nullable JsonArray parameters;
@SerializedName("condition")
@Expose
private @Nullable MiIoDeviceActionCondition condition;

public JsonArray getParameters() {
final @Nullable JsonArray parameter = this.parameters;
Expand Down Expand Up @@ -77,42 +70,17 @@ public void setparameterType(String type) {
this.commandParameterType = org.openhab.binding.miio.internal.basic.CommandParameterType.fromString(type);
}

public @Nullable String getPreCommandParameter1() {
return preCommandParameter1;
}

public void setPreCommandParameter1(String preCommandParameter1) {
this.preCommandParameter1 = preCommandParameter1;
}

public @Nullable String getParameter1() {
return parameter1;
}

public void setParameter1(String parameter1) {
this.parameter1 = parameter1;
}

public @Nullable String getParameter2() {
return parameter2;
}

public void setParameter2(String parameter2) {
this.parameter1 = parameter2;
}

public @Nullable String getParameter3() {
return parameter3;
public @Nullable MiIoDeviceActionCondition getCondition() {
return condition;
}

public void setParameter3(String parameter3) {
this.parameter1 = parameter3;
public void setCondition(@Nullable MiIoDeviceActionCondition condition) {
this.condition = condition;
}

@Override
public String toString() {
return "MiIoDeviceAction [command=" + command + ", commandParameterType=" + commandParameterType
+ ", preCommandParameter1=" + preCommandParameter1 + ", parameter1=" + parameter1 + ", parameter2="
+ parameter2 + ", parameter3=" + parameter3 + "]";
+ (parameters != null ? ", parameters=" + getParameters().toString() : "") + "]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.miio.internal.basic;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

/**
* Mapping actions conditions
*
* @author Marcel Verpaalen - Initial contribution
*/
@NonNullByDefault
public class MiIoDeviceActionCondition {

@SerializedName("name")
@Expose
private @Nullable String name;
@SerializedName("parameters")
@Expose
private @Nullable JsonElement parameters;

public String getName() {
final @Nullable String command = this.name;
return command != null ? command : "";
}

public void setName(String command) {
this.name = command;
}

public JsonElement getParameters() {
final JsonElement parameter = this.parameters;
return parameter != null ? parameter : JsonNull.INSTANCE;
}

public void setParameters(JsonArray parameters) {
this.parameters = parameters;
}

@Override
public String toString() {
return "MiIoDeviceActionCondition [condition=" + name + ",parameters=" + getParameters().toString() + "]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public void setCredentials(@Nullable String username, @Nullable String password,

private boolean logon() {
if (username.isEmpty() || password.isEmpty()) {
logger.info("No Xiaomi cloud credentials. Cloud connectivity diabled");
logger.info("No Xiaomi cloud credentials. Cloud connectivity disabled");
logger.debug("Logon details: username: '{}', pass: '{}', country: '{}'", username,
password.replaceAll(".", "*"), country);
return connected;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ private void updateProperties(JsonObject miioInfo) {
if (info.mcuFwVer != null) {
properties.put("mcuFirmware", info.mcuFwVer);
}
deviceVariables.putAll(properties);
updateProperties(properties);
}

Expand Down
Loading

0 comments on commit b0cdb04

Please sign in to comment.