[shelly] Add support for Shelly Wall Dimmer US and Wall Display (#15051)

Signed-off-by: Markus Michels <markus7017@gmail.com>
This commit is contained in:
Markus Michels 2023-07-08 17:05:49 +02:00 committed by GitHub
parent 5629d75d60
commit 5bea9bcfdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 663 additions and 285 deletions

View File

@ -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 | | shellyplusi4dc | Shelly Plus i4 with 4x DC input | SNSN-0D24X |
| shellyplusht | Shelly Plus HT with temperature + humidity sensor | SNSN-0013A | | shellyplusht | Shelly Plus HT with temperature + humidity sensor | SNSN-0013A |
| shellyplussmoke | Shelly Plus Smoke sensor | SNSN-0031Z | | 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 ### 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. 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 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) - 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 - 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. - 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 % | | battery | batteryLevel | Number | yes | Battery Level in % |
| | lowBattery | Switch | yes | Low battery alert (< 20%) | | | 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 ## Shelly Pro Series
@ -1405,6 +1418,22 @@ See notes on discovery of Shelly BLU devices above.
| | lowBattery | Switch | yes | Low battery alert (< 20%) | | | lowBattery | Switch | yes | Low battery alert (< 20%) |
| device | gatewayDevice | String | yes | Shelly forwarded last status update (BLU gateway), could vary from packet to packet | | 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 ## Full Example
### shelly.things ### shelly.things

View File

@ -67,10 +67,22 @@ public class ShellyBindingConstants {
THING_TYPE_SHELLYBUTTON1, // THING_TYPE_SHELLYBUTTON1, //
THING_TYPE_SHELLYBUTTON2, // THING_TYPE_SHELLYBUTTON2, //
THING_TYPE_SHELLMOTION, // THING_TYPE_SHELLMOTION, //
// Shelly Plus
THING_TYPE_SHELLYPLUS1, // THING_TYPE_SHELLYPLUS1, //
THING_TYPE_SHELLYPLUS1PM, // THING_TYPE_SHELLYPLUS1PM, //
THING_TYPE_SHELLYPLUS2PM_RELAY, // THING_TYPE_SHELLYPLUS2PM_RELAY, //
THING_TYPE_SHELLYPLUS2PM_ROLLER, // 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_SHELLYPRO1, //
THING_TYPE_SHELLYPRO1PM, // THING_TYPE_SHELLYPRO1PM, //
THING_TYPE_SHELLYPRO2_RELAY, // THING_TYPE_SHELLYPRO2_RELAY, //
@ -79,14 +91,11 @@ public class ShellyBindingConstants {
THING_TYPE_SHELLYPRO3, // THING_TYPE_SHELLYPRO3, //
THING_TYPE_SHELLYPRO3EM, // THING_TYPE_SHELLYPRO3EM, //
THING_TYPE_SHELLYPRO4PM, // THING_TYPE_SHELLYPRO4PM, //
THING_TYPE_SHELLYPLUSI4, //
THING_TYPE_SHELLYPLUSI4DC, // // Shelly BLU
THING_TYPE_SHELLYPLUSHT, //
THING_TYPE_SHELLYPLUSSMOKE, //
THING_TYPE_SHELLYPLUSPLUGS, //
THING_TYPE_SHELLYPLUSPLUGUS, //
THING_TYPE_SHELLYBLUBUTTON, // THING_TYPE_SHELLYBLUBUTTON, //
THING_TYPE_SHELLYBLUDW, // THING_TYPE_SHELLYBLUDW, //
THING_TYPE_SHELLYPROTECTED, // THING_TYPE_SHELLYPROTECTED, //
THING_TYPE_SHELLYUNKNOWN); THING_TYPE_SHELLYUNKNOWN);

View File

@ -102,6 +102,8 @@ public class ShellyDeviceProfile {
public boolean isIX = false; // true for a Shelly IX public boolean isIX = false; // true for a Shelly IX
public boolean isTRV = false; // true for a Shelly TRV public boolean isTRV = false; // true for a Shelly TRV
public boolean isSmoke = false; // true for Shelly Smoke 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 minTemp = 0; // Bulb/Duo: Min Light Temp
public int maxTemp = 0; // Bulb/Duo: Max Light Temp public int maxTemp = 0; // Bulb/Duo: Max Light Temp
@ -138,9 +140,8 @@ public class ShellyDeviceProfile {
name = getString(settings.name); name = getString(settings.name);
deviceType = getString(settings.device.type); deviceType = getString(settings.device.type);
mac = getString(settings.device.mac); mac = getString(settings.device.mac);
hostname = settings.device.hostname != null && !settings.device.hostname.isEmpty() hostname = !getString(settings.device.hostname).isEmpty() ? settings.device.hostname.toLowerCase()
? settings.device.hostname.toLowerCase() : mac.length() >= 12 ? "shelly-" + mac.toUpperCase().substring(6, 11) : "unknown";
: "shelly-" + mac.toUpperCase().substring(6, 11);
mode = getString(settings.mode).toLowerCase(); mode = getString(settings.mode).toLowerCase();
hwRev = settings.hwinfo != null ? getString(settings.hwinfo.hwRevision) : ""; hwRev = settings.hwinfo != null ? getString(settings.hwinfo.hwRevision) : "";
hwBatchId = settings.hwinfo != null ? getString(settings.hwinfo.batchId.toString()) : ""; 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 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); isBulb = thingType.equals(THING_TYPE_SHELLYBULB_STR);
isDuo = thingType.equals(THING_TYPE_SHELLYDUO_STR) || thingType.equals(THING_TYPE_SHELLYVINTAGE_STR) isDuo = thingType.equals(THING_TYPE_SHELLYDUO_STR) || thingType.equals(THING_TYPE_SHELLYVINTAGE_STR)
|| thingType.equals(THING_TYPE_SHELLYDUORGBW_STR); || thingType.equals(THING_TYPE_SHELLYDUORGBW_STR);
@ -217,10 +220,13 @@ public class ShellyDeviceProfile {
|| thingType.equals(THING_TYPE_SHELLYPLUSI4DC_STR); || thingType.equals(THING_TYPE_SHELLYPLUSI4DC_STR);
isButton = thingType.equals(THING_TYPE_SHELLYBUTTON1_STR) || thingType.equals(THING_TYPE_SHELLYBUTTON2_STR) isButton = thingType.equals(THING_TYPE_SHELLYBUTTON1_STR) || thingType.equals(THING_TYPE_SHELLYBUTTON2_STR)
|| thingType.equals(THING_TYPE_SHELLYBLUBUTTON_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); 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) alwaysOn = !hasBattery || isMotion || isSense; // true means: device is reachable all the time (no sleep mode)
} }

View File

@ -405,6 +405,7 @@ public class Shelly1ApiJsonDTO {
public String pushShortUrl; // to access when roller stopped public String pushShortUrl; // to access when roller stopped
// Status information // Status information
public Integer id;
public Boolean ison; public Boolean ison;
public Boolean overpower; public Boolean overpower;
@SerializedName("is_valid") @SerializedName("is_valid")
@ -756,7 +757,7 @@ public class Shelly1ApiJsonDTO {
public ShellyStatusSensor.ShellyExtSwitchStatus extSwitch; public ShellyStatusSensor.ShellyExtSwitchStatus extSwitch;
// Internal device temp // Internal device temp
public ShellySensorTmp tmp = new ShellySensorTmp(); // Shelly 1PM public ShellySensorTmp tmp; // Shelly 1PM
public Double temperature; // Shelly 2.5 public Double temperature; // Shelly 2.5
public Boolean overtemperature; public Boolean overtemperature;
@ -825,6 +826,8 @@ public class Shelly1ApiJsonDTO {
public Integer brightness; // brightness: 0.100% public Integer brightness; // brightness: 0.100%
@SerializedName("has_timer") @SerializedName("has_timer")
public Boolean hasTimer; public Boolean hasTimer;
@SerializedName("timer_duration")
public Integer timerDuration;
} }
public static class ShellyStatusRelay { public static class ShellyStatusRelay {

View File

@ -149,7 +149,7 @@ public class Shelly1CoIoTVersion1 extends Shelly1CoIoTProtocol implements Shelly
break; break;
case "current": case "current":
updateChannel(updates, rGroup, CHANNEL_EMETER_CURRENT, updateChannel(updates, rGroup, CHANNEL_EMETER_CURRENT,
toQuantityType(getDouble(s.value), DIGITS_VOLT, Units.AMPERE)); toQuantityType(getDouble(s.value), DIGITS_AMPERE, Units.AMPERE));
break; break;
case "pf": case "pf":
updateChannel(updates, rGroup, CHANNEL_EMETER_PFACTOR, getDecimal(s.value)); updateChannel(updates, rGroup, CHANNEL_EMETER_PFACTOR, getDecimal(s.value));

View File

@ -90,7 +90,9 @@ public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterfa
@Override @Override
public ShellySettingsDevice getDeviceInfo() throws ShellyApiException { 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 @Override

View File

@ -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.ShellyInputState;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus; 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.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.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput; 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.ShellySettingsMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay; 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.ShellySettingsRoller;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; 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.ShellyShortStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor; 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.ShellyExtVoltage;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellySensorBat; 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.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.Shelly2AuthRequest;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2AuthResponse; 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.Shelly2DevConfigCover;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2DevConfigInput; 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.Shelly2DevConfigSwitch;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2GetConfigResult; 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;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2CoverStatus; 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.Shelly2DeviceStatusEm;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusHumidity; 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.Shelly2DeviceStatusPower;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusSmoke; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusSmoke;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusTempId; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusTempId;
@ -164,6 +169,8 @@ public class Shelly2ApiClient extends ShellyHttpClient {
} }
ShellySettingsRelay rsettings = new ShellySettingsRelay(); ShellySettingsRelay rsettings = new ShellySettingsRelay();
rsettings.id = cs.id;
rsettings.isValid = cs.id != null;
rsettings.name = cs.name; rsettings.name = cs.name;
rsettings.ison = false; rsettings.ison = false;
rsettings.autoOn = getBool(cs.autoOn) ? cs.autoOnDelay : 0; rsettings.autoOn = getBool(cs.autoOn) ? cs.autoOnDelay : 0;
@ -177,7 +184,10 @@ public class Shelly2ApiClient extends ShellyHttpClient {
boolean channelUpdate) throws ShellyApiException { boolean channelUpdate) throws ShellyApiException {
boolean updated = false; 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; status.temperature = status.tmp.tC = result.temperature0.tC;
} }
@ -188,12 +198,14 @@ public class Shelly2ApiClient extends ShellyHttpClient {
updated |= updateRelayStatus(status, result.switch3, channelUpdate); updated |= updateRelayStatus(status, result.switch3, channelUpdate);
updated |= updateEmStatus(status, result.em0, channelUpdate); updated |= updateEmStatus(status, result.em0, channelUpdate);
updated |= updateRollerStatus(status, result.cover0, channelUpdate); updated |= updateRollerStatus(status, result.cover0, channelUpdate);
updated |= updateDimmerStatus(status, result.light0, channelUpdate);
if (channelUpdate) { if (channelUpdate) {
updated |= ShellyComponents.updateMeters(getThing(), status); updated |= ShellyComponents.updateMeters(getThing(), status);
} }
updateHumidityStatus(sensorData, result.humidity0); updateHumidityStatus(sensorData, result.humidity0);
updateTemperatureStatus(sensorData, result.temperature0); updateTemperatureStatus(sensorData, result.temperature0);
updateIlluminanceStatus(sensorData, result.illuminance0);
updateSmokeStatus(sensorData, result.smoke0); updateSmokeStatus(sensorData, result.smoke0);
updateBatteryStatus(sensorData, result.devicepower0); updateBatteryStatus(sensorData, result.devicepower0);
updateAddonStatus(status, result); updateAddonStatus(status, result);
@ -222,7 +234,13 @@ public class Shelly2ApiClient extends ShellyHttpClient {
int duration = (int) (now() - rs.timerStartetAt); int duration = (int) (now() - rs.timerStartetAt);
sr.timerRemaining = duration; sr.timerRemaining = duration;
} }
if (status.tmp == null) {
status.tmp = new ShellySensorTmp();
}
if (rs.temperature != null) { if (rs.temperature != null) {
if (status.tmp == null) {
status.tmp = new ShellySensorTmp();
}
status.tmp.isValid = true; status.tmp.isValid = true;
status.tmp.tC = rs.temperature.tC; status.tmp.tC = rs.temperature.tC;
status.tmp.tF = rs.temperature.tF; 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) { if (status.temperature == null || getDouble(rs.temperature.tC) > status.temperature) {
status.temperature = sr.temperature; status.temperature = sr.temperature;
} }
} else {
status.tmp.isValid = false;
} }
if (rs.voltage != null) { if (rs.voltage != null) {
if (status.voltage == null || rs.voltage > status.voltage) { if (status.voltage == null || rs.voltage > status.voltage) {
@ -250,11 +266,11 @@ public class Shelly2ApiClient extends ShellyHttpClient {
ShellySettingsMeter sm = new ShellySettingsMeter(); ShellySettingsMeter sm = new ShellySettingsMeter();
ShellySettingsEMeter emeter = status.emeters.get(rs.id); ShellySettingsEMeter emeter = status.emeters.get(rs.id);
sm.isValid = emeter.isValid = true;
if (rs.apower != null) { if (rs.apower != null) {
sm.power = emeter.power = rs.apower; sm.power = emeter.power = rs.apower;
} }
if (rs.aenergy != null) { if (rs.aenergy != null) {
// Gen2 reports Watt, needs to be converted to W/h
sm.total = emeter.total = rs.aenergy.total; sm.total = emeter.total = rs.aenergy.total;
sm.counters = rs.aenergy.byMinute; sm.counters = rs.aenergy.byMinute;
sm.timestamp = rs.aenergy.minuteTs; 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, private void updateMeter(ShellySettingsStatus status, int id, ShellySettingsMeter sm, ShellySettingsEMeter emeter,
boolean channelUpdate) throws ShellyApiException { 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.meters.set(id, sm);
status.emeters.set(id, emeter); status.emeters.set(id, emeter);
relayStatus.meters.set(id, sm); relayStatus.meters.set(id, sm);
@ -301,7 +323,6 @@ public class Shelly2ApiClient extends ShellyHttpClient {
ShellySettingsMeter sm = new ShellySettingsMeter(); ShellySettingsMeter sm = new ShellySettingsMeter();
ShellySettingsEMeter emeter = status.emeters.get(0); ShellySettingsEMeter emeter = status.emeters.get(0);
sm.isValid = emeter.isValid = true;
if (em.aActPower != null) { if (em.aActPower != null) {
sm.power = emeter.power = em.aActPower; sm.power = emeter.power = em.aActPower;
} }
@ -322,7 +343,6 @@ public class Shelly2ApiClient extends ShellyHttpClient {
sm = new ShellySettingsMeter(); sm = new ShellySettingsMeter();
emeter = status.emeters.get(1); emeter = status.emeters.get(1);
sm.isValid = emeter.isValid = true;
if (em.bActPower != null) { if (em.bActPower != null) {
sm.power = emeter.power = em.bActPower; sm.power = emeter.power = em.bActPower;
} }
@ -446,6 +466,9 @@ public class Shelly2ApiClient extends ShellyHttpClient {
rs.duration = (int) (now() - cs.moveStartedAt.longValue()); rs.duration = (int) (now() - cs.moveStartedAt.longValue());
} }
if (cs.temperature != null && cs.temperature.tC > getDouble(status.temperature)) { 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); status.temperature = status.tmp.tC = getDouble(cs.temperature.tC);
} }
if (cs.apower != null) { if (cs.apower != null) {
@ -482,6 +505,46 @@ public class Shelly2ApiClient extends ShellyHttpClient {
return updateChannels ? ShellyComponents.updateRoller((ShellyBaseHandler) getThing(), rs, cs.id) : false; 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 // Addon
private void updateAddonStatus(ShellySettingsStatus status, @Nullable Shelly2DeviceStatusResult ds) private void updateAddonStatus(ShellySettingsStatus status, @Nullable Shelly2DeviceStatusResult ds)
throws ShellyApiException { throws ShellyApiException {
@ -544,6 +607,18 @@ public class Shelly2ApiClient extends ShellyHttpClient {
sdata.tmp.tF = value.tF; 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) { protected void updateSmokeStatus(ShellyStatusSensor sdata, @Nullable Shelly2DeviceStatusSmoke value) {
if (value == null) { if (value == null) {
return; return;

View File

@ -47,6 +47,10 @@ public class Shelly2ApiJsonDTO {
public static final String SHELLY2_COVER_CMD_OPEN = "Open"; 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_CLOSE = "Close";
public static final String SHELLY2_COVER_CMD_STOP = "Stop"; 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_WIFIGETCONG = "Wifi.GetConfig";
public static final String SHELLYRPC_METHOD_WIFISETCONG = "Wifi.SetConfig"; public static final String SHELLYRPC_METHOD_WIFISETCONG = "Wifi.SetConfig";
public static final String SHELLYRPC_METHOD_ETHGETCONG = "Eth.GetConfig"; 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_CLOUDSET = "Cloud.SetConfig";
public static final String SHELLYRPC_METHOD_WSGETCONFIG = "WS.GetConfig"; public static final String SHELLYRPC_METHOD_WSGETCONFIG = "WS.GetConfig";
public static final String SHELLYRPC_METHOD_WSSETCONFIG = "WS.SetConfig"; 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_SETCONFIG = "Smoke.SetConfig";
public static final String SHELLYRPC_METHOD_SMOKE_MUTE = "Smoke.Mute"; public static final String SHELLYRPC_METHOD_SMOKE_MUTE = "Smoke.Mute";
public static final String SHELLYRPC_METHOD_SCRIPT_LIST = "Script.List"; 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_UPDATE = "status_update";
public static final String SHELLY2_WAKEUPOCAUSE_UNDEFINED = "undefined"; 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 class Shelly2DevConfigBle {
public Boolean enable; public Boolean enable;
} }
@ -265,7 +276,7 @@ public class Shelly2ApiJsonDTO {
} }
public class Shelly2DevConfigInput { public class Shelly2DevConfigInput {
public String id; public Integer id;
public String name; public String name;
public String type; public String type;
public Boolean invert; public Boolean invert;
@ -276,7 +287,7 @@ public class Shelly2ApiJsonDTO {
} }
public class Shelly2DevConfigSwitch { public class Shelly2DevConfigSwitch {
public String id; public Integer id;
public String name; public String name;
@SerializedName("in_mode") @SerializedName("in_mode")
@ -367,6 +378,41 @@ public class Shelly2ApiJsonDTO {
public Boolean mute; 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 static class Shelly2GetConfigResult {
public class Shelly2DevConfigCloud { public class Shelly2DevConfigCloud {
@ -392,6 +438,8 @@ public class Shelly2ApiJsonDTO {
public Shelly2DevConfigMqtt mqtt; public Shelly2DevConfigMqtt mqtt;
public Shelly2DeviceConfigSys sys; public Shelly2DeviceConfigSys sys;
public Shelly2DeviceConfigWiFi wifi; public Shelly2DeviceConfigWiFi wifi;
@SerializedName("wd_ui")
public Shelly2DeviceConfigLed led;
@SerializedName("input:0") @SerializedName("input:0")
public Shelly2DevConfigInput input0; public Shelly2DevConfigInput input0;
@ -417,6 +465,9 @@ public class Shelly2ApiJsonDTO {
@SerializedName("cover:0") @SerializedName("cover:0")
public Shelly2DevConfigCover cover0; public Shelly2DevConfigCover cover0;
@SerializedName("light:0")
public Shelly2GetConfigLight light0;
@SerializedName("smoke:0") @SerializedName("smoke:0")
public Shelly2ConfigSmoke smoke0; public Shelly2ConfigSmoke smoke0;
} }
@ -460,6 +511,17 @@ public class Shelly2ApiJsonDTO {
public ArrayList<String> errors;// shown only if at least one error is present. public ArrayList<String> 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 static class Shelly2DeviceStatusResult {
public class Shelly2DeviceStatusBle { public class Shelly2DeviceStatusBle {
@ -501,6 +563,12 @@ public class Shelly2ApiJsonDTO {
public Double rh; public Double rh;
} }
public class Shelly2DeviceStatusIlluminance {
public Integer id;
public Double lux;
public String illumination;
}
public class Shelly2DeviceStatusVoltage { public class Shelly2DeviceStatusVoltage {
public Integer id; public Integer id;
public Double voltage; public Double voltage;
@ -618,6 +686,9 @@ public class Shelly2ApiJsonDTO {
@SerializedName("cover:0") @SerializedName("cover:0")
public Shelly2CoverStatus cover0; public Shelly2CoverStatus cover0;
@SerializedName("light:0")
public Shelly2DeviceStatusLight light0;
@SerializedName("temperature:0") @SerializedName("temperature:0")
public Shelly2DeviceStatusTempId temperature0; public Shelly2DeviceStatusTempId temperature0;
@SerializedName("temperature:100") @SerializedName("temperature:100")
@ -635,6 +706,10 @@ public class Shelly2ApiJsonDTO {
public Shelly2DeviceStatusHumidity humidity0; public Shelly2DeviceStatusHumidity humidity0;
@SerializedName("humidity:100") @SerializedName("humidity:100")
public Shelly2DeviceStatusHumidity humidity100; public Shelly2DeviceStatusHumidity humidity100;
@SerializedName("illuminance:0")
Shelly2DeviceStatusIlluminance illuminance0;
@SerializedName("smoke:0") @SerializedName("smoke:0")
public Shelly2DeviceStatusSmoke smoke0; public Shelly2DeviceStatusSmoke smoke0;
@ -751,6 +826,12 @@ public class Shelly2ApiJsonDTO {
public Boolean autoOff; public Boolean autoOff;
@SerializedName("auto_off_delay") @SerializedName("auto_off_delay")
public Double autoOffDelay; public Double autoOffDelay;
// WD_UI.SetConfig
@SerializedName("sys_led_enable")
public Boolean sysLedEnable;
@SerializedName("power_led")
public String powerLed;
} }
public static class Shelly2RpcRequest { public static class Shelly2RpcRequest {
@ -764,6 +845,11 @@ public class Shelly2ApiJsonDTO {
public Integer pos; public Integer pos;
public Boolean on; public Boolean on;
// Dimmer / Light
public Integer brightness;
@SerializedName("toggle_after")
public Integer toggleAfter;
// Shelly.SetAuth // Shelly.SetAuth
public String user; public String user;
public String realm; public String realm;

View File

@ -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.ShellyRollerStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorSleepMode; 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.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.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; 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;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfigAp.Shelly2DeviceConfigApRE; 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.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.Shelly2DeviceStatusResult;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusSys.Shelly2DeviceStatusSysAvlUpdate; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusSys.Shelly2DeviceStatusSysAvlUpdate;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2NotifyEvent; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2NotifyEvent;
@ -151,11 +153,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
@Override @Override
public void startScan() { public void startScan() {
if (config.enableBluGateway) { try {
try { installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway);
installScript(SHELLY2_BLU_GWSCRIPT); } catch (ShellyApiException e) {
} catch (ShellyApiException e) {
}
} }
} }
@ -206,6 +206,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
profile.deviceType = device.type; profile.deviceType = device.type;
profile.mac = device.mac; profile.mac = device.mac;
profile.auth = device.auth; profile.auth = device.auth;
profile.isGen2 = device.gen == 2;
if (config.serviceName.isEmpty()) { if (config.serviceName.isEmpty()) {
config.serviceName = getString(profile.hostname); 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.lights = profile.isBulb ? new ArrayList<>() : null;
profile.status.thermostats = profile.isTRV ? new ArrayList<>() : null; profile.status.thermostats = profile.isTRV ? new ArrayList<>() : null;
@ -286,19 +293,25 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
checkSetWsCallback(); checkSetWsCallback();
} }
if (dc.led != null) {
profile.settings.ledStatusDisable = !getBool(dc.led.sysLedEnable);
profile.settings.ledPowerDisable = getString(dc.led.powerLed).equals("off");
}
profile.initialized = true; profile.initialized = true;
if (!discovery) { if (!discovery) {
getStatus(); // make sure profile.status is initialized (e.g,. relay/meter status) getStatus(); // make sure profile.status is initialized (e.g,. relay/meter status)
asyncApiRequest(SHELLYRPC_METHOD_GETSTATUS); // request periodic status updates from device asyncApiRequest(SHELLYRPC_METHOD_GETSTATUS); // request periodic status updates from device
try { try {
logger.debug("{}: BLU Gateway support enabled for this device: {}", thingName, config.enableBluGateway); if (config.enableBluGateway != null) {
if (config.enableBluGateway) { logger.debug("{}: BLU Gateway support is {} for this device", thingName,
if (getBool(profile.settings.bluetooth)) { config.enableBluGateway ? "enabled" : "disabled");
installScript(SHELLY2_BLU_GWSCRIPT); boolean bluetooth = getBool(profile.settings.bluetooth);
} else { if (config.enableBluGateway && !bluetooth) {
logger.debug("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName); logger.info("{}: Bluetooth needs to be enabled to activate BLU Gateway mode", thingName);
} }
installScript(SHELLY2_BLU_GWSCRIPT, config.enableBluGateway && bluetooth);
} }
} catch (ShellyApiException e) { } catch (ShellyApiException e) {
logger.debug("{}: Device config failed", thingName, 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 { protected void installScript(String script, boolean install) throws ShellyApiException {
String json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_LIST)); ShellyScriptListResponse scriptList = apiRequest(
ShellyScriptListResponse scriptList = gson.fromJson(json, ShellyScriptListResponse.class); new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_LIST), ShellyScriptListResponse.class);
Integer ourId = -1; Integer ourId = -1;
String code = ""; 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; boolean running = false, upload = false;
if (scriptList != null) { for (ShellyScriptListEntry s : scriptList.scripts) {
for (ShellyScriptListEntry s : scriptList.scripts) { if (s.name.startsWith(script)) {
if (s.name.startsWith(script)) { ourId = s.id;
ourId = s.id; running = s.running;
running = s.running; logger.debug("{}: Script {} is already installed, id={}", thingName, script, ourId);
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 // get script code from bundle resources
String file = BUNDLE_RESOURCE_SCRIPTS + "/" + script; String file = BUNDLE_RESOURCE_SCRIPTS + "/" + script;
ClassLoader cl = Shelly2ApiRpc.class.getClassLoader(); ClassLoader cl = Shelly2ApiRpc.class.getClassLoader();
@ -380,8 +403,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
} else { } else {
try { try {
// verify that the same code version is active (avoid unnesesary flash updates) // 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 = apiRequest(
ShellyScriptResponse rsp = gson.fromJson(json, ShellyScriptResponse.class); new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_GETCODE).withId(ourId),
ShellyScriptResponse.class);
if (!rsp.data.trim().equals(code.trim())) { if (!rsp.data.trim().equals(code.trim())) {
logger.debug("{}: A script version was found, update to newest one", thingName); logger.debug("{}: A script version was found, update to newest one", thingName);
upload = true; upload = true;
@ -397,27 +421,26 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
} }
if (restart || (running && upload)) { if (restart || (running && upload)) {
json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_STOP).withId(ourId));
// first stop running script // first stop running script
startScript(ourId, false);
running = false; running = false;
} }
if (upload && ourId != -1) { if (upload && ourId != -1) {
// Delete existing script // Delete existing script
logger.debug("{}: Delete existing script", thingName); 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) { if (upload) {
logger.debug("{}: Script will be installed...", thingName); logger.debug("{}: Script will be installed...", thingName);
// Create new script, get id // Create new script, get id
json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_CREATE).withName(script)); ShellyScriptResponse rsp = apiRequest(
ShellyScriptResponse rsp = gson.fromJson(json, ShellyScriptResponse.class); new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_CREATE).withName(script),
if (rsp != null) { ShellyScriptResponse.class);
ourId = rsp.id; ourId = rsp.id;
logger.debug("{}: Script has been created, id={}", thingName, ourId); logger.debug("{}: Script has been created, id={}", thingName, ourId);
upload = true; upload = true;
}
} }
if (upload) { if (upload) {
@ -437,17 +460,40 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
parms.append = true; parms.append = true;
} while (processed < length); } while (processed < length);
running = false; running = false;
}
Shelly2RpcRequestParams params = new Shelly2RpcRequestParams().withConfig(); if (enableScript(script, true)) {
params.config.enable = true; logger.info("{}: Script {} was {} installed successful", thingName, thingName, script);
apiRequest(SHELLYRPC_METHOD_SCRIPT_SETCONFIG, params, String.class);
} }
if (!running) { if (!running) {
// Script was created or is there and stopped -> start it running = startScript(ourId, true);
json = apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SCRIPT_START).withId(ourId)); }
logger.debug("{}: Script {} was {} successful", thingName, script, logger.info("{}: Script {} {}", thingName, script,
restart ? "restarted" : "installed and started"); 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)); 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; profile.status = status;
if (updated) { if (updated) {
getThing().restartWatchdog(); getThing().restartWatchdog();
@ -765,6 +820,44 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_COVER_SETPOS).withId(relayIndex).withPos(position)); 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 @Override
public ShellyStatusSensor getSensorStatus() throws ShellyApiException { public ShellyStatusSensor getSensorStatus() throws ShellyApiException {
return sensorData; return sensorData;
@ -772,10 +865,13 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
@Override @Override
public void setAutoTimer(int index, String timerName, double value) throws ShellyApiException { 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.withConfig();
req.params.config.name = "Switch" + index; req.params.config.name = component + index;
if (timerName.equals(SHELLY_TIMER_AUTOON)) { if (timerName.equals(SHELLY_TIMER_AUTOON)) {
req.params.config.autoOn = value > 0; req.params.config.autoOn = value > 0;
req.params.config.autoOnDelay = value; req.params.config.autoOnDelay = value;
@ -786,8 +882,23 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
apiRequest(req); 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 @Override
public void resetMeterTotal(int id) throws ShellyApiException { public void resetMeterTotal(int id) throws ShellyApiException {
apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_EMDATARESET).withId(id));
} }
@Override @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 * The following API calls are not yet relevant, because currently there a no Plus/Pro (Gen2) devices of those
* categories (e.g. bulbs) * 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 @Override
public void setLightParm(int lightIndex, String parm, String value) throws ShellyApiException { 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"); 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 @Override
public void setLightMode(String mode) throws ShellyApiException { public void setLightMode(String mode) throws ShellyApiException {
throw new ShellyApiException("API call not implemented"); throw new ShellyApiException("API call not implemented");
@ -1058,10 +1145,12 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac
if (response.result != null) { if (response.result != null) {
// return sub element result as requested class type // return sub element result as requested class type
json = gson.toJson(gson.fromJson(json, Shelly2RpcBaseMessage.class).result); 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 { } else {
// return direct format // 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); return apiRequest(request.method, request.params, classOfT);
} }
public String apiRequest(Shelly2RpcRequest request) throws ShellyApiException { public void apiRequest(Shelly2RpcRequest request) throws ShellyApiException {
return apiRequest(request.method, request.params, String.class); apiRequest(request.method, request.params, Shelly2RpcBaseMessage.class);
} }
private String rpcPost(String postData) throws ShellyApiException { private String rpcPost(String postData) throws ShellyApiException {

View File

@ -24,15 +24,15 @@ import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2RpcNoti
@NonNullByDefault @NonNullByDefault
public interface Shelly2RpctInterface { 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);
} }

View File

@ -44,5 +44,5 @@ public class ShellyThingConfiguration {
public String localPort = "8080"; public String localPort = "8080";
public String serviceName = ""; public String serviceName = "";
public boolean enableBluGateway = false; public Boolean enableBluGateway = false;
} }

View File

@ -79,6 +79,8 @@ public class ShellyThingCreator {
public static final String SHELLYDT_PLUSI4DC = "SNSN-0D24X"; public static final String SHELLYDT_PLUSI4DC = "SNSN-0D24X";
public static final String SHELLYDT_PLUSHT = "SNSN-0013A"; public static final String SHELLYDT_PLUSHT = "SNSN-0013A";
public static final String SHELLYDT_PLUSSMOKE = "SNSN-0031Z"; 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 // Shelly Pro Series
public static final String SHELLYDT_PRO1 = "SPSW-001XE16EU"; 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_SHELLYPLUSSMOKE_STR = "shellyplussmoke";
public static final String THING_TYPE_SHELLYPLUSPLUGS_STR = "shellyplusplug"; public static final String THING_TYPE_SHELLYPLUSPLUGS_STR = "shellyplusplug";
public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus"; 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 // Shelly Pro Series
public static final String THING_TYPE_SHELLYPRO1_STR = "shellypro1"; 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, public static final ThingTypeUID THING_TYPE_SHELLYUNKNOWN = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYUNKNOWN_STR); 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_SHELLYPLUS1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUS1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUS1PM = new ThingTypeUID(BINDING_ID, public static final ThingTypeUID THING_TYPE_SHELLYPLUS1PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUS1PM_STR); THING_TYPE_SHELLYPLUS1PM_STR);
@ -253,6 +257,12 @@ public class ShellyThingCreator {
THING_TYPE_SHELLYPLUSPLUGS_STR); THING_TYPE_SHELLYPLUSPLUGS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGUS = new ThingTypeUID(BINDING_ID, public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGUS = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSPLUGUS_STR); 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_SHELLYPRO1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO1PM = new ThingTypeUID(BINDING_ID, public static final ThingTypeUID THING_TYPE_SHELLYPRO1PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO1PM_STR); 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_PLUSI4, THING_TYPE_SHELLYPLUSI4_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSHT, THING_TYPE_SHELLYPLUSHT_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_PLUSSMOKE, THING_TYPE_SHELLYPLUSSMOKE_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSDIMMERUS, THING_TYPE_SHELLYPLUSDIMMERUS_STR);
// Pro Series // Pro Series
THING_TYPE_MAPPING.put(SHELLYDT_PRO1, THING_TYPE_SHELLYPRO1_STR); 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_BLUBUTTON, THING_TYPE_SHELLYBLUBUTTON_STR);
THING_TYPE_MAPPING.put(SHELLYDT_BLUDW, THING_TYPE_SHELLYBLUDW_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 // mapping by thing type
THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1_STR, THING_TYPE_SHELLY1_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1_STR, THING_TYPE_SHELLY1_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1PM_STR, THING_TYPE_SHELLY1PM_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_SHELLYPLUSI4_STR, THING_TYPE_SHELLYPLUSI4_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSHT_STR, THING_TYPE_SHELLYPLUSHT_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_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_SHELLYPRO1_STR, THING_TYPE_SHELLYPRO1_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO1PM_STR, THING_TYPE_SHELLYPRO1PM_STR); THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO1PM_STR, THING_TYPE_SHELLYPRO1PM_STR);

View File

@ -20,22 +20,28 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiException; import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile; 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.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.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; 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.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; 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;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyADC; 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.ShellyStatusSensor.ShellyExtTemperature.ShellyShortTemp;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions; 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.types.StringType;
import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.types.UnDefType; import org.openhab.core.types.UnDefType;
import com.google.gson.Gson;
/*** /***
* The{@link ShellyComponents} implements updates for supplemental components * 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 * 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); Integer rssi = getInteger(status.wifiSta.rssi);
thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_RSSI, mapSignalStrength(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 && status.tmp.tC != SHELLY_API_INVTEMP) {
if (status.tmp != null && !thingHandler.getProfile().isSensor) { thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP,
thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS));
toQuantityType(getDouble(status.tmp.tC), DIGITS_NONE, SIUnits.CELSIUS)); } else if (status.temperature != null && status.temperature != SHELLY_API_INVTEMP) {
} else if (status.temperature != null) { thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP,
thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ITEMP, toQuantityType(getDouble(status.temperature), DIGITS_NONE, SIUnits.CELSIUS));
toQuantityType(getDouble(status.temperature), DIGITS_NONE, SIUnits.CELSIUS));
}
} }
thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_SLEEPTIME, thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_SLEEPTIME,
toQuantityType(getInteger(status.sleepTime), Units.SECOND)); toQuantityType(getInteger(status.sleepTime), Units.SECOND));
@ -268,8 +272,8 @@ public class ShellyComponents {
.createEMeterChannels(thingHandler.getThing(), profile, emeter, groupName)); .createEMeterChannels(thingHandler.getThing(), profile, emeter, groupName));
} }
// convert Watt/Hour to kw/h // convert Watt/h to KW/h
double total = getDouble(emeter.total) / 1000 / 60; double total = getDouble(emeter.total) / 1000;
double totalReturned = getDouble(emeter.totalReturned) / 1000; double totalReturned = getDouble(emeter.totalReturned) / 1000;
updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_CURRENTWATTS, updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_CURRENTWATTS,
toQuantityType(getDouble(emeter.power), DIGITS_WATT, Units.WATT)); toQuantityType(getDouble(emeter.power), DIGITS_WATT, Units.WATT));
@ -332,7 +336,7 @@ public class ShellyComponents {
// convert totalWatts into kw/h // convert totalWatts into kw/h
totalWatts = totalWatts / (60.0 * 1000.0); totalWatts = totalWatts / (60.0 * 1000.0);
updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_CURRENTWATTS, 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, updated |= thingHandler.updateChannel(groupName, CHANNEL_METER_TOTALKWH,
toQuantityType(totalWatts, DIGITS_KWH, Units.KILOWATT_HOUR)); toQuantityType(totalWatts, DIGITS_KWH, Units.KILOWATT_HOUR));
@ -537,6 +541,64 @@ public class ShellyComponents {
return updated; 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, public static boolean updateTempChannel(@Nullable ShellyShortTemp sensor, ShellyThingInterface thingHandler,
String channel) { String channel) {
return sensor != null ? updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, channel, sensor.tC, "") : false; return sensor != null ? updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, channel, sensor.tC, "") : false;

View File

@ -28,6 +28,6 @@ public interface ShellyDeviceListener {
/** /**
* This method is called when new device information is received. * 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<String, String> parameters); Map<String, String> parameters);
} }

View File

@ -19,9 +19,7 @@ import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException; 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.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.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; 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.ShellyShortLightStatus;
@ -42,8 +40,6 @@ import org.openhab.core.types.Command;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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 * The{@link ShellyRelayHandler} handles light (bulb+rgbw2) specific commands and status. All other commands will be
* handled by the generic thing handler. * handled by the generic thing handler.
@ -193,7 +189,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
if (brightness > 0) { if (brightness > 0) {
api.setBrightness(lightId, brightness, config.brightnessAutoOn); api.setBrightness(lightId, brightness, config.brightnessAutoOn);
} else { } 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 if (brightness >= 0) { // ignore -1
updateChannel(CHANNEL_COLOR_WHITE, CHANNEL_BRIGHTNESS + "$Value", updateChannel(CHANNEL_COLOR_WHITE, CHANNEL_BRIGHTNESS + "$Value",
toQuantityType((double) (power == OnOffType.ON ? brightness : 0), DIGITS_NONE, Units.PERCENT)); toQuantityType((double) (power == OnOffType.ON ? brightness : 0), DIGITS_NONE, Units.PERCENT));
@ -206,7 +202,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
// map status to channels // map status to channels
boolean updated = false; boolean updated = false;
updated |= updateRelays(status); updated |= updateRelays(status);
updated |= updateDimmers(status); updated |= ShellyComponents.updateDimmers(this, status);
updated |= updateLed(status); updated |= updateLed(status);
return updated; 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) { private void createRollerChannels(ShellyRollerStatus roller) {
if (!areChannelsCreated()) { if (!areChannelsCreated()) {
updateChannelDefinitions(ShellyChannelDefinitions.createRollerChannels(getThing(), roller)); updateChannelDefinitions(ShellyChannelDefinitions.createRollerChannels(getThing(), roller));
@ -356,63 +346,6 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
return updated; 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 * Update LED channels
* *

View File

@ -39,85 +39,86 @@ import org.openhab.core.types.StateOption;
@NonNullByDefault @NonNullByDefault
public interface ShellyThingInterface { public interface ShellyThingInterface {
public ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiException; ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiException;
public @Nullable List<StateOption> getStateOptions(ChannelTypeUID uid); @Nullable
List<StateOption> 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<String, Channel> dynChannels); void updateChannelDefinitions(Map<String, Channel> 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<Object> valueArray); boolean updateWakeupReason(@Nullable List<Object> 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();
} }

View File

@ -78,7 +78,7 @@ public class ShellyChannelDefinitions {
public static final String ITEMT_POWER = "Number:Power"; public static final String ITEMT_POWER = "Number:Power";
public static final String ITEMT_ENERGY = "Number:Energy"; public static final String ITEMT_ENERGY = "Number:Energy";
public static final String ITEMT_VOLT = "Number:ElectricPotential"; 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_ANGLE = "Number:Angle";
public static final String ITEMT_DISTANCE = "Number:Length"; public static final String ITEMT_DISTANCE = "Number:Length";
public static final String ITEMT_SPEED = "Number:Speed"; 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_ITEMP, "deviceTemp", ITEMT_TEMP))
.add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_WAKEUP, "sensorWakeup", ITEMT_STRING)) .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_ACCUWATTS, "meterAccuWatts", ITEMT_POWER))
.add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL, "meterAccuTotal", 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_POWER)) .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_VOLTAGE, "supplyVoltage", ITEMT_VOLT))
.add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_DEVST_CHARGER, "charger", ITEMT_SWITCH)) .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)) .add(new ShellyChannel(m, CHGR_DEVST, CHANNEL_LED_STATUS_DISABLE, "ledStatusDisable", ITEMT_SWITCH))
@ -191,7 +191,7 @@ public class ShellyChannelDefinitions {
// Power Meter // Power Meter
.add(new ShellyChannel(m, CHGR_METER, CHANNEL_METER_CURRENTWATTS, "meterWatts", ITEMT_POWER)) .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_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)) .add(new ShellyChannel(m, CHGR_METER, CHANNEL_LAST_UPDATE, "lastUpdate", ITEMT_DATETIME))
// EMeter // 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, "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_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_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_FLOOD, "sensorFlood", ITEMT_SWITCH))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_SMOKE, "sensorSmoke", 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)) .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.temperature != null && getDouble(status.temperature) != SHELLY_API_INVTEMP)
|| (status.tmp != null && getDouble(status.tmp.tC) != SHELLY_API_INVTEMP))) { || (status.tmp != null && getDouble(status.tmp.tC) != SHELLY_API_INVTEMP))) {
// Only some devices report the internal device temp // 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); 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 // 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 boolean accuChannel = profile.numMeters > 1 && !profile.isRoller && !profile.isRGBW2;
&& !profile.isRGBW2) || ((status.emeters != null && status.emeters.size() > 1)));
addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUWATTS); addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUWATTS);
addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL); addChannel(thing, add, accuChannel, CHGR_DEVST, CHANNEL_DEVST_ACCUTOTAL);
addChannel(thing, add, accuChannel && (status.emeters != null), CHGR_DEVST, CHANNEL_DEVST_ACCURETURNED); 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 // Shelly 1/1PM and Plus 1/1PM Addon
if (profile.settings.extSwitch != null && profile.settings.extSwitch.input0 != null boolean addon = profile.settings.extSwitch != null && profile.settings.extSwitch.input0 != null
&& idx == getInteger(profile.settings.extSwitch.input0.relayNum)) { && idx == getInteger(profile.settings.extSwitch.input0.relayNum);
addChannel(thing, add, true, CHGR_SENSOR, CHANNEL_ESENSOR_INPUT + (idx + 1)); if (addon) {
addChannel(thing, add, addon, CHGR_SENSOR,
CHANNEL_ESENSOR_INPUT + (profile.settings.extSwitch.input0.relayNum + 1));
} }
if (profile.status.extTemperature != null) { if (profile.status.extTemperature != null) {
addChannel(thing, add, profile.status.extTemperature.sensor1 != null, CHGR_SENSOR, CHANNEL_ESENSOR_TEMP1); 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.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.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.extVoltage != null, CHGR_SENSOR, CHANNEL_ESENSOR_VOLTAGE);
addChannel(thing, add, profile.status.extDigitalInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_DIGITALINPUT); addChannel(thing, add, profile.status.extDigitalInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_DIGITALINPUT);
addChannel(thing, add, profile.status.extAnalogInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_ANALOGINPUT); addChannel(thing, add, profile.status.extAnalogInput != null, CHGR_SENSOR, CHANNEL_ESENSOR_ANALOGINPUT);
@ -379,6 +383,7 @@ public class ShellyChannelDefinitions {
if (profile.settings.dimmers != null) { if (profile.settings.dimmers != null) {
ShellySettingsDimmer ds = profile.settings.dimmers.get(idx); 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.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF); addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
ShellyShortLightStatus dss = dstatus.dimmers.get(idx); 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.voltage != null, group, CHANNEL_EMETER_VOLTAGE);
addChannel(thing, newChannels, emeter.current != null, group, CHANNEL_EMETER_CURRENT); 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.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); addChannel(thing, newChannels, true, group, CHANNEL_LAST_UPDATE);
return newChannels; return newChannels;
} }
@ -505,7 +510,8 @@ public class ShellyChannelDefinitions {
addChannel(thing, newChannels, sdata.sensor.vibration != null, CHANNEL_GROUP_SENSOR, addChannel(thing, newChannels, sdata.sensor.vibration != null, CHANNEL_GROUP_SENSOR,
CHANNEL_SENSOR_VIBRATION); 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); addChannel(thing, newChannels, sdata.accel.tilt != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TILT);
} }

View File

@ -89,4 +89,33 @@
<advanced>true</advanced> <advanced>true</advanced>
</parameter> </parameter>
</config-description> </config-description>
<config-description uri="thing-type:shelly:dimmer-gen2">
<parameter name="deviceIp" type="text" required="true">
<label>@text/thing-type.config.shelly.deviceIp.label</label>
<description>@text/thing-type.config.shelly.deviceIp.description</description>
<context>network-address</context>
</parameter>
<parameter name="userId" type="text" required="false">
<label>@text/thing-type.config.shelly.userId.label</label>
<description>@text/thing-type.config.shelly.userId.description</description>
</parameter>
<parameter name="password" type="text" required="false">
<label>@text/thing-type.config.shelly.password.label</label>
<description>@text/thing-type.config.shelly.password.description</description>
<context>password</context>
</parameter>
<parameter name="brightnessAutoOn" type="boolean" required="false">
<label>@text/thing-type.config.shelly.light.brightnessAutoOn.label</label>
<description>@text/thing-type.config.shelly.light.brightnessAutoOn.description</description>
<default>true</default>
</parameter>
<parameter name="updateInterval" type="integer" min="10" required="true" unit="s">
<label>@text/thing-type.config.shelly.updateInterval.label</label>
<description>@text/thing-type.config.shelly.updateInterval.description</description>
<default>60</default>
<unitLabel>seconds</unitLabel>
<advanced>true</advanced>
</parameter>
</config-description>
</config-description:config-descriptions> </config-description:config-descriptions>

View File

@ -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.shellyix3.description = Shelly ix3 (Activation Device with 3 inputs)
thing-type.shelly.shellypludht.description = Shelly Plus HT - Temperature and Humidity Sensor 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 # Pro Devices
thing-type.shelly.shellypro1.description = Shelly Pro 1 - Single Relay Switch 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.shellypro1pm.description = Shelly Pro 1PM - Single Relay Switch with Power Meter
@ -98,30 +114,9 @@ thing-type.shelly.shellypro3.description = Shelly Pro 3 - 3xRelay Switch
thing-type.shelly.shellypro3em.description = Shelly Pro 3EM - 3xPower Meter thing-type.shelly.shellypro3em.description = Shelly Pro 3EM - 3xPower Meter
thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter
# Plus devices # BLU devices
thing-type.shelly.shellyplus1.description = Shelly Plus 1 (Single Relay Switch) thing-type.shelly.shellypblubutton.description = Shelly BLU Button
thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - Single Relay Switch with Power Meter thing-type.shelly.shellybludw.description = Shelly BLU Door/Window Sensor
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
# thing config - shellydevice # thing config - shellydevice
thing-type.config.shelly.deviceIp.label = IP Address thing-type.config.shelly.deviceIp.label = IP Address

View File

@ -479,7 +479,7 @@
<category>Energy</category> <category>Energy</category>
<tags> <tags>
<tag>Measurement</tag> <tag>Measurement</tag>
<tag>Current</tag> <tag>Power</tag>
</tags> </tags>
<state readOnly="true" pattern="%.2f %unit%"> <state readOnly="true" pattern="%.2f %unit%">
</state> </state>
@ -490,24 +490,36 @@
<label>@text/channel-type.shelly.meterAccuWatts.label</label> <label>@text/channel-type.shelly.meterAccuWatts.label</label>
<description>@text/channel-type.shelly.meterAccuWatts.description</description> <description>@text/channel-type.shelly.meterAccuWatts.description</description>
<category>Energy</category> <category>Energy</category>
<tags>
<tag>Measurement</tag>
<tag>Power</tag>
</tags>
<state readOnly="true" pattern="%.2f %unit%"> <state readOnly="true" pattern="%.2f %unit%">
</state> </state>
</channel-type> </channel-type>
<channel-type id="meterAccuTotal" advanced="true"> <channel-type id="meterAccuTotal" advanced="true">
<item-type>Number:Power</item-type> <item-type>Number:Energy</item-type>
<label>@text/channel-type.shelly.meterAccuTotal.label</label> <label>@text/channel-type.shelly.meterAccuTotal.label</label>
<description>@text/channel-type.shelly.meterAccuTotal.description</description> <description>@text/channel-type.shelly.meterAccuTotal.description</description>
<category>Energy</category> <category>Energy</category>
<tags>
<tag>Measurement</tag>
<tag>Energy</tag>
</tags>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>
</channel-type> </channel-type>
<channel-type id="meterAccuReturned" advanced="true"> <channel-type id="meterAccuReturned" advanced="true">
<item-type>Number:Power</item-type> <item-type>Number:Energy</item-type>
<label>@text/channel-type.shelly.meterAccuReturned.label</label> <label>@text/channel-type.shelly.meterAccuReturned.label</label>
<description>@text/channel-type.shelly.meterAccuReturned.description</description> <description>@text/channel-type.shelly.meterAccuReturned.description</description>
<category>Energy</category> <category>Energy</category>
<tags>
<tag>Measurement</tag>
<tag>Energy</tag>
</tags>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>
</channel-type> </channel-type>
@ -521,10 +533,14 @@
</channel-type> </channel-type>
<channel-type id="lastPower1" advanced="true"> <channel-type id="lastPower1" advanced="true">
<item-type>Number:Energy</item-type> <item-type>Number:Power</item-type>
<label>@text/channel-type.shelly.lastPower1.label</label> <label>@text/channel-type.shelly.lastPower1.label</label>
<description>@text/channel-type.shelly.lastPower1.description</description> <description>@text/channel-type.shelly.lastPower1.description</description>
<category>Energy</category> <category>Energy</category>
<tags>
<tag>Measurement</tag>
<tag>Power</tag>
</tags>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>
</channel-type> </channel-type>
@ -533,7 +549,6 @@
<item-type>Number:Energy</item-type> <item-type>Number:Energy</item-type>
<label>@text/channel-type.shelly.meterTotal.label</label> <label>@text/channel-type.shelly.meterTotal.label</label>
<description>@text/channel-type.shelly.meterTotal.description</description> <description>@text/channel-type.shelly.meterTotal.description</description>
<category>Energy</category>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>
</channel-type> </channel-type>
@ -543,6 +558,10 @@
<label>@text/channel-type.shelly.meterReturned.label</label> <label>@text/channel-type.shelly.meterReturned.label</label>
<description>@text/channel-type.shelly.meterReturned.description</description> <description>@text/channel-type.shelly.meterReturned.description</description>
<category>Energy</category> <category>Energy</category>
<tags>
<tag>Measurement</tag>
<tag>Energy</tag>
</tags>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>
</channel-type> </channel-type>
@ -551,6 +570,7 @@
<item-type>Number:ElectricPotential</item-type> <item-type>Number:ElectricPotential</item-type>
<label>@text/channel-type.shelly.meterVoltage.label</label> <label>@text/channel-type.shelly.meterVoltage.label</label>
<description>@text/channel-type.shelly.meterVoltage.description</description> <description>@text/channel-type.shelly.meterVoltage.description</description>
<category>Energy</category>
<tags> <tags>
<tag>Measurement</tag> <tag>Measurement</tag>
<tag>Voltage</tag> <tag>Voltage</tag>
@ -560,13 +580,13 @@
</channel-type> </channel-type>
<channel-type id="meterCurrent"> <channel-type id="meterCurrent">
<item-type>Number:ElectricPotential</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>@text/channel-type.shelly.meterCurrent.label</label> <label>@text/channel-type.shelly.meterCurrent.label</label>
<description>@text/channel-type.shelly.meterCurrent.description</description> <description>@text/channel-type.shelly.meterCurrent.description</description>
<category>Energy</category> <category>Energy</category>
<tags> <tags>
<tag>Measurement</tag> <tag>Measurement</tag>
<tag>Power</tag> <tag>Current</tag>
</tags> </tags>
<state readOnly="true" pattern="%.3f %unit%"> <state readOnly="true" pattern="%.3f %unit%">
</state> </state>

View File

@ -290,4 +290,18 @@
<config-description-ref uri="thing-type:shelly:relay-gen2"/> <config-description-ref uri="thing-type:shelly:relay-gen2"/>
</thing-type> </thing-type>
<thing-type id="shellypluswdus">
<label>Shelly Plus Dimmer US</label>
<description>@text/thing-type.shelly.shellypluswdus.description</description>
<category>DimmableLight</category>
<channel-groups>
<channel-group id="relay" typeId="dimmerChannel"/>
<channel-group id="meter" typeId="meter"/>
<channel-group id="device" typeId="deviceStatus"/>
</channel-groups>
<representation-property>serviceName</representation-property>
<config-description-ref uri="thing-type:shelly:dimmer-gen2"/>
</thing-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -32,4 +32,16 @@
<config-description-ref uri="thing-type:shelly:battery-gen2"/> <config-description-ref uri="thing-type:shelly:battery-gen2"/>
</thing-type> </thing-type>
<thing-type id="shellywalldisplay">
<label>Shelly Wall Display</label>
<description>@text/thing-type.shelly.shellywalldisplay.description</description>
<category>Sensor</category>
<channel-groups>
<channel-group id="sensors" typeId="sensorData"/>
<channel-group id="device" typeId="deviceStatus"/>
</channel-groups>
<representation-property>serviceName</representation-property>
<config-description-ref uri="thing-type:shelly:relay-gen2"/>
</thing-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -1,6 +1,7 @@
/* /*
* This script uses the BLE scan functionality in scripting to pass scan reults to openHAB * This script uses the BLE scan functionality in scripting to pass scan reults to openHAB
* Supported BLU Devices: SBBT , SBDW * Supported BLU Devices: SBBT , SBDW
* Version 0.2
*/ */
let ALLTERCO_DEVICE_NAME_PREFIX = ["SBBT", "SBDW"]; 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'); let BLEConfig = Shelly.getComponentConfig('ble');
if(BLEConfig.enable === false) { if(BLEConfig.enable === false) {
console.log('Error: BLE not enabled'); console.log('Error: BLE not enabled, unable to start OH-BLU Scanner');
} else { } else {
Timer.set(1000, false, startBLEScan); BLE.Scanner.Start({ duration_ms: SCAN_DURATION, active: true }, scanCB);
console.log('OH-BLU Event Gateway running');
} }