diff --git a/bundles/org.openhab.binding.shelly/README.md b/bundles/org.openhab.binding.shelly/README.md index 07d6e97ed..be851c340 100644 --- a/bundles/org.openhab.binding.shelly/README.md +++ b/bundles/org.openhab.binding.shelly/README.md @@ -90,6 +90,8 @@ The binding provides the same feature set across all devices as good as possible | shellyplusi4dc | Shelly Plus i4 with 4x DC input | SNSN-0D24X | | shellyplusht | Shelly Plus HT with temperature + humidity sensor | SNSN-0013A | | shellyplussmoke | Shelly Plus Smoke sensor | SNSN-0031Z | +| shellypluswdus | Shelly Plus Wall Dimmer US | SNDM-0013US | +| shellypluswalldisplay| Shelly Plus Wall Display | SAWD-0A1XX10EU1 | ### Generation 2 Pro series @@ -175,6 +177,7 @@ The binding can't communicate directly with the device, but the Plus/Pro series The binding automatically installs a script on the Shelly Device (oh-blu-scanner), which forwards the BLU events to the binding using the WebSocket channel. Follow these steps to add the Shelly BLU Device to openHAB + - Make sure a Shelly is near by the BLU device, enable Bluetooh on this device (the Bluetooth Gateway mode is not required) - Add this thing to openHAB, make sure thing gets online - Enable "BLU Gateway Support" in the thing configuration of the Shelly device acting as gateway. @@ -1202,6 +1205,16 @@ Channels lastEvent and eventCount are only available if input type is set to mom | battery | batteryLevel | Number | yes | Battery Level in % | | | lowBattery | Switch | yes | Low battery alert (< 20%) | +### Shelly Plus Wall Dimmer US (thing-type: shellypluswdus) + +|Group | Channel |Type |read-only |Description | +|-------|-------------|---------|----------|------------------------------------------------------------------------------------| +| relay | brightness | Dimmer | r/w | Currently selected brightness. | +| | outputName | String | yes | Logical name of this relay output as configured in the Shelly App | +| | autoOn | Number | r/w | Relay #1: Sets a timer to turn the device ON after every OFF command; in seconds | +| | autoOff | Number | r/w | Relay #1: Sets a timer to turn the device OFF after every ON command; in seconds | +| | timerActive | Switch | yes | Relay #1: ON: An auto-on/off timer is active | +| ## Shelly Pro Series @@ -1405,6 +1418,22 @@ See notes on discovery of Shelly BLU devices above. | | lowBattery | Switch | yes | Low battery alert (< 20%) | | device | gatewayDevice | String | yes | Shelly forwarded last status update (BLU gateway), could vary from packet to packet | +## Shelly Wall Displays + +| Group | Channel | Type | read-only | Description | +| ------- | ----------- | -------- | --------- | --------------------------------------------------------------------------------- | +| relay | output | Switch | r/w | Controls the relay's output channel (on/off) | +| | outputName | String | yes | Logical name of this relay output as configured in the Shelly App | +| | input | Switch | yes | ON: Input/Button is powered, see General Notes on Channels | +| | autoOn | Number | r/w | Relay #1: Sets a timer to turn the device ON after every OFF command; in seconds | +| | autoOff | Number | r/w | Relay #1: Sets a timer to turn the device OFF after every ON command; in seconds | +| | timerActive | Switch | yes | Relay #1: ON: An auto-on/off timer is active | +| | button | Trigger | yes | Event trigger, see section Button Events | +| sensors | temperature | Number | yes | Temperature reported by the integrated sensor | +| | humidity | Number | yes | Relative Humidity in percent reported by the integrated sensor | +| | lux | Number | yes | Brightness in Lux reported by the integrated sensor | +| | lastUpdate | DateTime | yes | Timestamp of the last update (any sensor value changed) | + ## Full Example ### shelly.things diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java index 6ef2c453f..c80e6b09c 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java @@ -67,10 +67,22 @@ public class ShellyBindingConstants { THING_TYPE_SHELLYBUTTON1, // THING_TYPE_SHELLYBUTTON2, // THING_TYPE_SHELLMOTION, // + + // Shelly Plus THING_TYPE_SHELLYPLUS1, // THING_TYPE_SHELLYPLUS1PM, // THING_TYPE_SHELLYPLUS2PM_RELAY, // THING_TYPE_SHELLYPLUS2PM_ROLLER, // + THING_TYPE_SHELLYPLUSI4, // + THING_TYPE_SHELLYPLUSI4DC, // + THING_TYPE_SHELLYPLUSHT, // + THING_TYPE_SHELLYPLUSSMOKE, // + THING_TYPE_SHELLYPLUSPLUGS, // + THING_TYPE_SHELLYPLUSPLUGUS, // + THING_TYPE_SHELLYPLUSDIMMERUS, // + THING_TYPE_SHELLYPLUSWALLDISPLAY, // + + // Shelly Pro THING_TYPE_SHELLYPRO1, // THING_TYPE_SHELLYPRO1PM, // THING_TYPE_SHELLYPRO2_RELAY, // @@ -79,14 +91,11 @@ public class ShellyBindingConstants { THING_TYPE_SHELLYPRO3, // THING_TYPE_SHELLYPRO3EM, // THING_TYPE_SHELLYPRO4PM, // - THING_TYPE_SHELLYPLUSI4, // - THING_TYPE_SHELLYPLUSI4DC, // - THING_TYPE_SHELLYPLUSHT, // - THING_TYPE_SHELLYPLUSSMOKE, // - THING_TYPE_SHELLYPLUSPLUGS, // - THING_TYPE_SHELLYPLUSPLUGUS, // + + // Shelly BLU THING_TYPE_SHELLYBLUBUTTON, // THING_TYPE_SHELLYBLUDW, // + THING_TYPE_SHELLYPROTECTED, // THING_TYPE_SHELLYUNKNOWN); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java index 6230bbeb0..2fcb6f711 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java @@ -102,6 +102,8 @@ public class ShellyDeviceProfile { public boolean isIX = false; // true for a Shelly IX public boolean isTRV = false; // true for a Shelly TRV public boolean isSmoke = false; // true for Shelly Smoke + public boolean isWall = false; // true: Shelly Wall Display + public boolean is3EM = false; // true for Shelly 3EM and Pro 3EM public int minTemp = 0; // Bulb/Duo: Min Light Temp public int maxTemp = 0; // Bulb/Duo: Max Light Temp @@ -138,9 +140,8 @@ public class ShellyDeviceProfile { name = getString(settings.name); deviceType = getString(settings.device.type); mac = getString(settings.device.mac); - hostname = settings.device.hostname != null && !settings.device.hostname.isEmpty() - ? settings.device.hostname.toLowerCase() - : "shelly-" + mac.toUpperCase().substring(6, 11); + hostname = !getString(settings.device.hostname).isEmpty() ? settings.device.hostname.toLowerCase() + : mac.length() >= 12 ? "shelly-" + mac.toUpperCase().substring(6, 11) : "unknown"; mode = getString(settings.mode).toLowerCase(); hwRev = settings.hwinfo != null ? getString(settings.hwinfo.hwRevision) : ""; hwBatchId = settings.hwinfo != null ? getString(settings.hwinfo.batchId.toString()) : ""; @@ -193,7 +194,9 @@ public class ShellyDeviceProfile { isBlu = thingType.startsWith("shellyblu"); // e.g. SBBT for BU Button - isDimmer = deviceType.equalsIgnoreCase(SHELLYDT_DIMMER) || deviceType.equalsIgnoreCase(SHELLYDT_DIMMER2); + isDimmer = deviceType.equalsIgnoreCase(SHELLYDT_DIMMER) || deviceType.equalsIgnoreCase(SHELLYDT_DIMMER2) + || deviceType.equalsIgnoreCase(SHELLYDT_PLUSDIMMERUS) + || thingType.equalsIgnoreCase(THING_TYPE_SHELLYPLUSDIMMERUS_STR); isBulb = thingType.equals(THING_TYPE_SHELLYBULB_STR); isDuo = thingType.equals(THING_TYPE_SHELLYDUO_STR) || thingType.equals(THING_TYPE_SHELLYVINTAGE_STR) || thingType.equals(THING_TYPE_SHELLYDUORGBW_STR); @@ -217,10 +220,13 @@ public class ShellyDeviceProfile { || thingType.equals(THING_TYPE_SHELLYPLUSI4DC_STR); isButton = thingType.equals(THING_TYPE_SHELLYBUTTON1_STR) || thingType.equals(THING_TYPE_SHELLYBUTTON2_STR) || thingType.equals(THING_TYPE_SHELLYBLUBUTTON_STR); - isSensor = isHT || isFlood || isDW || isSmoke || isGas || isButton || isUNI || isMotion || isSense || isTRV; - hasBattery = isHT || isFlood || isDW || isSmoke || isButton || isMotion || isTRV; isTRV = thingType.equals(THING_TYPE_SHELLYTRV_STR); + isWall = thingType.equals(THING_TYPE_SHELLYPLUSWALLDISPLAY_STR); + is3EM = thingType.equals(THING_TYPE_SHELLY3EM_STR) || thingType.equals(THING_TYPE_SHELLYPRO3EM_STR); + isSensor = isHT || isFlood || isDW || isSmoke || isGas || isButton || isUNI || isMotion || isSense || isTRV + || isWall; + hasBattery = isHT || isFlood || isDW || isSmoke || isButton || isMotion || isTRV; alwaysOn = !hasBattery || isMotion || isSense; // true means: device is reachable all the time (no sleep mode) } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java index 44f87beb0..c5304fe4e 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1ApiJsonDTO.java @@ -405,6 +405,7 @@ public class Shelly1ApiJsonDTO { public String pushShortUrl; // to access when roller stopped // Status information + public Integer id; public Boolean ison; public Boolean overpower; @SerializedName("is_valid") @@ -756,7 +757,7 @@ public class Shelly1ApiJsonDTO { public ShellyStatusSensor.ShellyExtSwitchStatus extSwitch; // Internal device temp - public ShellySensorTmp tmp = new ShellySensorTmp(); // Shelly 1PM + public ShellySensorTmp tmp; // Shelly 1PM public Double temperature; // Shelly 2.5 public Boolean overtemperature; @@ -825,6 +826,8 @@ public class Shelly1ApiJsonDTO { public Integer brightness; // brightness: 0.100% @SerializedName("has_timer") public Boolean hasTimer; + @SerializedName("timer_duration") + public Integer timerDuration; } public static class ShellyStatusRelay { diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion1.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion1.java index 263da597a..d7116528d 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion1.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1CoIoTVersion1.java @@ -149,7 +149,7 @@ public class Shelly1CoIoTVersion1 extends Shelly1CoIoTProtocol implements Shelly break; case "current": updateChannel(updates, rGroup, CHANNEL_EMETER_CURRENT, - toQuantityType(getDouble(s.value), DIGITS_VOLT, Units.AMPERE)); + toQuantityType(getDouble(s.value), DIGITS_AMPERE, Units.AMPERE)); break; case "pf": updateChannel(updates, rGroup, CHANNEL_EMETER_PFACTOR, getDecimal(s.value)); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java index 5160f9ac9..d271e1c99 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java @@ -90,7 +90,9 @@ public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterfa @Override public ShellySettingsDevice getDeviceInfo() throws ShellyApiException { - return callApi(SHELLY_URL_DEVINFO, ShellySettingsDevice.class); + ShellySettingsDevice info = callApi(SHELLY_URL_DEVINFO, ShellySettingsDevice.class); + info.gen = 1; + return info; } @Override diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java index 3736bc300..5351ef096 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java @@ -32,12 +32,14 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyFavPos; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputState; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorTmp; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRoller; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortStatusRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor; @@ -49,16 +51,19 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSe import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyExtVoltage; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellySensorBat; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellySensorHum; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellySensorLux; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2AuthRequest; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2AuthResponse; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2DevConfigCover; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2DevConfigInput; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2DevConfigSwitch; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2GetConfigResult; +import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusLight; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2CoverStatus; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusEm; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusHumidity; +import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusIlluminance; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusPower; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusSmoke; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusTempId; @@ -164,6 +169,8 @@ public class Shelly2ApiClient extends ShellyHttpClient { } ShellySettingsRelay rsettings = new ShellySettingsRelay(); + rsettings.id = cs.id; + rsettings.isValid = cs.id != null; rsettings.name = cs.name; rsettings.ison = false; rsettings.autoOn = getBool(cs.autoOn) ? cs.autoOnDelay : 0; @@ -177,7 +184,10 @@ public class Shelly2ApiClient extends ShellyHttpClient { boolean channelUpdate) throws ShellyApiException { boolean updated = false; - if (result.temperature0 != null && !getProfile().isSensor) { + if (result.temperature0 != null && result.temperature0.tC != null && !getProfile().isSensor) { + if (status.tmp == null) { + status.tmp = new ShellySensorTmp(); + } status.temperature = status.tmp.tC = result.temperature0.tC; } @@ -188,12 +198,14 @@ public class Shelly2ApiClient extends ShellyHttpClient { updated |= updateRelayStatus(status, result.switch3, channelUpdate); updated |= updateEmStatus(status, result.em0, channelUpdate); updated |= updateRollerStatus(status, result.cover0, channelUpdate); + updated |= updateDimmerStatus(status, result.light0, channelUpdate); if (channelUpdate) { updated |= ShellyComponents.updateMeters(getThing(), status); } updateHumidityStatus(sensorData, result.humidity0); updateTemperatureStatus(sensorData, result.temperature0); + updateIlluminanceStatus(sensorData, result.illuminance0); updateSmokeStatus(sensorData, result.smoke0); updateBatteryStatus(sensorData, result.devicepower0); updateAddonStatus(status, result); @@ -222,7 +234,13 @@ public class Shelly2ApiClient extends ShellyHttpClient { int duration = (int) (now() - rs.timerStartetAt); sr.timerRemaining = duration; } + if (status.tmp == null) { + status.tmp = new ShellySensorTmp(); + } if (rs.temperature != null) { + if (status.tmp == null) { + status.tmp = new ShellySensorTmp(); + } status.tmp.isValid = true; status.tmp.tC = rs.temperature.tC; status.tmp.tF = rs.temperature.tF; @@ -231,8 +249,6 @@ public class Shelly2ApiClient extends ShellyHttpClient { if (status.temperature == null || getDouble(rs.temperature.tC) > status.temperature) { status.temperature = sr.temperature; } - } else { - status.tmp.isValid = false; } if (rs.voltage != null) { if (status.voltage == null || rs.voltage > status.voltage) { @@ -250,11 +266,11 @@ public class Shelly2ApiClient extends ShellyHttpClient { ShellySettingsMeter sm = new ShellySettingsMeter(); ShellySettingsEMeter emeter = status.emeters.get(rs.id); - sm.isValid = emeter.isValid = true; if (rs.apower != null) { sm.power = emeter.power = rs.apower; } if (rs.aenergy != null) { + // Gen2 reports Watt, needs to be converted to W/h sm.total = emeter.total = rs.aenergy.total; sm.counters = rs.aenergy.byMinute; sm.timestamp = rs.aenergy.minuteTs; @@ -278,6 +294,12 @@ public class Shelly2ApiClient extends ShellyHttpClient { private void updateMeter(ShellySettingsStatus status, int id, ShellySettingsMeter sm, ShellySettingsEMeter emeter, boolean channelUpdate) throws ShellyApiException { + if (getProfile().numMeters == 0) { + return; + } + sm.isValid = sm.power != null || sm.total != null; + emeter.isValid = emeter.current != null || emeter.voltage != null || emeter.power != null; + emeter.isValid = emeter.current != null || emeter.voltage != null || emeter.power != null; status.meters.set(id, sm); status.emeters.set(id, emeter); relayStatus.meters.set(id, sm); @@ -301,7 +323,6 @@ public class Shelly2ApiClient extends ShellyHttpClient { ShellySettingsMeter sm = new ShellySettingsMeter(); ShellySettingsEMeter emeter = status.emeters.get(0); - sm.isValid = emeter.isValid = true; if (em.aActPower != null) { sm.power = emeter.power = em.aActPower; } @@ -322,7 +343,6 @@ public class Shelly2ApiClient extends ShellyHttpClient { sm = new ShellySettingsMeter(); emeter = status.emeters.get(1); - sm.isValid = emeter.isValid = true; if (em.bActPower != null) { sm.power = emeter.power = em.bActPower; } @@ -446,6 +466,9 @@ public class Shelly2ApiClient extends ShellyHttpClient { rs.duration = (int) (now() - cs.moveStartedAt.longValue()); } if (cs.temperature != null && cs.temperature.tC > getDouble(status.temperature)) { + if (status.tmp == null) { + status.tmp = new ShellySensorTmp(); + } status.temperature = status.tmp.tC = getDouble(cs.temperature.tC); } if (cs.apower != null) { @@ -482,6 +505,46 @@ public class Shelly2ApiClient extends ShellyHttpClient { return updateChannels ? ShellyComponents.updateRoller((ShellyBaseHandler) getThing(), rs, cs.id) : false; } + protected void fillDimmerSettings(ShellyDeviceProfile profile, Shelly2GetConfigResult dc) { + if (!profile.isDimmer || dc.light0 == null) { + return; + } + + if (profile.settings.dimmers != null) { + ShellySettingsDimmer ds = profile.settings.dimmers.get(0); + ds.autoOn = dc.light0.autoOnDelay; + ds.autoOff = dc.light0.autoOffDelay; + ds.name = dc.light0.name; + profile.settings.dimmers.set(0, ds); + } + } + + private boolean updateDimmerStatus(ShellySettingsStatus status, @Nullable Shelly2DeviceStatusLight value, + boolean channelUpdate) throws ShellyApiException { + ShellyDeviceProfile profile = getProfile(); + if (!profile.isDimmer || value == null) { + return false; + } + + ShellyShortLightStatus ds = status.dimmers.get(0); + if (value.brightness != null) { + ds.brightness = value.brightness.intValue(); + } + ds.ison = value.output; + ds.hasTimer = value.timerStartedAt != null; + ds.timerDuration = getDuration(value.timerStartedAt, value.timerDuration); + status.dimmers.set(0, ds); + return channelUpdate ? ShellyComponents.updateDimmers(getThing(), status) : false; + } + + protected @Nullable Integer getDuration(@Nullable Double timerStartedAt, @Nullable Integer timerDuration) { + if (timerStartedAt == null || timerDuration == null) { + return null; + } + int duration = (int) (now() - timerStartedAt.longValue()); + return duration <= timerDuration ? timerDuration - duration : 0; + } + // Addon private void updateAddonStatus(ShellySettingsStatus status, @Nullable Shelly2DeviceStatusResult ds) throws ShellyApiException { @@ -544,6 +607,18 @@ public class Shelly2ApiClient extends ShellyHttpClient { sdata.tmp.tF = value.tF; } + protected void updateIlluminanceStatus(ShellyStatusSensor sdata, @Nullable Shelly2DeviceStatusIlluminance value) { + if (value == null) { + return; + } + if (sdata.lux == null) { + sdata.lux = new ShellySensorLux(); + } + sdata.lux.isValid = value.lux != null; + sdata.lux.value = value.lux; + sdata.lux.illumination = value.illumination; + } + protected void updateSmokeStatus(ShellyStatusSensor sdata, @Nullable Shelly2DeviceStatusSmoke value) { if (value == null) { return; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java index 58dcddfb7..37ebc620a 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiJsonDTO.java @@ -47,6 +47,10 @@ public class Shelly2ApiJsonDTO { public static final String SHELLY2_COVER_CMD_OPEN = "Open"; public static final String SHELLY2_COVER_CMD_CLOSE = "Close"; public static final String SHELLY2_COVER_CMD_STOP = "Stop"; + public static final String SHELLYRPC_METHOD_LIGHT_STATUS = "Light.GetStatus"; + public static final String SHELLYRPC_METHOD_LIGHT_SET = "Light.Set"; + public static final String SHELLYRPC_METHOD_LIGHT_SETCONFIG = "Light.SetConfig"; + public static final String SHELLYRPC_METHOD_LED_SETCONFIG = "WD_UI.SetConfig"; public static final String SHELLYRPC_METHOD_WIFIGETCONG = "Wifi.GetConfig"; public static final String SHELLYRPC_METHOD_WIFISETCONG = "Wifi.SetConfig"; public static final String SHELLYRPC_METHOD_ETHGETCONG = "Eth.GetConfig"; @@ -56,6 +60,7 @@ public class Shelly2ApiJsonDTO { public static final String SHELLYRPC_METHOD_CLOUDSET = "Cloud.SetConfig"; public static final String SHELLYRPC_METHOD_WSGETCONFIG = "WS.GetConfig"; public static final String SHELLYRPC_METHOD_WSSETCONFIG = "WS.SetConfig"; + public static final String SHELLYRPC_METHOD_EMDATARESET = "EMData.DeleteAllData"; public static final String SHELLYRPC_METHOD_SMOKE_SETCONFIG = "Smoke.SetConfig"; public static final String SHELLYRPC_METHOD_SMOKE_MUTE = "Smoke.Mute"; public static final String SHELLYRPC_METHOD_SCRIPT_LIST = "Script.List"; @@ -151,6 +156,12 @@ public class Shelly2ApiJsonDTO { public static final String SHELLY2_WAKEUPOCAUSE_UPDATE = "status_update"; public static final String SHELLY2_WAKEUPOCAUSE_UNDEFINED = "undefined"; + // Dimmer US: LED power modes + public static final String SHELLY2_POWERLED_ON = "on"; + public static final String SHELLY2_POWERLED_OFF = "off"; + public static final String SHELLY2_POWERLED_MATCH = "match_output"; + public static final String SHELLY2_POWERLED_INVERT = "inverted_output"; + public class Shelly2DevConfigBle { public Boolean enable; } @@ -265,7 +276,7 @@ public class Shelly2ApiJsonDTO { } public class Shelly2DevConfigInput { - public String id; + public Integer id; public String name; public String type; public Boolean invert; @@ -276,7 +287,7 @@ public class Shelly2ApiJsonDTO { } public class Shelly2DevConfigSwitch { - public String id; + public Integer id; public String name; @SerializedName("in_mode") @@ -367,6 +378,41 @@ public class Shelly2ApiJsonDTO { public Boolean mute; } + public static class Shelly2GetConfigLight { + public static class Shelly2GetConfigLightDefault { + public Integer brightness; + } + + public static class Shelly2GetConfigLightNightMode { + public boolean enable; + public Integer brightness; + } + + public Integer id; + public String name; + @SerializedName("initial_state") + public String initialState; + @SerializedName("auto_on") + public Boolean autoOn; + @SerializedName("auto_off") + public Boolean autoOff; + @SerializedName("auto_on_delay") + public Double autoOnDelay; + @SerializedName("auto_off_delay") + public Double autoOffDelay; + @SerializedName("default") + public Shelly2GetConfigLightDefault defaultCfg; + @SerializedName("night_mode") + public Shelly2GetConfigLightNightMode nightMode; + } + + public class Shelly2DeviceConfigLed { + @SerializedName("sys_led_enable") + public Boolean sysLedEnable; + @SerializedName("power_led") + public String powerLed; + } + public static class Shelly2GetConfigResult { public class Shelly2DevConfigCloud { @@ -392,6 +438,8 @@ public class Shelly2ApiJsonDTO { public Shelly2DevConfigMqtt mqtt; public Shelly2DeviceConfigSys sys; public Shelly2DeviceConfigWiFi wifi; + @SerializedName("wd_ui") + public Shelly2DeviceConfigLed led; @SerializedName("input:0") public Shelly2DevConfigInput input0; @@ -417,6 +465,9 @@ public class Shelly2ApiJsonDTO { @SerializedName("cover:0") public Shelly2DevConfigCover cover0; + @SerializedName("light:0") + public Shelly2GetConfigLight light0; + @SerializedName("smoke:0") public Shelly2ConfigSmoke smoke0; } @@ -460,6 +511,17 @@ public class Shelly2ApiJsonDTO { public ArrayList errors;// shown only if at least one error is present. } + public static class Shelly2DeviceStatusLight { + public Integer id; + public String source; + public Boolean output; + public Double brightness; + @SerializedName("timer_started_at") + public Double timerStartedAt; + @SerializedName("timer_duration") + public Integer timerDuration; + } + public static class Shelly2DeviceStatusResult { public class Shelly2DeviceStatusBle { @@ -501,6 +563,12 @@ public class Shelly2ApiJsonDTO { public Double rh; } + public class Shelly2DeviceStatusIlluminance { + public Integer id; + public Double lux; + public String illumination; + } + public class Shelly2DeviceStatusVoltage { public Integer id; public Double voltage; @@ -618,6 +686,9 @@ public class Shelly2ApiJsonDTO { @SerializedName("cover:0") public Shelly2CoverStatus cover0; + @SerializedName("light:0") + public Shelly2DeviceStatusLight light0; + @SerializedName("temperature:0") public Shelly2DeviceStatusTempId temperature0; @SerializedName("temperature:100") @@ -635,6 +706,10 @@ public class Shelly2ApiJsonDTO { public Shelly2DeviceStatusHumidity humidity0; @SerializedName("humidity:100") public Shelly2DeviceStatusHumidity humidity100; + + @SerializedName("illuminance:0") + Shelly2DeviceStatusIlluminance illuminance0; + @SerializedName("smoke:0") public Shelly2DeviceStatusSmoke smoke0; @@ -751,6 +826,12 @@ public class Shelly2ApiJsonDTO { public Boolean autoOff; @SerializedName("auto_off_delay") public Double autoOffDelay; + + // WD_UI.SetConfig + @SerializedName("sys_led_enable") + public Boolean sysLedEnable; + @SerializedName("power_led") + public String powerLed; } public static class Shelly2RpcRequest { @@ -764,6 +845,11 @@ public class Shelly2ApiJsonDTO { public Integer pos; public Boolean on; + // Dimmer / Light + public Integer brightness; + @SerializedName("toggle_after") + public Integer toggleAfter; + // Shelly.SetAuth public String user; public String realm; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java index a1d9f69f5..2efb6c6c4 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java @@ -41,6 +41,7 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheck import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorSleepMode; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; @@ -60,6 +61,7 @@ import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceC import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfigAp; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfigAp.Shelly2DeviceConfigApRE; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceSettings; +import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusLight; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusSys.Shelly2DeviceStatusSysAvlUpdate; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2NotifyEvent; @@ -151,11 +153,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac @Override public void startScan() { - if (config.enableBluGateway) { - try { - installScript(SHELLY2_BLU_GWSCRIPT); - } catch (ShellyApiException e) { - } + try { + installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway); + } catch (ShellyApiException e) { } } @@ -206,6 +206,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac profile.deviceType = device.type; profile.mac = device.mac; profile.auth = device.auth; + profile.isGen2 = device.gen == 2; if (config.serviceName.isEmpty()) { config.serviceName = getString(profile.hostname); } @@ -275,7 +276,13 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } } - profile.status.dimmers = profile.isDimmer ? new ArrayList<>() : null; + if (profile.isDimmer) { + profile.settings.dimmers = new ArrayList<>(); + profile.settings.dimmers.add(new ShellySettingsDimmer()); + profile.status.dimmers = new ArrayList<>(); + profile.status.dimmers.add(new ShellyShortLightStatus()); + fillDimmerSettings(profile, dc); + } profile.status.lights = profile.isBulb ? new ArrayList<>() : null; profile.status.thermostats = profile.isTRV ? new ArrayList<>() : null; @@ -286,19 +293,25 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac checkSetWsCallback(); } + if (dc.led != null) { + profile.settings.ledStatusDisable = !getBool(dc.led.sysLedEnable); + profile.settings.ledPowerDisable = getString(dc.led.powerLed).equals("off"); + } + profile.initialized = true; if (!discovery) { getStatus(); // make sure profile.status is initialized (e.g,. relay/meter status) asyncApiRequest(SHELLYRPC_METHOD_GETSTATUS); // request periodic status updates from device try { - logger.debug("{}: BLU Gateway support enabled for this device: {}", thingName, config.enableBluGateway); - if (config.enableBluGateway) { - if (getBool(profile.settings.bluetooth)) { - installScript(SHELLY2_BLU_GWSCRIPT); - } else { - logger.debug("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName); + if (config.enableBluGateway != null) { + logger.debug("{}: BLU Gateway support is {} for this device", thingName, + config.enableBluGateway ? "enabled" : "disabled"); + boolean bluetooth = getBool(profile.settings.bluetooth); + if (config.enableBluGateway && !bluetooth) { + logger.info("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName); } + installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway && bluetooth); } } catch (ShellyApiException e) { logger.debug("{}: Device config failed", thingName, e); @@ -340,24 +353,34 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } } - protected void installScript(String script) throws ShellyApiException { - String json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_LIST)); - ShellyScriptListResponse scriptList = gson.fromJson(json, ShellyScriptListResponse.class); + protected void installScript(String script, boolean install) throws ShellyApiException { + ShellyScriptListResponse scriptList = apiRequest( + new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_LIST), ShellyScriptListResponse.class); Integer ourId = -1; String code = ""; - logger.debug("{}: Install or restart script {} on Shelly Device", thingName, script); + if (install) { + logger.debug("{}: Install or restart script {} on Shelly Device", thingName, script); + } boolean running = false, upload = false; - if (scriptList != null) { - for (ShellyScriptListEntry s : scriptList.scripts) { - if (s.name.startsWith(script)) { - ourId = s.id; - running = s.running; - logger.debug("{}: Script {} is already installed, id={}", thingName, script, ourId); - } + for (ShellyScriptListEntry s : scriptList.scripts) { + if (s.name.startsWith(script)) { + ourId = s.id; + running = s.running; + logger.debug("{}: Script {} is already installed, id={}", thingName, script, ourId); + break; } } + if (!install) { + if (ourId != -1) { + startScript(ourId, false); + enableScript(script, false); + logger.debug("{}: Script {} was disabledd, id={}", thingName, script, ourId); + } + return; + } + // get script code from bundle resources String file = BUNDLE_RESOURCE_SCRIPTS + "/" + script; ClassLoader cl = Shelly2ApiRpc.class.getClassLoader(); @@ -380,8 +403,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } else { try { // verify that the same code version is active (avoid unnesesary flash updates) - json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_GETCODE).withId(ourId)); - ShellyScriptResponse rsp = gson.fromJson(json, ShellyScriptResponse.class); + ShellyScriptResponse rsp = apiRequest( + new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_GETCODE).withId(ourId), + ShellyScriptResponse.class); if (!rsp.data.trim().equals(code.trim())) { logger.debug("{}: A script version was found, update to newest one", thingName); upload = true; @@ -397,27 +421,26 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } if (restart || (running && upload)) { - json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_STOP).withId(ourId)); // first stop running script + startScript(ourId, false); running = false; } if (upload && ourId != -1) { // Delete existing script logger.debug("{}: Delete existing script", thingName); - json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_DELETE).withId(ourId)); + apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_DELETE).withId(ourId)); } if (upload) { logger.debug("{}: Script will be installed...", thingName); // Create new script, get id - json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_CREATE).withName(script)); - ShellyScriptResponse rsp = gson.fromJson(json, ShellyScriptResponse.class); - if (rsp != null) { - ourId = rsp.id; - logger.debug("{}: Script has been created, id={}", thingName, ourId); - upload = true; - } + ShellyScriptResponse rsp = apiRequest( + new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_CREATE).withName(script), + ShellyScriptResponse.class); + ourId = rsp.id; + logger.debug("{}: Script has been created, id={}", thingName, ourId); + upload = true; } if (upload) { @@ -437,17 +460,40 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac parms.append = true; } while (processed < length); running = false; - - Shelly2RpcRequestParams params = new Shelly2RpcRequestParams().withConfig(); - params.config.enable = true; - apiRequest(SHELLYRPC_METHOD_SCRIPT_SETCONFIG, params, String.class); + } + if (enableScript(script, true)) { + logger.info("{}: Script {} was {} installed successful", thingName, thingName, script); } if (!running) { - // Script was created or is there and stopped -> start it - json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_START).withId(ourId)); - logger.debug("{}: Script {} was {} successful", thingName, script, - restart ? "restarted" : "installed and started"); + running = startScript(ourId, true); + } + logger.info("{}: Script {} {}", thingName, script, + running ? "was successfully (re)started" : "failed to start"); + } + + private boolean startScript(int ourId, boolean start) { + if (ourId != -1) { + try { + apiRequest(new Shelly2RpcRequest() + .withMethod(start ? SHELLYRPC_METHOD_SCRIPT_START : SHELLYRPC_METHOD_SCRIPT_STOP) + .withId(ourId)); + return true; + } catch (ShellyApiException e) { + } + } + return false; + } + + private boolean enableScript(String script, boolean enable) { + try { + Shelly2RpcRequestParams params = new Shelly2RpcRequestParams().withConfig(); + params.config.name = script; + params.config.enable = enable; + apiRequest(SHELLYRPC_METHOD_SCRIPT_SETCONFIG, params, String.class); + return true; + } catch (ShellyApiException e) { + return false; } } @@ -519,6 +565,15 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS)); } + if (status.meters.size() > 0) { + boolean validMeter = false; + for (ShellySettingsMeter meter : status.meters) { + validMeter |= meter.isValid; + } + if (!validMeter) { + profile.numMeters = 0; + } + } profile.status = status; if (updated) { getThing().restartWatchdog(); @@ -765,6 +820,44 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_COVER_SETPOS).withId(relayIndex).withPos(position)); } + @Override + public ShellyStatusLight getLightStatus() throws ShellyApiException { + throw new ShellyApiException("API call not implemented"); + } + + @Override + public ShellyShortLightStatus getLightStatus(int index) throws ShellyApiException { + ShellyShortLightStatus status = new ShellyShortLightStatus(); + Shelly2DeviceStatusLight ls = apiRequest( + new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_LIGHT_STATUS).withId(index), + Shelly2DeviceStatusLight.class); + status.ison = ls.output; + status.hasTimer = ls.timerStartedAt != null; + status.timerDuration = getDuration(ls.timerStartedAt, ls.timerDuration); + if (ls.brightness != null) { + status.brightness = ls.brightness.intValue(); + } + return status; + } + + @Override + public void setBrightness(int id, int brightness, boolean autoOn) throws ShellyApiException { + Shelly2RpcRequestParams params = new Shelly2RpcRequestParams(); + params.id = id; + params.brightness = brightness; + params.on = brightness > 0; + apiRequest(SHELLYRPC_METHOD_LIGHT_SET, params, String.class); + } + + @Override + public ShellyShortLightStatus setLightTurn(int id, String turnMode) throws ShellyApiException { + Shelly2RpcRequestParams params = new Shelly2RpcRequestParams(); + params.id = id; + params.on = turnMode.equals(SHELLY_API_ON); + apiRequest(SHELLYRPC_METHOD_LIGHT_SET, params, String.class); + return getLightStatus(id); + } + @Override public ShellyStatusSensor getSensorStatus() throws ShellyApiException { return sensorData; @@ -772,10 +865,13 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac @Override public void setAutoTimer(int index, String timerName, double value) throws ShellyApiException { - Shelly2RpcRequest req = new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SWITCH_SETCONFIG).withId(index); - + ShellyDeviceProfile profile = getProfile(); + boolean isLight = profile.isLight || profile.isDimmer; + String method = isLight ? SHELLYRPC_METHOD_LIGHT_SETCONFIG : SHELLYRPC_METHOD_SWITCH_SETCONFIG; + String component = isLight ? "Light" : "Switch"; + Shelly2RpcRequest req = new Shelly2RpcRequest().withMethod(method).withId(index); req.params.withConfig(); - req.params.config.name = "Switch" + index; + req.params.config.name = component + index; if (timerName.equals(SHELLY_TIMER_AUTOON)) { req.params.config.autoOn = value > 0; req.params.config.autoOnDelay = value; @@ -786,8 +882,23 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac apiRequest(req); } + @Override + public void setLedStatus(String ledName, boolean value) throws ShellyApiException { + Shelly2RpcRequestParams params = new Shelly2RpcRequestParams().withConfig(); + params.id = 0; + if (ledName.equals(SHELLY_LED_STATUS_DISABLE)) { + params.config.sysLedEnable = value; + } else if (ledName.equals(SHELLY_LED_POWER_DISABLE)) { + params.config.powerLed = value ? SHELLY2_POWERLED_OFF : SHELLY2_POWERLED_MATCH; + } else { + throw new ShellyApiException("API call not implemented for this LED type"); + } + apiRequest(SHELLYRPC_METHOD_LED_SETCONFIG, params, Shelly2WsConfigResult.class); + } + @Override public void resetMeterTotal(int id) throws ShellyApiException { + apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_EMDATARESET).withId(id)); } @Override @@ -899,20 +1010,6 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac * The following API calls are not yet relevant, because currently there a no Plus/Pro (Gen2) devices of those * categories (e.g. bulbs) */ - @Override - public void setLedStatus(String ledName, boolean value) throws ShellyApiException { - throw new ShellyApiException("API call not implemented"); - } - - @Override - public ShellyStatusLight getLightStatus() throws ShellyApiException { - throw new ShellyApiException("API call not implemented"); - } - - @Override - public ShellyShortLightStatus getLightStatus(int index) throws ShellyApiException { - throw new ShellyApiException("API call not implemented"); - } @Override public void setLightParm(int lightIndex, String parm, String value) throws ShellyApiException { @@ -924,16 +1021,6 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac throw new ShellyApiException("API call not implemented"); } - @Override - public ShellyShortLightStatus setLightTurn(int id, String turnMode) throws ShellyApiException { - throw new ShellyApiException("API call not implemented"); - } - - @Override - public void setBrightness(int id, int brightness, boolean autoOn) throws ShellyApiException { - throw new ShellyApiException("API call not implemented"); - } - @Override public void setLightMode(String mode) throws ShellyApiException { throw new ShellyApiException("API call not implemented"); @@ -1058,10 +1145,12 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac if (response.result != null) { // return sub element result as requested class type json = gson.toJson(gson.fromJson(json, Shelly2RpcBaseMessage.class).result); - return fromJson(gson, json, classOfT); + boolean isString = response.result instanceof String; + return fromJson(gson, isString && ((String) response.result).equalsIgnoreCase("null") ? "{}" : json, + classOfT); } else { // return direct format - return gson.fromJson(json, classOfT); + return gson.fromJson(json, classOfT == String.class ? Shelly2RpcBaseMessage.class : classOfT); } } @@ -1069,8 +1158,8 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac return apiRequest(request.method, request.params, classOfT); } - public String apiRequest(Shelly2RpcRequest request) throws ShellyApiException { - return apiRequest(request.method, request.params, String.class); + public void apiRequest(Shelly2RpcRequest request) throws ShellyApiException { + apiRequest(request.method, request.params, Shelly2RpcBaseMessage.class); } private String rpcPost(String postData) throws ShellyApiException { diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpctInterface.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpctInterface.java index 82ffdee92..4387db141 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpctInterface.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpctInterface.java @@ -24,15 +24,15 @@ import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2RpcNoti @NonNullByDefault public interface Shelly2RpctInterface { - public void onConnect(String deviceIp, boolean connected); + void onConnect(String deviceIp, boolean connected); - public void onMessage(String decodedmessage); + void onMessage(String decodedmessage); - public void onNotifyStatus(Shelly2RpcNotifyStatus message); + void onNotifyStatus(Shelly2RpcNotifyStatus message); - public void onNotifyEvent(Shelly2RpcNotifyEvent message); + void onNotifyEvent(Shelly2RpcNotifyEvent message); - public void onClose(int statusCode, String reason); + void onClose(int statusCode, String reason); - public void onError(Throwable cause); + void onError(Throwable cause); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java index eb7ed5091..b08e74edb 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/config/ShellyThingConfiguration.java @@ -44,5 +44,5 @@ public class ShellyThingConfiguration { public String localPort = "8080"; public String serviceName = ""; - public boolean enableBluGateway = false; + public Boolean enableBluGateway = false; } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java index 664047b90..b142c6291 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyThingCreator.java @@ -79,6 +79,8 @@ public class ShellyThingCreator { public static final String SHELLYDT_PLUSI4DC = "SNSN-0D24X"; public static final String SHELLYDT_PLUSHT = "SNSN-0013A"; public static final String SHELLYDT_PLUSSMOKE = "SNSN-0031Z"; + public static final String SHELLYDT_PLUSDIMMERUS = "SNDM-0013US"; + public static final String SHELLYDT_PLUSWALLDISPLAY = "SAWD-0A1XX10EU1"; // Shelly Pro Series public static final String SHELLYDT_PRO1 = "SPSW-001XE16EU"; @@ -157,6 +159,8 @@ public class ShellyThingCreator { public static final String THING_TYPE_SHELLYPLUSSMOKE_STR = "shellyplussmoke"; public static final String THING_TYPE_SHELLYPLUSPLUGS_STR = "shellyplusplug"; public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus"; + public static final String THING_TYPE_SHELLYPLUSDIMMERUS_STR = "shellypluswdus"; + public static final String THING_TYPE_SHELLYPLUSWALLDISPLAY_STR = "shellywalldisplay"; // Shelly Pro Series public static final String THING_TYPE_SHELLYPRO1_STR = "shellypro1"; @@ -233,7 +237,7 @@ public class ShellyThingCreator { public static final ThingTypeUID THING_TYPE_SHELLYUNKNOWN = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYUNKNOWN_STR); - // Shelly Plus/Pro + // Shelly Plus public static final ThingTypeUID THING_TYPE_SHELLYPLUS1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUS1_STR); public static final ThingTypeUID THING_TYPE_SHELLYPLUS1PM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUS1PM_STR); @@ -253,6 +257,12 @@ public class ShellyThingCreator { THING_TYPE_SHELLYPLUSPLUGS_STR); public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGUS = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUSPLUGUS_STR); + public static final ThingTypeUID THING_TYPE_SHELLYPLUSDIMMERUS = new ThingTypeUID(BINDING_ID, + THING_TYPE_SHELLYPLUSDIMMERUS_STR); + public static final ThingTypeUID THING_TYPE_SHELLYPLUSWALLDISPLAY = new ThingTypeUID(BINDING_ID, + THING_TYPE_SHELLYPLUSWALLDISPLAY_STR); + + // Shelly Pro public static final ThingTypeUID THING_TYPE_SHELLYPRO1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO1_STR); public static final ThingTypeUID THING_TYPE_SHELLYPRO1PM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO1PM_STR); @@ -317,6 +327,7 @@ public class ShellyThingCreator { THING_TYPE_MAPPING.put(SHELLYDT_PLUSI4, THING_TYPE_SHELLYPLUSI4_STR); THING_TYPE_MAPPING.put(SHELLYDT_PLUSHT, THING_TYPE_SHELLYPLUSHT_STR); THING_TYPE_MAPPING.put(SHELLYDT_PLUSSMOKE, THING_TYPE_SHELLYPLUSSMOKE_STR); + THING_TYPE_MAPPING.put(SHELLYDT_PLUSDIMMERUS, THING_TYPE_SHELLYPLUSDIMMERUS_STR); // Pro Series THING_TYPE_MAPPING.put(SHELLYDT_PRO1, THING_TYPE_SHELLYPRO1_STR); @@ -343,6 +354,9 @@ public class ShellyThingCreator { THING_TYPE_MAPPING.put(SHELLYDT_BLUBUTTON, THING_TYPE_SHELLYBLUBUTTON_STR); THING_TYPE_MAPPING.put(SHELLYDT_BLUDW, THING_TYPE_SHELLYBLUDW_STR); + // Wall displays + THING_TYPE_MAPPING.put(SHELLYDT_PLUSWALLDISPLAY, THING_TYPE_SHELLYPLUSWALLDISPLAY_STR); + // mapping by thing type THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1_STR, THING_TYPE_SHELLY1_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1PM_STR, THING_TYPE_SHELLY1PM_STR); @@ -385,6 +399,8 @@ public class ShellyThingCreator { THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSI4_STR, THING_TYPE_SHELLYPLUSI4_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSHT_STR, THING_TYPE_SHELLYPLUSHT_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSSMOKE_STR, THING_TYPE_SHELLYPLUSSMOKE_STR); + THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSDIMMERUS_STR, THING_TYPE_SHELLYPLUSDIMMERUS_STR); + THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSWALLDISPLAY_STR, THING_TYPE_SHELLYPLUSWALLDISPLAY_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO1_STR, THING_TYPE_SHELLYPRO1_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO1PM_STR, THING_TYPE_SHELLYPRO1PM_STR); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java index 3e6e0a229..bdea3aa76 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java @@ -20,22 +20,28 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.shelly.internal.api.ShellyApiException; import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyADC; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyExtTemperature.ShellyShortTemp; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat; import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions; +import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.Units; import org.openhab.core.types.UnDefType; +import com.google.gson.Gson; + /*** * The{@link ShellyComponents} implements updates for supplemental components * Meter will be used by Relay + Light; Sensor is part of H&T, Flood, Door Window, Sense @@ -69,14 +75,12 @@ public class ShellyComponents { Integer rssi = getInteger(status.wifiSta.rssi); thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_RSSI, mapSignalStrength(rssi)); - if (getDouble(status.temperature) != SHELLY_API_INVTEMP) { - if (status.tmp != null && !thingHandler.getProfile().isSensor) { - thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, - toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS)); - } else if (status.temperature != null) { - thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, - toQuantityType(getDouble(status.temperature), DIGITS_NONE, SIUnits.CELSIUS)); - } + if (status.tmp != null && !thingHandler.getProfile().isSensor && status.tmp.tC != SHELLY_API_INVTEMP) { + thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, + toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS)); + } else if (status.temperature != null && status.temperature != SHELLY_API_INVTEMP) { + thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, + toQuantityType(getDouble(status.temperature), DIGITS_NONE, SIUnits.CELSIUS)); } thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_SLEEPTIME, toQuantityType(getInteger(status.sleepTime), Units.SECOND)); @@ -268,8 +272,8 @@ public class ShellyComponents { .createEMeterChannels(thingHandler.getThing(), profile, emeter, groupName)); } - // convert Watt/Hour to kw/h - double total = getDouble(emeter.total) / 1000 / 60; + // convert Watt/h to KW/h + double total = getDouble(emeter.total) / 1000; double totalReturned = getDouble(emeter.totalReturned) / 1000; updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_CURRENTWATTS, toQuantityType(getDouble(emeter.power), DIGITS_WATT, Units.WATT)); @@ -332,7 +336,7 @@ public class ShellyComponents { // convert totalWatts into kw/h totalWatts = totalWatts / (60.0 * 1000.0); updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_CURRENTWATTS, - toQuantityType(getDouble(currentWatts), DIGITS_WATT, Units.WATT)); + toQuantityType(currentWatts, DIGITS_WATT, Units.WATT)); updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_TOTALKWH, toQuantityType(totalWatts, DIGITS_KWH, Units.KILOWATT_HOUR)); @@ -537,6 +541,64 @@ public class ShellyComponents { return updated; } + public static boolean updateDimmers(ShellyThingInterface thingHandler, ShellySettingsStatus orgStatus) + throws ShellyApiException { + boolean updated = false; + ShellyDeviceProfile profile = thingHandler.getProfile(); + if (profile.isDimmer) { + // We need to fixup the returned Json: The dimmer returns light[] element, which is ok, but it doesn't have + // the same structure as lights[] from Bulb,RGBW2 and Duo. The tag gets replaced by dimmers[] so that Gson + // maps to a different structure (ShellyShortLight). + Gson gson = new Gson(); + ShellySettingsStatus dstatus = !profile.isGen2 + ? fromJson(gson, Shelly1ApiJsonDTO.fixDimmerJson(orgStatus.json), ShellySettingsStatus.class) + : orgStatus; + + int l = 0; + for (ShellyShortLightStatus dimmer : dstatus.dimmers) { + Integer r = l + 1; + String groupName = profile.numRelays <= 1 ? CHANNEL_GROUP_DIMMER_CONTROL + : CHANNEL_GROUP_DIMMER_CONTROL + r.toString(); + + if (!thingHandler.areChannelsCreated()) { + thingHandler.updateChannelDefinitions(ShellyChannelDefinitions + .createDimmerChannels(thingHandler.getThing(), profile, dstatus, l)); + } + + ShellySettingsDimmer ds = profile.settings.dimmers.get(l); + if (ds.name != null) { + updated |= thingHandler.updateChannel(groupName, CHANNEL_OUTPUT_NAME, getStringType(ds.name)); + } + + // On a status update we map a dimmer.ison = false to brightness 0 rather than the device's brightness + // and send an OFF status to the same channel. + // When the device's brightness is > 0 we send the new value to the channel and an ON command + if (dimmer.ison) { + updated |= thingHandler.updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.ON); + updated |= thingHandler.updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", + toQuantityType((double) getInteger(dimmer.brightness), DIGITS_NONE, Units.PERCENT)); + } else { + updated |= thingHandler.updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.OFF); + updated |= thingHandler.updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", + toQuantityType(0.0, DIGITS_NONE, Units.PERCENT)); + } + + if (profile.settings.dimmers != null) { + ShellySettingsDimmer dsettings = profile.settings.dimmers.get(l); + if (dsettings != null) { + updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOON, + toQuantityType(getDouble(dsettings.autoOn), Units.SECOND)); + updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOOFF, + toQuantityType(getDouble(dsettings.autoOff), Units.SECOND)); + } + } + + l++; + } + } + return updated; + } + public static boolean updateTempChannel(@Nullable ShellyShortTemp sensor, ShellyThingInterface thingHandler, String channel) { return sensor != null ? updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, channel, sensor.tC, "") : false; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyDeviceListener.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyDeviceListener.java index 187c18759..98cbf7ea6 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyDeviceListener.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyDeviceListener.java @@ -28,6 +28,6 @@ public interface ShellyDeviceListener { /** * This method is called when new device information is received. */ - public boolean onEvent(String ipAddress, String deviceName, String deviceIndex, String eventType, + boolean onEvent(String ipAddress, String deviceName, String deviceIndex, String eventType, Map parameters); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java index ca15d5491..ce3895fd6 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyRelayHandler.java @@ -19,9 +19,7 @@ import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.shelly.internal.api.ShellyApiException; -import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; -import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus; @@ -42,8 +40,6 @@ import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.Gson; - /*** * The{@link ShellyRelayHandler} handles light (bulb+rgbw2) specific commands and status. All other commands will be * handled by the generic thing handler. @@ -193,7 +189,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler { if (brightness > 0) { api.setBrightness(lightId, brightness, config.brightnessAutoOn); } else { - api.setRelayTurn(lightId, power == OnOffType.ON ? SHELLY_API_ON : SHELLY_API_OFF); + api.setLightTurn(lightId, power == OnOffType.ON ? SHELLY_API_ON : SHELLY_API_OFF); if (brightness >= 0) { // ignore -1 updateChannel(CHANNEL_COLOR_WHITE, CHANNEL_BRIGHTNESS + "$Value", toQuantityType((double) (power == OnOffType.ON ? brightness : 0), DIGITS_NONE, Units.PERCENT)); @@ -206,7 +202,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler { // map status to channels boolean updated = false; updated |= updateRelays(status); - updated |= updateDimmers(status); + updated |= ShellyComponents.updateDimmers(this, status); updated |= updateLed(status); return updated; } @@ -300,12 +296,6 @@ public class ShellyRelayHandler extends ShellyBaseHandler { } } - private void createDimmerChannels(ShellySettingsStatus dstatus, int idx) { - if (!areChannelsCreated()) { - updateChannelDefinitions(ShellyChannelDefinitions.createDimmerChannels(getThing(), profile, dstatus, idx)); - } - } - private void createRollerChannels(ShellyRollerStatus roller) { if (!areChannelsCreated()) { updateChannelDefinitions(ShellyChannelDefinitions.createRollerChannels(getThing(), roller)); @@ -356,63 +346,6 @@ public class ShellyRelayHandler extends ShellyBaseHandler { return updated; } - /** - * Update Relay/Roller channels - * - * @param th Thing Handler instance - * @param profile ShellyDeviceProfile - * @param status Last ShellySettingsStatus - * - * @throws ShellyApiException - */ - public boolean updateDimmers(ShellySettingsStatus orgStatus) throws ShellyApiException { - boolean updated = false; - if (profile.isDimmer) { - // We need to fixup the returned Json: The dimmer returns light[] element, which is ok, but it doesn't have - // the same structure as lights[] from Bulb,RGBW2 and Duo. The tag gets replaced by dimmers[] so that Gson - // maps to a different structure (ShellyShortLight). - Gson gson = new Gson(); - ShellySettingsStatus dstatus = fromJson(gson, Shelly1ApiJsonDTO.fixDimmerJson(orgStatus.json), - ShellySettingsStatus.class); - - logger.trace("{}: Updating {} dimmers(s)", thingName, dstatus.dimmers.size()); - int l = 0; - for (ShellyShortLightStatus dimmer : dstatus.dimmers) { - Integer r = l + 1; - String groupName = profile.numRelays <= 1 ? CHANNEL_GROUP_DIMMER_CONTROL - : CHANNEL_GROUP_DIMMER_CONTROL + r.toString(); - - createDimmerChannels(dstatus, l); - - // On a status update we map a dimmer.ison = false to brightness 0 rather than the device's brightness - // and send an OFF status to the same channel. - // When the device's brightness is > 0 we send the new value to the channel and an ON command - if (dimmer.ison) { - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.ON); - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", - toQuantityType((double) getInteger(dimmer.brightness), DIGITS_NONE, Units.PERCENT)); - } else { - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Switch", OnOffType.OFF); - updated |= updateChannel(groupName, CHANNEL_BRIGHTNESS + "$Value", - toQuantityType(0.0, DIGITS_NONE, Units.PERCENT)); - } - - if (profile.settings.dimmers != null) { - ShellySettingsDimmer dsettings = profile.settings.dimmers.get(l); - if (dsettings != null) { - updated |= updateChannel(groupName, CHANNEL_TIMER_AUTOON, - toQuantityType(getDouble(dsettings.autoOn), Units.SECOND)); - updated |= updateChannel(groupName, CHANNEL_TIMER_AUTOOFF, - toQuantityType(getDouble(dsettings.autoOff), Units.SECOND)); - } - } - - l++; - } - } - return updated; - } - /** * Update LED channels * diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingInterface.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingInterface.java index 2285f66f2..5483b0ff1 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingInterface.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingInterface.java @@ -39,85 +39,86 @@ import org.openhab.core.types.StateOption; @NonNullByDefault public interface ShellyThingInterface { - public ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiException; + ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiException; - public @Nullable List getStateOptions(ChannelTypeUID uid); + @Nullable + List getStateOptions(ChannelTypeUID uid); - public double getChannelDouble(String group, String channel); + double getChannelDouble(String group, String channel); - public boolean updateChannel(String group, String channel, State value); + boolean updateChannel(String group, String channel, State value); - public boolean updateChannel(String channelId, State value, boolean force); + boolean updateChannel(String channelId, State value, boolean force); - public void setThingOnline(); + void setThingOnline(); - public void setThingOffline(ThingStatusDetail detail, String messageKey, Object... arguments); + void setThingOffline(ThingStatusDetail detail, String messageKey, Object... arguments); - public boolean isStopping(); + boolean isStopping(); - public String getThingType(); + String getThingType(); - public ThingStatus getThingStatus(); + ThingStatus getThingStatus(); - public ThingStatusDetail getThingStatusDetail(); + ThingStatusDetail getThingStatusDetail(); - public boolean isThingOnline(); + boolean isThingOnline(); - public boolean requestUpdates(int requestCount, boolean refreshSettings); + boolean requestUpdates(int requestCount, boolean refreshSettings); - public void triggerUpdateFromCoap(); + void triggerUpdateFromCoap(); - public void reinitializeThing(); + void reinitializeThing(); - public void restartWatchdog(); + void restartWatchdog(); - public void publishState(String channelId, State value); + void publishState(String channelId, State value); - public boolean areChannelsCreated(); + boolean areChannelsCreated(); - public State getChannelValue(String group, String channel); + State getChannelValue(String group, String channel); - public boolean updateInputs(ShellySettingsStatus status); + boolean updateInputs(ShellySettingsStatus status); - public void updateChannelDefinitions(Map dynChannels); + void updateChannelDefinitions(Map dynChannels); - public void postEvent(String event, boolean force); + void postEvent(String event, boolean force); - public void triggerChannel(String group, String channelID, String event); + void triggerChannel(String group, String channelID, String event); - public void triggerButton(String group, int idx, String value); + void triggerButton(String group, int idx, String value); - public ShellyDeviceStats getStats(); + ShellyDeviceStats getStats(); - public void resetStats(); + void resetStats(); - public Thing getThing(); + Thing getThing(); - public String getThingName(); + String getThingName(); - public ShellyThingConfiguration getThingConfig(); + ShellyThingConfiguration getThingConfig(); - public HttpClient getHttpClient(); + HttpClient getHttpClient(); - public String getProperty(String key); + String getProperty(String key); - public void updateProperties(String key, String value); + void updateProperties(String key, String value); - public boolean updateWakeupReason(@Nullable List valueArray); + boolean updateWakeupReason(@Nullable List valueArray); - public ShellyApiInterface getApi(); + ShellyApiInterface getApi(); - public ShellyDeviceProfile getProfile(); + ShellyDeviceProfile getProfile(); - public long getScheduledUpdates(); + long getScheduledUpdates(); - public void fillDeviceStatus(ShellySettingsStatus status, boolean updated); + void fillDeviceStatus(ShellySettingsStatus status, boolean updated); - public boolean checkRepresentation(String key); + boolean checkRepresentation(String key); - public void incProtMessages(); + void incProtMessages(); - public void incProtErrors(); + void incProtErrors(); - public void startScan(); + void startScan(); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java index 71dfe33d4..94ee50278 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java @@ -78,7 +78,7 @@ public class ShellyChannelDefinitions { public static final String ITEMT_POWER = "Number:Power"; public static final String ITEMT_ENERGY = "Number:Energy"; public static final String ITEMT_VOLT = "Number:ElectricPotential"; - public static final String ITEMT_AMP = "Number:ElectricPotential"; + public static final String ITEMT_AMP = "Number:ElectricCurrent"; public static final String ITEMT_ANGLE = "Number:Angle"; public static final String ITEMT_DISTANCE = "Number:Length"; public static final String ITEMT_SPEED = "Number:Speed"; @@ -129,8 +129,8 @@ public class ShellyChannelDefinitions { .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ITEMP, "deviceTemp", ITEMT_TEMP)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_WAKEUP, "sensorWakeup", ITEMT_STRING)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCUWATTS, "meterAccuWatts", ITEMT_POWER)) - .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL, "meterAccuTotal", ITEMT_POWER)) - .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCURETURNED, "meterAccuReturned", ITEMT_POWER)) + .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL, "meterAccuTotal", ITEMT_ENERGY)) + .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCURETURNED, "meterAccuReturned", ITEMT_ENERGY)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_VOLTAGE, "supplyVoltage", ITEMT_VOLT)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_CHARGER, "charger", ITEMT_SWITCH)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_LED_STATUS_DISABLE, "ledStatusDisable", ITEMT_SWITCH)) @@ -191,7 +191,7 @@ public class ShellyChannelDefinitions { // Power Meter .add(new ShellyChannel(m, CHGR_METER, CHANNEL_METER_CURRENTWATTS, "meterWatts", ITEMT_POWER)) .add(new ShellyChannel(m, CHGR_METER, CHANNEL_METER_TOTALKWH, "meterTotal", ITEMT_ENERGY)) - .add(new ShellyChannel(m, CHGR_METER, CHANNEL_METER_LASTMIN1, "lastPower1", ITEMT_ENERGY)) + .add(new ShellyChannel(m, CHGR_METER, CHANNEL_METER_LASTMIN1, "lastPower1", ITEMT_POWER)) .add(new ShellyChannel(m, CHGR_METER, CHANNEL_LAST_UPDATE, "lastUpdate", ITEMT_DATETIME)) // EMeter @@ -215,7 +215,7 @@ public class ShellyChannelDefinitions { .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION, "sensorMotion", ITEMT_SWITCH)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION_TS, "motionTimestamp", ITEMT_DATETIME)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION_ACT, "motionActive", ITEMT_SWITCH)) - .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VIBRATION, "vibration", ITEMT_SWITCH)) + .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VIBRATION, "sensorVibration", ITEMT_SWITCH)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_FLOOD, "sensorFlood", ITEMT_SWITCH)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_SMOKE, "sensorSmoke", ITEMT_SWITCH)) .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MUTE, "sensorMute", ITEMT_SWITCH)) @@ -304,13 +304,14 @@ public class ShellyChannelDefinitions { && ((status.temperature != null && getDouble(status.temperature) != SHELLY_API_INVTEMP) || (status.tmp != null && getDouble(status.tmp.tC) != SHELLY_API_INVTEMP))) { // Only some devices report the internal device temp - addChannel(thing, add, status.tmp != null || status.temperature != null, CHGR_DEVST, CHANNEL_DEVST_ITEMP); + addChannel(thing, add, + !profile.isLight && (status.temperature != null || (status.tmp != null && !profile.isSensor)), + CHGR_DEVST, CHANNEL_DEVST_ITEMP); } addChannel(thing, add, profile.settings.sleepTime != null, CHGR_SENSOR, CHANNEL_SENSOR_SLEEPTIME); // If device has more than 1 meter the channel accumulatedWatts receives the accumulated value - boolean accuChannel = (((status.meters != null) && (status.meters.size() > 1) && !profile.isRoller - && !profile.isRGBW2) || ((status.emeters != null && status.emeters.size() > 1))); + boolean accuChannel = profile.numMeters > 1 && !profile.isRoller && !profile.isRGBW2; addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUWATTS); addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL); addChannel(thing, add, accuChannel && (status.emeters != null), CHGR_DEVST, CHANNEL_DEVST_ACCURETURNED); @@ -350,9 +351,11 @@ public class ShellyChannelDefinitions { } // Shelly 1/1PM and Plus 1/1PM Addon - if (profile.settings.extSwitch != null && profile.settings.extSwitch.input0 != null - && idx == getInteger(profile.settings.extSwitch.input0.relayNum)) { - addChannel(thing, add, true, CHGR_SENSOR, CHANNEL_ESENSOR_INPUT + (idx + 1)); + boolean addon = profile.settings.extSwitch != null && profile.settings.extSwitch.input0 != null + && idx == getInteger(profile.settings.extSwitch.input0.relayNum); + if (addon) { + addChannel(thing, add, addon, CHGR_SENSOR, + CHANNEL_ESENSOR_INPUT + (profile.settings.extSwitch.input0.relayNum + 1)); } if (profile.status.extTemperature != null) { addChannel(thing, add, profile.status.extTemperature.sensor1 != null, CHGR_SENSOR, CHANNEL_ESENSOR_TEMP1); @@ -361,7 +364,8 @@ public class ShellyChannelDefinitions { addChannel(thing, add, profile.status.extTemperature.sensor4 != null, CHGR_SENSOR, CHANNEL_ESENSOR_TEMP4); addChannel(thing, add, profile.status.extTemperature.sensor5 != null, CHGR_SENSOR, CHANNEL_ESENSOR_TEMP5); } - addChannel(thing, add, profile.status.extHumidity != null, CHGR_SENSOR, CHANNEL_ESENSOR_HUMIDITY); + addChannel(thing, add, profile.status.extHumidity != null && profile.status.extHumidity.sensor1 != null, + CHGR_SENSOR, CHANNEL_ESENSOR_HUMIDITY); addChannel(thing, add, profile.status.extVoltage != null, CHGR_SENSOR, CHANNEL_ESENSOR_VOLTAGE); addChannel(thing, add, profile.status.extDigitalInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_DIGITALINPUT); addChannel(thing, add, profile.status.extAnalogInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_ANALOGINPUT); @@ -379,6 +383,7 @@ public class ShellyChannelDefinitions { if (profile.settings.dimmers != null) { ShellySettingsDimmer ds = profile.settings.dimmers.get(idx); + addChannel(thing, add, ds.name != null, group, CHANNEL_OUTPUT_NAME); addChannel(thing, add, ds.autoOn != null, group, CHANNEL_TIMER_AUTOON); addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF); ShellyShortLightStatus dss = dstatus.dimmers.get(idx); @@ -473,7 +478,7 @@ public class ShellyChannelDefinitions { addChannel(thing, newChannels, emeter.voltage != null, group, CHANNEL_EMETER_VOLTAGE); addChannel(thing, newChannels, emeter.current != null, group, CHANNEL_EMETER_CURRENT); addChannel(thing, newChannels, emeter.pf != null, group, CHANNEL_EMETER_PFACTOR); // EM has no PF. but power - addChannel(thing, newChannels, emeter.total != null && profile.numMeters > 1, group, CHANNEL_EMETER_RESETTOTAL); // 3EM + addChannel(thing, newChannels, profile.is3EM, group, CHANNEL_EMETER_RESETTOTAL); // 3EM addChannel(thing, newChannels, true, group, CHANNEL_LAST_UPDATE); return newChannels; } @@ -505,7 +510,8 @@ public class ShellyChannelDefinitions { addChannel(thing, newChannels, sdata.sensor.vibration != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION); } - if (sdata.accel != null) { // DW2 + // Create tilt for DW/DW2, for BLU DW create channel even tilt is currently not reported + if (sdata.accel != null || (profile.isBlu && sdata.lux != null)) { addChannel(thing, newChannels, sdata.accel.tilt != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TILT); } diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml index bdc569513..bc212f828 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/config/config2.xml @@ -89,4 +89,33 @@ true + + + + + @text/thing-type.config.shelly.deviceIp.description + network-address + + + + @text/thing-type.config.shelly.userId.description + + + + @text/thing-type.config.shelly.password.description + password + + + + @text/thing-type.config.shelly.light.brightnessAutoOn.description + true + + + + @text/thing-type.config.shelly.updateInterval.description + 60 + seconds + true + + diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties index 94d969f5a..ba3a49206 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties @@ -88,6 +88,22 @@ thing-type.shelly.shellytrv.description = Shelly TRV (Radiator value, battery po thing-type.shelly.shellyix3.description = Shelly ix3 (Activation Device with 3 inputs) thing-type.shelly.shellypludht.description = Shelly Plus HT - Temperature and Humidity Sensor +# Plus Devices +thing-type.shelly.shellyplus1.description = Shelly Plus 1 (Single Relay Switch) +thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - Single Relay Switch with Power Meter +thing-type.shelly.shellyplus2-relay.description = Shelly Plus 2PM - Dual Relay Switch with Power Meter +thing-type.shelly.shellyplus2pm-roller.description = Shelly Plus 2PM - Roller Control with Power Meter +thing-type.shelly.shellyplusplug.description = Shelly Plus Plug S/IT/UK/US . Outlet with Power Meter +thing-type.shelly.shellyplusi4.description = Shelly Plus i4 - 4xInput Device +thing-type.shelly.shellyplusi4dc.description = Shelly Plus i4DC - 4xDC Input Device +thing-type.shelly.shellyplusht.description = Shelly Plus HT - Humidity and Temperature sensor with display +thing-type.shelly.shellyplussmoke.description = Shelly Plus Smoke - Smoke Detector with Alarm +thing-type.shelly.shellyplussmoke.description = Shelly Plus Smoke - Smoke Detector with Alarm +thing-type.shelly.shellypluswdus.description = Shelly Wall Dimmer US Device + +# Wall displays +thing-type.shelly.shellywalldisplay.description = Shelly Plus Wall Display with sensors and input/output + # Pro Devices thing-type.shelly.shellypro1.description = Shelly Pro 1 - Single Relay Switch thing-type.shelly.shellypro1pm.description = Shelly Pro 1PM - Single Relay Switch with Power Meter @@ -97,31 +113,10 @@ thing-type.shelly.shellypro2pm-roller.description = Shelly Pro 2PM - Roller Cont thing-type.shelly.shellypro3.description = Shelly Pro 3 - 3xRelay Switch thing-type.shelly.shellypro3em.description = Shelly Pro 3EM - 3xPower Meter thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter - -# Plus devices - thing-type.shelly.shellyplus1.description = Shelly Plus 1 (Single Relay Switch) - thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - Single Relay Switch with Power Meter - thing-type.shelly.shellyplus2-relay.description = Shelly Plus 2PM - Dual Relay Switch with Power Meter - thing-type.shelly.shellyplus2pm-roller.description = Shelly Plus 2PM - Roller Control with Power Meter - thing-type.shelly.shellyplusplug.description = Shelly Plus Plug S/IT/UK/US . Outlet with Power Meter - thing-type.shelly.shellyplusht.description = Shelly Plus HT - Humidity and Temperature sensor with display - thing-type.shelly.shellyplussmoke.description = Shelly Plus Smoke - Smoke Detector with Alarm - thing-type.shelly.shellyplusi4.description = Shelly Plus i4 - 4xInput Device - thing-type.shelly.shellyplusi4dc.description = Shelly Plus i4DC - 4xDC Input Device - # Pro devices - thing-type.shelly.shellypro1.description = Shelly Pro 1 - Single Relay Switch - thing-type.shelly.shellypro1pm.description = Shelly Pro 1PM - Single Relay Switch with Power Meter - thing-type.shelly.shellypro2-relay.description = Shelly Pro 2 - Dual Relay Switch - thing-type.shelly.shellypro2-roller.description = Shelly Pro 2 - Roller Control - thing-type.shelly.shellypro2pm-relay.description= Shelly Pro 2PM - Dual Relay Switch with Power Meter - thing-type.shelly.shellypro2pm-roller.description = Shelly Pro 2PM - Roller Control with Power Meter - thing-type.shelly.shellypro3.description = Shelly Pro 3 - 3xRelay Switch - thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter - - # BLU devices - thing-type.shelly.shellypblubutton.description = Shelly BLU Button - thing-type.shelly.shellybludw.description = Shelly BLU Door/Window Sensor +# BLU devices +thing-type.shelly.shellypblubutton.description = Shelly BLU Button +thing-type.shelly.shellybludw.description = Shelly BLU Door/Window Sensor # thing config - shellydevice thing-type.config.shelly.deviceIp.label = IP Address diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml index e7e5e13ef..ee99d0129 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen1_relay.xml @@ -479,7 +479,7 @@ Energy Measurement - Current + Power @@ -490,24 +490,36 @@ @text/channel-type.shelly.meterAccuWatts.description Energy + + Measurement + Power + - Number:Power + Number:Energy @text/channel-type.shelly.meterAccuTotal.description Energy + + Measurement + Energy + - Number:Power + Number:Energy @text/channel-type.shelly.meterAccuReturned.description Energy + + Measurement + Energy + @@ -521,10 +533,14 @@ - Number:Energy + Number:Power @text/channel-type.shelly.lastPower1.description Energy + + Measurement + Power + @@ -533,7 +549,6 @@ Number:Energy @text/channel-type.shelly.meterTotal.description - Energy @@ -543,6 +558,10 @@ @text/channel-type.shelly.meterReturned.description Energy + + Measurement + Energy + @@ -551,6 +570,7 @@ Number:ElectricPotential @text/channel-type.shelly.meterVoltage.description + Energy Measurement Voltage @@ -560,13 +580,13 @@ - Number:ElectricPotential + Number:ElectricCurrent @text/channel-type.shelly.meterCurrent.description Energy Measurement - Power + Current diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml index d98a8440b..51722ee74 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_relay.xml @@ -290,4 +290,18 @@ + + + @text/thing-type.shelly.shellypluswdus.description + DimmableLight + + + + + + + serviceName + + + diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_sensor.xml b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_sensor.xml index 3b3384b28..482379537 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_sensor.xml +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/thing/shellyGen2_sensor.xml @@ -32,4 +32,16 @@ + + + @text/thing-type.shelly.shellywalldisplay.description + Sensor + + + + + + serviceName + + diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js b/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js index a7b73899f..c02dbc953 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js +++ b/bundles/org.openhab.binding.shelly/src/main/resources/scripts/oh-blu-scanner.js @@ -1,6 +1,7 @@ /* * This script uses the BLE scan functionality in scripting to pass scan reults to openHAB * Supported BLU Devices: SBBT , SBDW + * Version 0.2 */ let ALLTERCO_DEVICE_NAME_PREFIX = ["SBBT", "SBDW"]; @@ -147,21 +148,11 @@ function scanCB(ev, res) { } } -// retry several times to start the scanner if script was started before -// BLE infrastructure was up in the Shelly -function startBLEScan() { - let bleScanSuccess = BLE.Scanner.Start({ duration_ms: SCAN_DURATION, active: true }, scanCB); - if( bleScanSuccess === false ) { - Timer.set(1000, false, startBLEScan); - } else { - console.log('Success: OH-BLU Event Gateway running'); - } -} - let BLEConfig = Shelly.getComponentConfig('ble'); if(BLEConfig.enable === false) { - console.log('Error: BLE not enabled'); + console.log('Error: BLE not enabled, unable to start OH-BLU Scanner'); } else { - Timer.set(1000, false, startBLEScan); + BLE.Scanner.Start({ duration_ms: SCAN_DURATION, active: true }, scanCB); + console.log('OH-BLU Event Gateway running'); } - \ No newline at end of file + \ No newline at end of file