[miio] Add support gateway lumi.gateway.mieu01 (#10893)

Signed-off-by: Marcel Verpaalen <marcel@verpaalen.com>
This commit is contained in:
Marcel
2021-06-21 22:07:17 +02:00
committed by GitHub
parent ea2cb217e0
commit 809e53d3af
6 changed files with 346 additions and 11 deletions

View File

@@ -94,7 +94,8 @@ public enum MiIoDevices {
LUMI_GATEWAY_MGL03("lumi.gateway.mgl03", "Mi Air Purifier virtual", THING_TYPE_BASIC),
LUMI_GATEWAY_V1("lumi.gateway.v1", "Mi smart Home Gateway Hub v1", THING_TYPE_BASIC),
LUMI_GATEWAY_V2("lumi.gateway.v2", "Mi smart Home GatewayHub v2", THING_TYPE_BASIC),
LUMI_GATEWAY_V3("lumi.gateway.v3", "Mi mart Home Gateway Hub v3", THING_TYPE_BASIC),
LUMI_GATEWAY_V3("lumi.gateway.v3", "Mi smart Home Gateway Hub v3", THING_TYPE_BASIC),
LUMI_GATEWAY_MIEU01("lumi.gateway.mieu01", "Mi smart Home Gateway Hub", THING_TYPE_BASIC),
MIDEA_AIRCONDITION_V1("midea.aircondition.v1", "Midea AC-i Youth", THING_TYPE_UNSUPPORTED),
MIDEA_AIRCONDITION_V2("midea.aircondition.v2", "Midea Air Conditioner v2", THING_TYPE_UNSUPPORTED),
MIDEA_AIRCONDITION_XA1("midea.aircondition.xa1", "Midea AC-Cool Golden", THING_TYPE_UNSUPPORTED),

View File

@@ -12,6 +12,7 @@
*/
package org.openhab.binding.miio.internal.basic;
import java.awt.Color;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -69,6 +70,23 @@ public class ActionConditions {
return value;
}
/**
* Convert HSV value to RGB+Brightness
*
* @param value
* @return RGB value + brightness as first byte
*/
private static @Nullable JsonElement HsvToBRGB(@Nullable Command command, @Nullable JsonElement value) {
if (command != null && command instanceof HSBType) {
HSBType hsb = (HSBType) command;
Color color = Color.getHSBColor(hsb.getHue().floatValue() / 360, hsb.getSaturation().floatValue() / 100,
hsb.getBrightness().floatValue() / 100);
return new JsonPrimitive((hsb.getBrightness().byteValue() << 24) + (color.getRed() << 16)
+ (color.getGreen() << 8) + color.getBlue());
}
return null;
}
/**
* Check if the value is a valid brightness between 1-100 which can be send to brightness channel.
* If not returns a null
@@ -152,6 +170,8 @@ public class ActionConditions {
return firmwareCheck(condition, deviceVariables, value);
case "BRIGHTNESSEXISTING":
return brightnessExists(value);
case "HSVTOBRGB":
return HsvToBRGB(command, value);
case "BRIGHTNESSONOFF":
return brightness(value);
case "HSBONLY":

View File

@@ -12,7 +12,11 @@
*/
package org.openhab.binding.miio.internal.basic;
import java.awt.Color;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.PercentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,6 +32,23 @@ import com.google.gson.JsonPrimitive;
public class Conversions {
private static final Logger LOGGER = LoggerFactory.getLogger(Conversions.class);
/**
* Converts a RGB+brightness input to a HSV value.
* *
*
* @param RGB + brightness value (note brightness in the first byte)
* @return HSV
*/
public static JsonElement bRGBtoHSV(JsonElement bRGB) throws ClassCastException {
if (bRGB.isJsonPrimitive() && bRGB.getAsJsonPrimitive().isNumber()) {
Color rgb = new Color(bRGB.getAsInt());
HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(bRGB.getAsInt() >>> 24));
return new JsonPrimitive(hsb.toFullString());
}
return bRGB;
}
public static JsonElement secondsToHours(JsonElement seconds) throws ClassCastException {
double value = seconds.getAsDouble() / 3600;
return new JsonPrimitive(value);
@@ -86,6 +107,8 @@ public class Conversions {
return divideHundred(value);
case "TANKLEVEL":
return tankLevel(value);
case "BRGBTOHSV":
return bRGBtoHSV(value);
default:
LOGGER.debug("Transformation {} not found. Returning '{}'", transfortmation, value.toString());
return value;

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -322,6 +323,11 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
private void refreshCustomProperties(MiIoBasicDevice midevice) {
for (MiIoBasicChannel miChannel : refreshListCustomCommands.values()) {
if (!isLinked(miChannel.getChannel())) {
logger.debug("Skip refresh of channel {} for {} as it is not linked", miChannel.getChannel(),
getThing().getUID());
continue;
}
sendCommand(miChannel.getChannelCustomRefreshCommand());
}
}
@@ -380,6 +386,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
}
if (hasChannelStructure) {
refreshList = new ArrayList<>();
refreshListCustomCommands = new HashMap<>();
final MiIoBasicDevice miioDevice = this.miioDevice;
if (miioDevice != null) {
for (MiIoBasicChannel miChannel : miioDevice.getDevice().getChannels()) {
@@ -475,7 +482,7 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
ChannelTypeUID channelTypeUID = new ChannelTypeUID(miChannel.getChannelType());
if (channelTypeRegistry.getChannelType(channelTypeUID) != null) {
newChannel = newChannel.withType(channelTypeUID);
final Set<String> tags = miChannel.getTags();
final LinkedHashSet<String> tags = miChannel.getTags();
if (tags != null && !tags.isEmpty()) {
newChannel.withDefaultTags(tags);
}
@@ -575,7 +582,11 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
updateState(basicChannel.getChannel(), new PercentType(val.getAsBigDecimal()));
break;
case "string":
updateState(basicChannel.getChannel(), new StringType(val.getAsString()));
if (val.isJsonPrimitive()) {
updateState(basicChannel.getChannel(), new StringType(val.getAsString()));
} else {
updateState(basicChannel.getChannel(), new StringType(val.toString()));
}
break;
case "switch":
if (val.getAsJsonPrimitive().isNumber()) {
@@ -587,9 +598,19 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
}
break;
case "color":
Color rgb = new Color(val.getAsInt());
HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
updateState(basicChannel.getChannel(), hsb);
if (val.isJsonPrimitive() && val.getAsJsonPrimitive().isNumber()) {
Color rgb = new Color(val.getAsInt());
HSBType hsb = HSBType.fromRGB(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
updateState(basicChannel.getChannel(), hsb);
} else {
try {
HSBType hsb = HSBType.valueOf(val.getAsString().replace("[", "").replace("]", ""));
updateState(basicChannel.getChannel(), hsb);
} catch (IllegalArgumentException e) {
logger.debug("Failed updating channel '{}'. Could not convert '{}' to color",
basicChannel.getChannel(), val.getAsString());
}
}
break;
default:
logger.debug("No update logic for channeltype '{}' ", basicChannel.getType());
@@ -658,7 +679,8 @@ public class MiIoBasicHandler extends MiIoAbstractHandler {
break;
default:
if (refreshListCustomCommands.containsKey(response.getMethod())) {
logger.debug("Processing custom refresh command response for !{}", response.getMethod());
logger.debug("Processing custom refresh command response for '{}' - {}", response.getMethod(),
response.getResult());
final MiIoBasicChannel ch = refreshListCustomCommands.get(response.getMethod());
if (ch != null) {
if (response.getResult().isJsonArray()) {

View File

@@ -0,0 +1,229 @@
{
"deviceMapping": {
"id": [
"lumi.gateway.mieu01"
],
"propertyMethod": "get_prop",
"maxProperties": 4,
"channels": [
{
"property": "get_arming",
"friendlyName": "Guard",
"channel": "guard",
"type": "Switch",
"refresh": true,
"customRefreshCommand": "get_arming",
"actions": [
{
"command": "set_arming",
"parameterType": "ONOFF"
}
],
"category": "alarm",
"tags": [
"Alarm"
]
},
{
"property": "corridor_light",
"friendlyName": "Automatic Night Light",
"channel": "corridor",
"type": "Switch",
"refresh": true,
"actions": [
{
"command": "set_corridor_light",
"parameterType": "ONOFF"
}
],
"category": "light",
"tags": [
"Switch"
]
},
{
"property": "night_light_rgb",
"friendlyName": "Night Light",
"channel": "nightlight",
"type": "Color",
"refresh": true,
"transformation": "bRGBtoHSV",
"actions": [
{
"command": "set_night_light_rgb",
"parameterType": "COLOR",
"condition": {
"name": "HSVTOBRGB"
}
}
],
"category": "colorpicker",
"tags": [
"Control",
"Light"
]
},
{
"property": "rgb",
"friendlyName": "Colored Light",
"channel": "rgb",
"type": "Color",
"refresh": true,
"transformation": "bRGBtoHSV",
"actions": [
{
"command": "set_rgb",
"parameterType": "NUMBER",
"condition": {
"name": "HSVTOBRGB"
}
}
],
"category": "colorpicker",
"tags": [
"Control",
"Light"
]
},
{
"property": "doorbell_volume",
"friendlyName": "Doorbell Volume",
"channel": "doorbell_volume",
"type": "Number",
"refresh": true,
"actions": [
{
"command": "set_doorbell_volume",
"parameterType": "NUMBER"
}
],
"category": "soundvolume",
"tags": [
"Setpoint",
"SoundVolume"
]
},
{
"property": "alarming_volume",
"friendlyName": "Alarming Volume",
"channel": "alarming_volume",
"type": "Number",
"refresh": true,
"actions": [
{
"command": "set_alarming_volume",
"parameterType": "NUMBER"
}
],
"category": "soundvolume",
"tags": [
"Setpoint",
"SoundVolume"
]
},
{
"property": "gateway_volume",
"friendlyName": "Gateway Volume",
"channel": "gateway_volume",
"type": "Number",
"refresh": true,
"actions": [
{
"command": "set_gateway_volume",
"parameterType": "NUMBER"
}
],
"category": "soundvolume",
"tags": [
"Setpoint",
"SoundVolume"
]
},
{
"property": "get_arming_time",
"friendlyName": "Arming Time",
"channel": "arming_time",
"type": "Number:Time",
"unit": "seconds",
"refresh": true,
"customRefreshCommand": "get_arming_time",
"actions": [
{
"command": "set_alarming_time",
"parameterType": "NUMBER"
}
],
"category": "time",
"tags": [
"Setpoint",
"Duration"
]
},
{
"property": "corridor_on_time",
"friendlyName": "Corridor on time",
"channel": "corridor_on_time",
"type": "Number:Time",
"unit": "seconds",
"refresh": true,
"actions": [
{
"command": "set_corridor_on_time",
"parameterType": "NUMBER"
}
],
"category": "time",
"tags": [
"Setpoint",
"Duration"
]
},
{
"property": "language",
"friendlyName": "Voice prompt Language",
"channel": "language",
"type": "String",
"refresh": true,
"customRefreshCommand": "get_device_prop[\"lumi.0\",\"gateway_lang\"]",
"actions": [],
"category": "settings"
},
{
"property": "get_zigbee_channel",
"friendlyName": "Zigbee Channel",
"channel": "zigbee_channel",
"type": "String",
"refresh": true,
"customRefreshCommand": "get_zigbee_channel",
"actions": [],
"category": "settings"
},
{
"property": "lumi_bind",
"friendlyName": "Lumi_bind info",
"channel": "lumi_bind",
"type": "String",
"refresh": true,
"customRefreshCommand": "get_lumi_bind",
"actions": [],
"category": "settings"
},
{
"property": "doorbell_push",
"friendlyName": "Doorbell Push",
"channel": "doorbell_push",
"type": "String",
"refresh": true,
"actions": [
{
"command": "set_doorbell_push",
"parameterType": "STRING"
}
],
"category": "settings"
}
],
"readmeComment": "Used to control the gateway itself. Controlling child devices currently only possible via rules",
"experimental": false
}
}