### Generation 2 Plus series
-| thing-type | Model | Vendor ID |
-| -------------------- | -------------------------------------------------------- | ------------- |
-| shellyplus1 | Shelly Plus 1 with 1x relay | SNSW-001X16EU |
-| shellyplus1pm | Shelly Plus 1PM with 1x relay + power meter | SNSW-001P16EU |
-| shellyplus2pm-relay | Shelly Plus 2PM with 2x relay + power meter, relay mode | SNSW-002P16EU |
-| shellyplus2pm-roller | Shelly Plus 2PM with 2x relay + power meter, roller mode | SNSW-002P16EU |
-| shellyplusi4 | Shelly Plus i4 with 4x AC input | SNSN-0024X |
-| shellyplusi4dc | Shelly Plus i4 with 4x DC input | SNSN-0D24X |
-| shellyplusht | Shelly Plus HT with temperature + humidity sensor | SNSN-0013A |
+| thing-type | Model | Vendor ID |
+| -------------------- | -------------------------------------------------------- | --------------------------------------------- |
+| shellyplus1 | Shelly Plus 1 with 1x relay | SNSW-001X16EU |
+| shellyplus1pm | Shelly Plus 1PM with 1x relay + power meter | SNSW-001P16EU |
+| shellyplus2pm-relay | Shelly Plus 2PM with 2x relay + power meter, relay mode | SNSW-002P16EU, SNSW-102P16EU |
+| shellyplus2pm-roller | Shelly Plus 2PM with 2x relay + power meter, roller mode | SNSW-002P16EU, SNSW-102P16EU |
+| shellyplusplug | Shelly Plug-S | SNPL-00112EU |
+| shellyplusplug | Shelly Plug-IT | SNPL-00110IT |
+| shellyplusplug | Shelly Plug-UK | SNPL-00112UK |
+| shellyplusplug | Shelly Plug-US | SNPL-00116US |
+| shellyplusi4 | Shelly Plus i4 with 4x AC input | SNSN-0024X |
+| shellyplusi4dc | Shelly Plus i4 with 4x DC input | SNSN-0D24X |
+| shellyplusht | Shelly Plus HT with temperature + humidity sensor | SNSN-0013A |
+| shellyplussmoke | Shelly Plus Smoke sensor | SNSN-0031Z |
### Generation 2 Pro series
-| thing-type | Model | Vendor ID |
-| ------------------- | -------------------------------------------------------- | -------------- |
-| shellypro1 | Shelly Pro 1 with 1x relay | SPSW-001XE16EU |
-| shellypro1pm | Shelly Pro 1 PM with 1x relay + power meter | SPSW-001PE16EU |
-| shellypro2-relay | Shelly Pro 2 with 2x relay, relay mode | SPSW-002XE16EU |
-| shellypro2pm-relay | Shelly Pro 2 PM with 2x relay + power meter, relay mode | SPSW-002PE16EU |
-| shellypro2pm-roller | Shelly Pro 2 PM with 2x relay + power meter, roller mode | SPSW-002PE16EU |
-| shellypro3 | Shelly Pro 3 with 3x relay (dry contacts) | SPSW-003XE16EU |
-| shellypro4pm | Shelly Pro 4 PM with 4x relay + power meter | SPSW-004PE16EU |
+| thing-type | Model | Vendor ID |
+| ------------------- | -------------------------------------------------------- | ---------------------------------------------- |
+| shellypro1 | Shelly Pro 1 with 1x relay | SPSW-001XE16EU, SPSW-101XE16EU, SPSW-201XE16EU |
+| shellypro1pm | Shelly Pro 1 PM with 1x relay + power meter | SPSW-001PE16EU, SPSW-101PE16EU, SPSW-201PE16EU |
+| shellypro2-relay | Shelly Pro 2 with 2x relay, relay mode | SPSW-002XE16EU, SPSW-102XE16EU, SPSW-202XE16EU |
+| shellypro2pm-relay | Shelly Pro 2 PM with 2x relay + power meter, relay mode | SPSW-002PE16EU, SPSW-102PE16EU, SPSW-202PE16EU |
+| shellypro2pm-roller | Shelly Pro 2 PM with 2x relay + power meter, roller mode | SPSW-002PE16EU, SPSW-102PE16EU, SPSW-202PE16EU |
+| shellypro3 | Shelly Pro 3 with 3x relay (dry contacts) | SPSW-003XE16EU |
+| shellypro3em | Shelly Pro 3 with 3 integrated power meters | SPEM-003CEBEU |
+| shellypro4pm | Shelly Pro 4 PM with 4x relay + power meter | SPSW-004PE16EU, SPSW-104PE16EU |
## Binding Configuration
| TEMP_OVER | Above "temperature over" threshold |
| VIBRATION | A vibration/tamper was detected (DW2 only) |
-Refer to section [Full Example:shelly.rules](#shellyrules) for examples how to catch alarm triggers in openHAB rules
+Refer to section [Full Example](#full-example) for examples how to catch alarm triggers in openHAB rules
## Channels
| | voltage | Number | yes | RMS voltage, Volts |
| | current | Number | yes | Current in A |
| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
| meter2 | currentWatts | Number | yes | Current power consumption in Watts |
| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
| | voltage | Number | yes | RMS voltage, Volts |
| | current | Number | yes | Current in A |
| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
| meter3 | currentWatts | Number | yes | Current power consumption in Watts |
| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
| | voltage | Number | yes | RMS voltage, Volts |
| | current | Number | yes | Current in A |
| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
### Shelly 2 - relay mode (thing-type: shelly2-relay)
| ------- | --------------- | -------- | --------- | ------------------------------------------------------------------- |
| sensors | temperature | Number | yes | Current Temperature in °C |
| | state | Contact | yes | Valve status: OPEN or CLOSED (position = 0) |
+| | open | Contact | yes | ON: "window is open" was detected, OFF: window is closed |
| | lastUpdate | DateTime | yes | Timestamp of the last update (any sensor value changed) |
| control | targetTemp | Number | no | Temperature in °C: 4=Low/Min; 5..30=target temperature;31=Hi/Max |
| | position | Dimmer | no | Set valve to manual mode (0..100%) disables auto-temp) |
The roller positioning calibration has to be performed using the Shelly Web UI or App before the position can be set in percent.
Refer to [Smartify Roller Shutters with openHAB and Shelly](doc/UseCaseSmartRoller.md) for more information on roller integration.
+### Shelly Plus Plug-S/IT/UK/US (thing-type: shellyplusplug)
+
+| 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 | Sets a timer to turn the device ON after every OFF command; in seconds |
+| | autoOff | Number | r/w | Sets a timer to turn the device OFF after every ON command; in seconds |
+| | timerActive | Switch | yes | ON: An auto-on/off timer is active |
+| | button | Trigger | yes | Event trigger, see section Button Events |
+| meter | currentWatts | Number | yes | Current power consumption in Watts |
+| | lastPower1 | Number | yes | Energy consumption for a round minute, 1 minute ago |
+| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
+| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+
+
### Shelly Plus i4, i4DC (thing-types: shellyplusi4, shellyplusi4dc)
| Group | Channel | Type | read-only | Description |
| battery | batteryLevel | Number | yes | Battery Level in % |
| | lowBattery | Switch | yes | Low battery alert (< 20%) |
+### Shelly Plus Smoke (thing-type: shellyplussmoke)
+
+| Group | Channel | Type | read-only | Description |
+| ------- | ------------ | -------- | --------- | ------------------------------------------------------- |
+| sensors | smoke | Switch | yes | ON: Smoke detected |
+| | mute | Switch | no | ON: Alarm muted |
+| | lastUpdate | DateTime | yes | Timestamp of the last update (any sensor value changed) |
+| | lastError | String | yes | Last device error. |
+| battery | batteryLevel | Number | yes | Battery Level in % |
+| | lowBattery | Switch | yes | Low battery alert (< 20%) |
+
+
## Shelly Pro Series
### Shelly Pro 1 (thing-type: shellypro1)
| | timerActive | Switch | yes | Relay #3: ON: An auto-on/off timer is active |
| | button | Trigger | yes | Relay #3: Event trigger, see section Button Events |
+### Shelly Pro 3EM (thing-type: shellypro3em)
+
+| Group | Channel | Type | read-only | Description |
+| ------ | ------------- | -------- | --------- | --------------------------------------------------------------------------------- |
+| meter1 | currentWatts | Number | yes | Current power consumption in Watts |
+| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
+| | returnedKWH | Number | yes | Total returned energy, kwh |
+| | reactiveWatts | Number | yes | Instantaneous reactive power, Watts |
+| | voltage | Number | yes | RMS voltage, Volts |
+| | current | Number | yes | Current in A |
+| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
+| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+| meter2 | currentWatts | Number | yes | Current power consumption in Watts |
+| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
+| | returnedKWH | Number | yes | Total returned energy, kwh |
+| | reactiveWatts | Number | yes | Instantaneous reactive power, Watts |
+| | voltage | Number | yes | RMS voltage, Volts |
+| | current | Number | yes | Current in A |
+| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
+| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+| meter3 | currentWatts | Number | yes | Current power consumption in Watts |
+| | totalKWH | Number | yes | Total energy consumption in kwh since the device powered up (resets on restart) |
+| | returnedKWH | Number | yes | Total returned energy, kwh |
+| | reactiveWatts | Number | yes | Instantaneous reactive power, Watts |
+| | voltage | Number | yes | RMS voltage, Volts |
+| | current | Number | yes | Current in A |
+| | powerFactor | Number | yes | Power Factor in percent |
+| | resetTotals | Switch | yes | ON: Resets total values for the power meter |
+| | lastUpdate | DateTime | yes | Timestamp of the last measurement |
+
### Shelly Pro 4PM (thing-type: shelly4pro)
| Group | Channel | Type | read-only | Description |
THING_TYPE_SHELLYPRO2PM_RELAY, //
THING_TYPE_SHELLYPRO2PM_ROLLER, //
THING_TYPE_SHELLYPRO3, //
+ THING_TYPE_SHELLYPRO3EM, //
THING_TYPE_SHELLYPRO4PM, //
THING_TYPE_SHELLYPLUSI4, //
THING_TYPE_SHELLYPLUSI4DC, //
THING_TYPE_SHELLYPLUSHT, //
+ THING_TYPE_SHELLYPLUSSMOKE, //
+ THING_TYPE_SHELLYPLUSPLUGS, //
THING_TYPE_SHELLYPLUSPLUGUS, //
THING_TYPE_SHELLYPROTECTED, //
THING_TYPE_SHELLYUNKNOWN);
public static final String CHANNEL_EMETER_VOLTAGE = "voltage";
public static final String CHANNEL_EMETER_CURRENT = "current";
public static final String CHANNEL_EMETER_PFACTOR = "powerFactor";
+ public static final String CHANNEL_EMETER_RESETTOTAL = "resetTotals";
public static final String CHANNEL_GROUP_SENSOR = "sensors";
public static final String CHANNEL_SENSOR_TEMP = "temperature";
public static final String CHANNEL_SENSOR_TILT = "tilt";
public static final String CHANNEL_SENSOR_FLOOD = "flood";
public static final String CHANNEL_SENSOR_SMOKE = "smoke";
+ public static final String CHANNEL_SENSOR_MUTE = "mute";
public static final String CHANNEL_SENSOR_STATE = "state";
+ public static final String CHANNEL_SENSOR_OPEN = "open";
public static final String CHANNEL_SENSOR_VALVE = "valve";
public static final String CHANNEL_SENSOR_SSTATE = "status"; // Shelly Gas
public static final String CHANNEL_SENSOR_MOTION_ACT = "motionActive";
public static final int DIGITS_WATT = 2;
public static final int DIGITS_KWH = 3;
public static final int DIGITS_VOLT = 1;
+ public static final int DIGITS_AMPERE = 3;
public static final int DIGITS_TEMP = 1;
public static final int DIGITS_LUX = 0;
public static final int DIGITS_PERCENT = 1;
void setRelayTurn(int id, String turnMode) throws ShellyApiException;
- ShellyRollerStatus getRollerStatus(int rollerIndex) throws ShellyApiException;
+ public void resetMeterTotal(int id) throws ShellyApiException;
+
+ public ShellyRollerStatus getRollerStatus(int rollerIndex) throws ShellyApiException;
void setRollerTurn(int relayIndex, String turnMode) throws ShellyApiException;
void startValveBoost(int valveId, int value) throws ShellyApiException;
+ void muteSmokeAlarm(int smokeId) throws ShellyApiException;
+
ShellyOtaCheckResult checkForUpdate() throws ShellyApiException;
ShellySettingsUpdate firmwareUpdate(String uri) throws ShellyApiException;
public boolean isButton = false; // true for a Shelly Button 1
public boolean isIX = false; // true for a Shelly IX
public boolean isTRV = false; // true for a Shelly TRV
+ public boolean isSmoke = false; // true for Shelly Smoke
public int minTemp = 0; // Bulb/Duo: Min Light Temp
public int maxTemp = 0; // Bulb/Duo: Max Light Temp
}
boolean isFlood = thingType.equals(THING_TYPE_SHELLYFLOOD_STR);
- boolean isSmoke = thingType.equals(THING_TYPE_SHELLYSMOKE_STR);
+ isSmoke = thingType.equals(THING_TYPE_SHELLYSMOKE_STR) || thingType.equals(THING_TYPE_SHELLYPLUSSMOKE_STR);
boolean isGas = thingType.equals(THING_TYPE_SHELLYGAS_STR);
boolean isUNI = thingType.equals(THING_TYPE_SHELLYUNI_STR);
isHT = thingType.equals(THING_TYPE_SHELLYHT_STR) || thingType.equals(THING_TYPE_SHELLYPLUSHT_STR);
//
// API values
//
- public static final double SHELLY_API_INVTEMP = -999.0;
+ public static final double SHELLY_API_INVTEMP = 999.0;
public static final String SHELLY_BTNT_MOMENTARY = "momentary";
public static final String SHELLY_BTNT_MOM_ON_RELEASE = "momentary_on_release";
public ShellyThermTemp tmp;
@SerializedName("boost_minutes")
public Integer boostMinutes;
+ @SerializedName("window_open")
+ public Boolean windowOpen;
}
public static class ShellySensorTmp {
public ShellySensorState sensor;
public Boolean smoke; // SHelly Smoke
public Boolean flood; // Shelly Flood: true = flood condition detected
+ public Boolean mute; // mute enabled/disabled
@SerializedName("rain_sensor")
public Boolean rainSensor; // Shelly Flood: true=in rain mode
// event count
updateChannel(updates, group, CHANNEL_STATUS_EVENTCOUNT + profile.getInputSuffix(idx), getDecimal(count));
logger.trace(
- "{}: Check button[{}] for event trigger (isButtonMode={}, isButton={}, hasBattery={}, serial={}, count={}, lastEventCount[{}]={}",
+ "{}: Check button[{}] for event trigger (inButtonMode={}, isButton={}, hasBattery={}, serial={}, count={}, lastEventCount[{}]={}",
thingName, idx, profile.inButtonMode(idx), profile.isButton, profile.hasBattery, serial, count, idx,
lastEventCount[idx]);
- if (profile.inButtonMode(idx) && ((profile.hasBattery && (count == 1))
- || ((lastEventCount[idx] != -1) && (count != lastEventCount[idx])))) {
+ if (profile.inButtonMode(idx) && ((profile.hasBattery && count == 1)
+ || (lastEventCount[idx] != -1 && count != lastEventCount[idx]))) {
if (!profile.isButton || (profile.isButton && (serial != 0x200))) { // skip duplicate on wake-up
logger.debug("{}: Trigger event {}", thingName, inputEvent[idx]);
thingHandler.triggerButton(group, idx, inputEvent[idx]);
// Special handling for TRV, because it uses duplicate ID values with different meanings
switch (sen.id) {
case "3101": // current temp
- updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
- toQuantityType(value, DIGITS_TEMP, SIUnits.CELSIUS));
+ if (value != SHELLY_API_INVTEMP) {
+ updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
+ toQuantityType(value, DIGITS_TEMP, SIUnits.CELSIUS));
+ }
break;
case "3103": // target temp in C. 4/31, 999=unknown
updateChannel(updates, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SETTEMP,
case "3201": // sensor_1: T, extTemp, C, -55/125; unknown 999
case "3301": // sensor_2: T, extTemp, C, -55/125; unknown 999
int idx = getExtTempId(sen.id);
- if (idx >= 0) {
+ if (idx >= 0 && value != SHELLY_API_INVTEMP) {
// H&T, Fllod, DW only have 1 channel, 1/1PM with Addon have up to to 3 sensors
String channel = profile.isSensor ? CHANNEL_SENSOR_TEMP : CHANNEL_SENSOR_TEMP + idx;
// Some devices report values = -999 or 99 during fw update
logger.debug("{}: CoIoT Message from {} (MID={}): {}", thingName,
response.getSourceContext().getPeerAddress(), response.getMID(), response.getPayloadString());
}
+ if (thingHandler.isStopping()) {
+ logger.debug("{}: Thing is shutting down, ignore CoIOT message", thingName);
+ return;
+ }
+
if (response.isCanceled() || response.isDuplicate() || response.isRejected()) {
logger.debug("{} ({}): Packet was canceled, rejected or is a duplicate -> discard", thingName, devId);
thingHandler.incProtErrors();
@Override
public void setRelayTurn(int id, String turnMode) throws ShellyApiException {
- callApi(getControlUriPrefix(id) + "?" + SHELLY_LIGHT_TURN + "=" + turnMode.toLowerCase(),
- ShellyShortLightStatus.class);
+ callApi(getControlUriPrefix(id) + "?" + SHELLY_LIGHT_TURN + "=" + turnMode.toLowerCase(), String.class);
+ }
+
+ @Override
+ public void resetMeterTotal(int id) throws ShellyApiException {
+ callApi(SHELLY_URL_STATUS_EMETER + "/" + id + "/reset_totals=1", ShellyStatusRelay.class);
}
@Override
}
}
+ @Override
+ public void muteSmokeAlarm(int id) throws ShellyApiException {
+ throw new ShellyApiException("Request not supported");
+ }
+
/**
* Set sensor Action URLs
*
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceConfig.Shelly2GetConfigResult;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2CoverStatus;
+import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusEm;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusHumidity;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2DeviceStatus.Shelly2DeviceStatusResult.Shelly2DeviceStatusPower;
+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.Shelly2InputStatus;
import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2RelayStatus;
boolean channelUpdate) throws ShellyApiException {
boolean updated = false;
+ if (result.temperature0 != null && !getProfile().isSensor) {
+ status.temperature = status.tmp.tC = result.temperature0.tC;
+ }
+
updated |= updateInputStatus(status, result, channelUpdate);
updated |= updateRelayStatus(status, result.switch0, channelUpdate);
updated |= updateRelayStatus(status, result.switch1, channelUpdate);
updated |= updateRelayStatus(status, result.switch2, channelUpdate);
updated |= updateRelayStatus(status, result.switch3, channelUpdate);
+ updated |= updateEmStatus(status, result.em0, channelUpdate);
updated |= updateRollerStatus(status, result.cover0, channelUpdate);
if (channelUpdate) {
updated |= ShellyComponents.updateMeters(getThing(), status);
updateHumidityStatus(sensorData, result.humidity0);
updateTemperatureStatus(sensorData, result.temperature0);
+ updateSmokeStatus(sensorData, result.smoke0);
updateBatteryStatus(sensorData, result.devicepower0);
updateAddonStatus(status, result);
updated |= ShellyComponents.updateSensors(getThing(), status);
// Update internal structures
status.relays.set(rs.id, rstatus);
- status.meters.set(rs.id, sm);
- status.emeters.set(rs.id, emeter);
relayStatus.relays.set(rs.id, sr);
- relayStatus.meters.set(rs.id, sm);
-
+ updateMeter(status, rs.id, sm, emeter, channelUpdate);
return channelUpdate ? ShellyComponents.updateRelay((ShellyBaseHandler) getThing(), status, rs.id) : false;
}
+ private void updateMeter(ShellySettingsStatus status, int id, ShellySettingsMeter sm, ShellySettingsEMeter emeter,
+ boolean channelUpdate) throws ShellyApiException {
+ status.meters.set(id, sm);
+ status.emeters.set(id, emeter);
+ relayStatus.meters.set(id, sm);
+ }
+
+ private boolean updateEmStatus(ShellySettingsStatus status, @Nullable Shelly2DeviceStatusEm em,
+ boolean channelUpdate) throws ShellyApiException {
+ if (em == null) {
+ return false;
+ }
+
+ boolean updated = false;
+ ShellySettingsMeter sm = new ShellySettingsMeter();
+ ShellySettingsEMeter emeter = status.emeters.get(0);
+ sm.isValid = emeter.isValid = true;
+ if (em.aActPower != null) {
+ sm.power = emeter.power = em.aActPower;
+ }
+ if (em.aAprtPower != null) {
+ emeter.totalReturned = em.aAprtPower;
+ }
+ if (em.aVoltage != null) {
+ emeter.voltage = em.aVoltage;
+ }
+ if (em.aCurrent != null) {
+ emeter.current = em.aCurrent;
+ }
+ if (em.aPF != null) {
+ emeter.pf = em.aPF;
+ }
+ // Update internal structures
+ updateMeter(status, 0, sm, emeter, channelUpdate);
+
+ sm = new ShellySettingsMeter();
+ emeter = status.emeters.get(1);
+ sm.isValid = emeter.isValid = true;
+ if (em.bActPower != null) {
+ sm.power = emeter.power = em.bActPower;
+ }
+ if (em.bAprtPower != null) {
+ emeter.totalReturned = em.bAprtPower;
+ }
+ if (em.bVoltage != null) {
+ emeter.voltage = em.bVoltage;
+ }
+ if (em.bCurrent != null) {
+ emeter.current = em.bCurrent;
+ }
+ if (em.bPF != null) {
+ emeter.pf = em.bPF;
+ }
+ // Update internal structures
+ updateMeter(status, 1, sm, emeter, channelUpdate);
+
+ sm = new ShellySettingsMeter();
+ emeter = status.emeters.get(2);
+ sm.isValid = emeter.isValid = true;
+ if (em.cActPower != null) {
+ sm.power = emeter.power = em.cActPower;
+ }
+ if (em.cAprtPower != null) {
+ emeter.totalReturned = em.cAprtPower;
+ }
+ if (em.cVoltage != null) {
+ emeter.voltage = em.cVoltage;
+ }
+ if (em.cCurrent != null) {
+ emeter.current = em.cCurrent;
+ }
+ if (em.cPF != null) {
+ emeter.pf = em.cPF;
+ }
+ // Update internal structures
+ updateMeter(status, 2, sm, emeter, channelUpdate);
+
+ return channelUpdate ? ShellyComponents.updateMeters(getThing(), status) : false;
+ }
+
protected @Nullable ArrayList<@Nullable ShellySettingsRoller> fillRollerSettings(ShellyDeviceProfile profile,
Shelly2GetConfigResult dc) {
if (dc.cover0 == null) {
if (cs.aenergy != null) {
sm.total = emeter.total = cs.aenergy.total;
sm.counters = cs.aenergy.byMinute;
- sm.timestamp = (long) cs.aenergy.minuteTs;
+ if (cs.aenergy.minuteTs != null) {
+ sm.timestamp = (long) cs.aenergy.minuteTs;
+ }
}
if (cs.voltage != null) {
emeter.voltage = cs.voltage;
sdata.tmp.tF = value.tF;
}
+ protected void updateSmokeStatus(ShellyStatusSensor sdata, @Nullable Shelly2DeviceStatusSmoke value) {
+ if (value == null) {
+ return;
+ }
+ sdata.smoke = getBool(value.alarm);
+ sdata.mute = getBool(value.mute);
+ }
+
protected void updateBatteryStatus(ShellyStatusSensor sdata, @Nullable Shelly2DeviceStatusPower value) {
if (value == null) {
return;
public static final String SHELLYRPC_METHOD_CLOUDSET = "Cloud.SetConfig";
public static final String SHELLYRPC_METHOD_WSGETCONFIG = "WS.GetConfig";
public static final String SHELLYRPC_METHOD_WSSETCONFIG = "WS.SetConfig";
+ public static final String SHELLYRPC_METHOD_SMOKE_SETCONFIG = "Smoke.SetConfig";
+ public static final String SHELLYRPC_METHOD_SMOKE_MUTE = "Smoke.Mute";
public static final String SHELLYRPC_METHOD_NOTIFYSTATUS = "NotifyStatus"; // inbound status
public static final String SHELLYRPC_METHOD_NOTIFYFULLSTATUS = "NotifyFullStatus"; // inbound status from bat device
public Double currentLimit;
}
+ public static class Shelly2DevConfigEm {
+ public Integer id;
+ public String name;
+ @SerializedName("blink_mode_selector")
+ public String blinkModeSelector;
+ @SerializedName("phase_selector")
+ public String phase_selector;
+ @SerializedName("monitor_phase_sequence")
+ public Boolean monitorPhaseSequence;
+ }
+
public class Shelly2DevConfigCover {
public class Shelly2DeviceConfigCoverMotor {
@SerializedName("idle_power_thr")
public Shelly2DeviceConfigCoverObstructionDetection obstructionDetection;
}
+ public static class Shelly2ConfigSmoke {
+ public Integer id;
+ public Boolean alarm;
+ public Boolean mute;
+ }
+
public static class Shelly2GetConfigResult {
public class Shelly2DevConfigCloud {
@SerializedName("switch:3")
public Shelly2DevConfigSwitch switch3;
+ @SerializedName("em:0")
+ public Shelly2DevConfigEm em0;
+
@SerializedName("cover:0")
public Shelly2DevConfigCover cover0;
+
+ @SerializedName("smoke:0")
+ public Shelly2ConfigSmoke smoke0;
}
public class Shelly2DeviceConfigSta {
public Shelly2DeviceStatusCharger external;
}
+ public static class Shelly2DeviceStatusEm {
+ public Integer id;
+
+ @SerializedName("a_current")
+ public Double aCurrent;
+ @SerializedName("a_voltage")
+ public Double aVoltage;
+ @SerializedName("a_act_power")
+ public Double aActPower;
+ @SerializedName("a_aprt_power")
+ public Double aAprtPower;
+ @SerializedName("a_pf")
+ public Double aPF;
+
+ @SerializedName("b_current")
+ public Double bCurrent;
+ @SerializedName("b_voltage")
+ public Double bVoltage;
+ @SerializedName("b_act_power")
+ public Double bActPower;
+ @SerializedName("b_aprt_power")
+ public Double bAprtPower;
+ @SerializedName("b_pf")
+ public Double bPF;
+
+ @SerializedName("c_current")
+ public Double cCurrent;
+ @SerializedName("c_voltage")
+ public Double cVoltage;
+ @SerializedName("c_act_power")
+ public Double cActPower;
+ @SerializedName("c_aprt_power")
+ public Double cAprtPower;
+ @SerializedName("c_pf")
+ public Double cPF;
+
+ @SerializedName("n_current")
+ public Double nCurrent;
+ }
+
+ public static class Shelly2DeviceStatusEmData {
+ public Integer id;
+ public String[] errors;
+ }
+
+ public class Shelly2DeviceStatusSmoke {
+ public Integer id;
+ public Boolean alarm;
+ public Boolean mute;
+ }
+
public Shelly2DeviceStatusBle ble;
public Shelly2DeviceStatusCloud cloud;
public Shelly2DeviceStatusMqqt mqtt;
@SerializedName("switch:3")
public Shelly2RelayStatus switch3;
+ @SerializedName("em:0")
+ Shelly2DeviceStatusEm em0;
+ @SerializedName("emdata:0")
+ Shelly2DeviceStatusEmData emdata0;
+
@SerializedName("cover:0")
public Shelly2CoverStatus cover0;
public Shelly2DeviceStatusHumidity humidity0;
@SerializedName("humidity:100")
public Shelly2DeviceStatusHumidity humidity100;
+ @SerializedName("smoke:0")
+ public Shelly2DeviceStatusSmoke smoke0;
@SerializedName("voltmeter:100")
public Shelly2DeviceStatusVoltage voltmeter100;
fillWiFiSta(dc.wifi.sta, profile.settings.wifiSta);
fillWiFiSta(dc.wifi.sta1, profile.settings.wifiSta1);
+ profile.numMeters = 0;
if (profile.hasRelays) {
profile.status.relays = new ArrayList<>();
- profile.status.meters = new ArrayList<>();
- profile.status.emeters = new ArrayList<>();
relayStatus.relays = new ArrayList<>();
- relayStatus.meters = new ArrayList<>();
profile.numMeters = profile.isRoller ? profile.numRollers : profile.numRelays;
for (int i = 0; i < profile.numRelays; i++) {
profile.status.relays.add(new ShellySettingsRelay());
relayStatus.relays.add(new ShellyShortStatusRelay());
}
- for (int i = 0; i < profile.numMeters; i++) {
- profile.status.meters.add(new ShellySettingsMeter());
- profile.status.emeters.add(new ShellySettingsEMeter());
- relayStatus.meters.add(new ShellySettingsMeter());
- }
}
if (profile.numInputs > 0) {
}
}
+ if (dc.em0 != null) {
+ profile.numMeters = 3;
+ }
+
+ if (profile.numMeters > 0) {
+ profile.status.meters = new ArrayList<>();
+ profile.status.emeters = new ArrayList<>();
+ relayStatus.meters = new ArrayList<>();
+
+ for (int i = 0; i < profile.numMeters; i++) {
+ profile.status.meters.add(new ShellySettingsMeter());
+ profile.status.emeters.add(new ShellySettingsEMeter());
+ relayStatus.meters.add(new ShellySettingsMeter());
+ }
+ }
+
if (profile.isRoller) {
profile.status.rollers = new ArrayList<>();
for (int i = 0; i < profile.numRollers; i++) {
private void checkSetWsCallback() throws ShellyApiException {
Shelly2ConfigParms wsConfig = apiRequest(SHELLYRPC_METHOD_WSGETCONFIG, null, Shelly2ConfigParms.class);
String url = "ws://" + config.localIp + ":" + config.localPort + "/shelly/wsevent";
- if (!getBool(wsConfig.enable) || !url.equalsIgnoreCase(getString(wsConfig.server))) {
+ if (!config.localIp.isEmpty() && !getBool(wsConfig.enable)
+ || !url.equalsIgnoreCase(getString(wsConfig.server))) {
logger.debug("{}: A battery device was detected without correct callback, fix it", thingName);
wsConfig.enable = true;
wsConfig.server = url;
thingName, thingName, message.src, message.dst, discovery);
return;
}
+ if (t.isStopping()) {
+ logger.debug("{}: Thing is shutting down, ignore WebSocket message", thingName);
+ return;
+ }
if (!t.isThingOnline() && t.getThingStatusDetail() != ThingStatusDetail.CONFIGURATION_PENDING) {
logger.debug("{}: Thing is not in online state/connectable, ignore NotifyStatus", thingName);
return;
apiRequest(req);
}
+ @Override
+ public void resetMeterTotal(int id) throws ShellyApiException {
+ }
+
+ @Override
+ public void muteSmokeAlarm(int index) throws ShellyApiException {
+ apiRequest(new Shelly2RpcRequest().withMethod(SHELLYRPC_METHOD_SMOKE_MUTE).withId(index));
+ }
+
@Override
public ShellySettingsLogin getLoginSettings() throws ShellyApiException {
return new ShellySettingsLogin();
public static final String SHELLYDT_PLUS2PM_ROLLER = "SNSW-002P16EU-roller";
public static final String SHELLYDT_PLUS2PM_RELAY_2 = "SNSW-102P16EU-relay";
public static final String SHELLYDT_PLUS2PM_ROLLER_2 = "SNSW-102P16EU-roller";
+ public static final String SHELLYDT_PLUSPLUGS = "SNPL-00112EU";
+ public static final String SHELLYDT_PLUSPLUGIT = "SNPL-00110IT";
+ public static final String SHELLYDT_PLUSPLUGUK = "SNPL-00112UK";
public static final String SHELLYDT_PLUSPLUGUS = "SNPL-00116US";
public static final String SHELLYDT_PLUSI4 = "SNSN-0024X";
public static final String SHELLYDT_PLUSI4DC = "SNSN-0D24X";
public static final String SHELLYDT_PLUSHT = "SNSN-0013A";
+ public static final String SHELLYDT_PLUSSMOKE = "SNSN-0031Z";
// Shelly Pro Series
public static final String SHELLYDT_PRO1 = "SPSW-001XE16EU";
public static final String SHELLYDT_PRO2PM_RELAY_3 = "SPSW-202PE16EU-relay";
public static final String SHELLYDT_PRO2PM_ROLLER_3 = "SPSW-202PE16EU-roller";
public static final String SHELLYDT_PRO3 = "SPSW-003XE16EU";
+ public static final String SHELLYDT_PRO3EM = "SPEM-003CEBEU";
public static final String SHELLYDT_PRO4PM = "SPSW-004PE16EU";
public static final String SHELLYDT_PRO4PM_2 = "SPSW-104PE16EU";
public static final String THING_TYPE_SHELLYPLUSI4_STR = "shellyplusi4";
public static final String THING_TYPE_SHELLYPLUSI4DC_STR = "shellyplusi4dc";
public static final String THING_TYPE_SHELLYPLUSHT_STR = "shellyplusht";
+ public static final String THING_TYPE_SHELLYPLUSSMOKE_STR = "shellyplussmoke";
+ public static final String THING_TYPE_SHELLYPLUSPLUGS_STR = "shellyplusplug";
public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus";
// Shelly Pro Series
public static final String THING_TYPE_SHELLYPRO2PM_RELAY_STR = "shellypro2pm-relay";
public static final String THING_TYPE_SHELLYPRO2PM_ROLLER_STR = "shellypro2pm-roller";
public static final String THING_TYPE_SHELLYPRO3_STR = "shellypro3";
+ public static final String THING_TYPE_SHELLYPRO3EM_STR = "shellypro3em";
public static final String THING_TYPE_SHELLYPRO4PM_STR = "shellypro4pm";
public static final String THING_TYPE_SHELLYPROTECTED_STR = "shellydevice";
THING_TYPE_SHELLYPLUSI4DC_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSHT = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSHT_STR);
+ public static final ThingTypeUID THING_TYPE_SHELLYPLUSSMOKE = new ThingTypeUID(BINDING_ID,
+ THING_TYPE_SHELLYPLUSSMOKE_STR);
+ public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGS = new ThingTypeUID(BINDING_ID,
+ THING_TYPE_SHELLYPLUSPLUGS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGUS = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSPLUGUS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO2PM_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO3 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO3_STR);
+ public static final ThingTypeUID THING_TYPE_SHELLYPRO3EM = new ThingTypeUID(BINDING_ID,
+ THING_TYPE_SHELLYPRO3EM_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO4PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO4PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS2PM_ROLLER, THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS2PM_RELAY_2, THING_TYPE_SHELLYPLUS2PM_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS2PM_ROLLER_2, THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_PLUSPLUGS, THING_TYPE_SHELLYPLUSPLUGS_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_PLUSPLUGIT, THING_TYPE_SHELLYPLUSPLUGS_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_PLUSPLUGUK, THING_TYPE_SHELLYPLUSPLUGS_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSPLUGUS, THING_TYPE_SHELLYPLUSPLUGUS_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSI4DC, THING_TYPE_SHELLYPLUSI4DC_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_PLUSSMOKE, THING_TYPE_SHELLYPLUSSMOKE_STR);
// Pro Series
THING_TYPE_MAPPING.put(SHELLYDT_PRO1, THING_TYPE_SHELLYPRO1_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_ROLLER_2, THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_ROLLER_3, THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO3, THING_TYPE_SHELLYPRO3_STR);
+ THING_TYPE_MAPPING.put(SHELLYDT_PRO3EM, THING_TYPE_SHELLYPRO3EM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO4PM, THING_TYPE_SHELLYPRO4PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO4PM_2, THING_TYPE_SHELLYPRO4PM_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_SHELLY1L_STR, THING_TYPE_SHELLY1L_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLY3EM_STR, THING_TYPE_SHELLY3EM_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYEM_STR, THING_TYPE_SHELLYEM_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLY4PRO_STR, THING_TYPE_SHELLY4PRO_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYDIMMER2_STR, THING_TYPE_SHELLYDIMMER2_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYDIMMER_STR, THING_TYPE_SHELLYDIMMER_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYIX3_STR, THING_TYPE_SHELLYIX3_STR);
- THING_TYPE_MAPPING.put(THING_TYPE_SHELLY3EM_STR, THING_TYPE_SHELLY3EM_STR);
- THING_TYPE_MAPPING.put(THING_TYPE_SHELLYEM_STR, THING_TYPE_SHELLYEM_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYDUORGBW_STR, THING_TYPE_SHELLYDUORGBW_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYDUO_STR, THING_TYPE_SHELLYDUO_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYVINTAGE_STR, THING_TYPE_SHELLYVINTAGE_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYUNI_STR, THING_TYPE_SHELLYUNI_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYMOTION2_STR, THING_TYPE_SHELLYMOTION_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS1PM_STR, THING_TYPE_SHELLYPLUS1PM_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS1_STR, THING_TYPE_SHELLYPLUS1_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS1PM_STR, THING_TYPE_SHELLYPLUS1PM_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS2PM_RELAY_STR, THING_TYPE_SHELLYPLUS2PM_RELAY_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS2PM_ROLLER_STR, THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS2PM_RELAY_STR, THING_TYPE_SHELLYPLUS2PM_RELAY_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUS2PM_ROLLER_STR, THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSPLUGS_STR, THING_TYPE_SHELLYPLUSPLUGS_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSPLUGUS_STR, THING_TYPE_SHELLYPLUSPLUGUS_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPLUSI4DC_STR, THING_TYPE_SHELLYPLUSI4DC_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_SHELLYPLUSSMOKE_STR, THING_TYPE_SHELLYPLUSSMOKE_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_SHELLYPRO2PM_RELAY_STR, THING_TYPE_SHELLYPRO2PM_RELAY_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO2PM_ROLLER_STR, THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO2_RELAY_STR, THING_TYPE_SHELLYPRO2_RELAY_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO3EM_STR, THING_TYPE_SHELLYPRO3EM_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO3_STR, THING_TYPE_SHELLYPRO3_STR);
+ THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPRO4PM_STR, THING_TYPE_SHELLYPRO4PM_STR);
+
THING_TYPE_MAPPING.put(THING_TYPE_SHELLYPROTECTED_STR, THING_TYPE_SHELLYPROTECTED_STR);
}
if (coap != null) {
coap.stop();
}
- requestUpdates(1, true);// force re-initialization
+ stopping = false;
+ reinitializeThing();// force re-initialization
}
/**
*/
public boolean initializeThing() throws ShellyApiException {
// Init from thing type to have a basic profile, gets updated when device info is received from API
- stopping = false;
refreshSettings = false;
lastWakeupReason = "";
cache.setThingName(thingName);
return false;
}
+ profile.initFromThingType(thingType); // do some basic initialization
+
// Gen 1 only: Setup CoAP listener to we get the CoAP message, which triggers initialization even the thing
// could not be fully initialized here. In this case the CoAP messages triggers auto-initialization (like the
// Action URL does when enabled)
// Initialize API access, exceptions will be catched by initialize()
api.initialize();
- profile.initFromThingType(thingType);
ShellySettingsDevice devInfo = api.getDeviceInfo();
if (getBool(devInfo.auth) && config.password.isEmpty()) {
setThingOffline(ThingStatusDetail.CONFIGURATION_ERROR, "offline.conf-error-no-credentials");
return;
}
- if (!profile.isInitialized()) {
+ if (!profile.isInitialized() || (isThingOffline() && profile.alwaysOn)) {
logger.debug("{}: {}", thingName, messages.get("command.init", command));
initializeThing();
} else {
logger.debug("{}: Set boost timer to {}", thingName, command);
api.setValveBoostTime(0, (int) getNumber(command));
break;
-
+ case CHANNEL_SENSOR_MUTE:
+ if (profile.isSmoke && ((OnOffType) command) == OnOffType.ON) {
+ logger.debug("{}: Mute Smoke Alarm", thingName);
+ api.muteSmokeAlarm(0);
+ updateChannel(getString(channelUID.getGroupId()), CHANNEL_SENSOR_MUTE, OnOffType.OFF);
+ }
+ break;
default:
update = handleDeviceCommand(channelUID, command);
break;
logger.debug("{}: Status update triggered thing initialization", thingName);
initializeThing(); // may fire an exception if initialization failed
}
- // Get profile, if refreshSettings == true reload settings from device
ShellySettingsStatus status = api.getStatus();
- if (status.uptime != null && status.uptime == 0 && profile.alwaysOn) {
- status = api.getStatus();
- }
boolean restarted = checkRestarted(status);
profile = getProfile(refreshSettings || restarted);
profile.status = status;
status = "offline.conf-error-access-denied";
} else if (isWatchdogStarted()) {
if (!isWatchdogExpired()) {
- logger.debug("{}: Ignore API Timeout, retry later", thingName);
+ logger.debug("{}: Ignore API Timeout on {} {}, retry later", thingName, res.method, res.url);
} else {
if (isThingOnline()) {
status = "offline.status-error-watchdog";
@Override
public void reinitializeThing() {
logger.debug("{}: Re-Initialize Thing", thingName);
- if (stopping) {
+ if (isStopping()) {
logger.debug("{}: Handler is shutting down, ignore", thingName);
return;
}
requestUpdates(0, true);
}
+ @Override
+ public boolean isStopping() {
+ return stopping;
+ }
+
@Override
public void fillDeviceStatus(ShellySettingsStatus status, boolean updated) {
String alarm = "";
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyADC;
+import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyExtTemperature.ShellyShortTemp;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions;
-import org.openhab.core.library.types.OnOffType;
-import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
if (status.extSwitch != null) {
if (status.extSwitch.input0 != null) {
updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_INPUT1,
- getInteger(status.extSwitch.input0.input) == 1 ? OpenClosedType.OPEN
- : OpenClosedType.CLOSED);
+ getOpenClosed(getInteger(status.extSwitch.input0.input) == 1));
}
}
if (status.extTemperature != null) {
// Shelly 1/1PM support up to 3 external sensors
// for whatever reason those are not represented as an array, but 3 elements
- if (status.extTemperature.sensor1 != null) {
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_TEMP1,
- toQuantityType(getDouble(status.extTemperature.sensor1.tC), DIGITS_TEMP, SIUnits.CELSIUS));
- }
- if (status.extTemperature.sensor2 != null) {
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_TEMP2,
- toQuantityType(getDouble(status.extTemperature.sensor2.tC), DIGITS_TEMP, SIUnits.CELSIUS));
- }
- if (status.extTemperature.sensor3 != null) {
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_TEMP3,
- toQuantityType(getDouble(status.extTemperature.sensor3.tC), DIGITS_TEMP, SIUnits.CELSIUS));
- }
- if (status.extTemperature.sensor4 != null) {
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_TEMP4,
- toQuantityType(getDouble(status.extTemperature.sensor4.tC), DIGITS_TEMP, SIUnits.CELSIUS));
- }
- if (status.extTemperature.sensor5 != null) {
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_TEMP5,
- toQuantityType(getDouble(status.extTemperature.sensor5.tC), DIGITS_TEMP, SIUnits.CELSIUS));
- }
+ updated |= updateTempChannel(status.extTemperature.sensor1, thingHandler, CHANNEL_ESENSOR_TEMP1);
+ updated |= updateTempChannel(status.extTemperature.sensor2, thingHandler, CHANNEL_ESENSOR_TEMP2);
+ updated |= updateTempChannel(status.extTemperature.sensor3, thingHandler, CHANNEL_ESENSOR_TEMP3);
+ updated |= updateTempChannel(status.extTemperature.sensor4, thingHandler, CHANNEL_ESENSOR_TEMP4);
+ updated |= updateTempChannel(status.extTemperature.sensor5, thingHandler, CHANNEL_ESENSOR_TEMP5);
}
if ((status.extHumidity != null) && (status.extHumidity.sensor1 != null)) {
updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_ESENSOR_HUMIDITY,
String groupName = profile.getMeterGroup(m);
if (!thingHandler.areChannelsCreated()) {
thingHandler.updateChannelDefinitions(ShellyChannelDefinitions
- .createEMeterChannels(thingHandler.getThing(), emeter, groupName));
+ .createEMeterChannels(thingHandler.getThing(), profile, emeter, groupName));
}
// convert Watt/Hour tok w/h
updated |= thingHandler.updateChannel(groupName, CHANNEL_EMETER_VOLTAGE,
toQuantityType(getDouble(emeter.voltage), DIGITS_VOLT, Units.VOLT));
updated |= thingHandler.updateChannel(groupName, CHANNEL_EMETER_CURRENT,
- toQuantityType(getDouble(emeter.current), DIGITS_VOLT, Units.AMPERE));
+ toQuantityType(getDouble(emeter.current), DIGITS_AMPERE, Units.AMPERE));
updated |= thingHandler.updateChannel(groupName, CHANNEL_EMETER_PFACTOR,
toQuantityType(computePF(emeter), Units.PERCENT));
if ((sdata.sensor != null) && sdata.sensor.isValid) {
// Shelly DW: “sensor”:{“state”:“open”, “is_valid”:true},
updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_STATE,
- getString(sdata.sensor.state).equalsIgnoreCase(SHELLY_API_DWSTATE_OPEN) ? OpenClosedType.OPEN
- : OpenClosedType.CLOSED);
+ getOpenClosed(getString(sdata.sensor.state).equalsIgnoreCase(SHELLY_API_DWSTATE_OPEN)));
String sensorError = sdata.sensorError;
boolean changed = thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ERROR,
getStringType(sensorError));
}
updated |= changed;
}
- if ((sdata.tmp != null) && getBool(sdata.tmp.isValid)) {
+ if (sdata.tmp != null && getBool(sdata.tmp.isValid)) {
Double temp = getString(sdata.tmp.units).toUpperCase().equals(SHELLY_TEMP_CELSIUS)
? getDouble(sdata.tmp.tC)
: getDouble(sdata.tmp.tF);
- if (getString(sdata.tmp.units).toUpperCase().equals(SHELLY_TEMP_FAHRENHEIT)) {
- // convert Fahrenheit to Celsius
- temp = ImperialUnits.FAHRENHEIT.getConverterTo(SIUnits.CELSIUS).convert(temp).doubleValue();
- }
- temp = convertToC(temp, getString(sdata.tmp.units));
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
- toQuantityType(temp.doubleValue(), DIGITS_TEMP, SIUnits.CELSIUS));
+ updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
+ temp.doubleValue(), getString(sdata.tmp.units));
} else if (status.thermostats != null) {
// Shelly TRV
if (profile.settings.thermostats != null) {
toQuantityType((double) bminutes, DIGITS_NONE, Units.MINUTE));
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_MODE, getStringType(
getBool(t.targetTemp.enabled) ? SHELLY_TRV_MODE_AUTO : SHELLY_TRV_MODE_MANUAL));
+ updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_OPEN,
+ getOpenClosed(t.windowOpen));
+
int pid = getBool(t.schedule) ? getInteger(t.profile) : 0;
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SCHEDULE,
getOnOff(t.schedule));
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_PROFILE,
getStringType(profile.getValueProfile(0, pid)));
if (t.tmp != null) {
- Double temp = convertToC(t.tmp.value, getString(t.tmp.units));
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
- toQuantityType(temp.doubleValue(), DIGITS_TEMP, SIUnits.CELSIUS));
- temp = convertToC(t.targetTemp.value, getString(t.targetTemp.unit));
- updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SETTEMP,
- toQuantityType(t.targetTemp.value, DIGITS_TEMP, SIUnits.CELSIUS));
+ updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TEMP,
+ t.tmp.value, t.tmp.units);
+ updated |= updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, CHANNEL_CONTROL_SETTEMP,
+ t.targetTemp.value, t.targetTemp.unit);
}
if (t.pos != null) {
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_POSITION,
t.pos != -1 ? toQuantityType(t.pos, DIGITS_NONE, Units.PERCENT) : UnDefType.UNDEF);
updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_STATE,
- getDouble(t.pos) > 0 ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
+ getOpenClosed(getDouble(t.pos) > 0));
}
}
}
updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_SMOKE,
getOnOff(sdata.smoke));
}
+ if (sdata.mute != null) {
+ updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_MUTE, getOnOff(sdata.mute));
+ }
+
if (sdata.gasSensor != null) {
updated |= thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_SELFTTEST,
getStringType(sdata.gasSensor.selfTestState));
boolean charger = (getInteger(profile.settings.externalPower) == 1) || getBool(sdata.charger);
if ((profile.settings.externalPower != null) || (sdata.charger != null)) {
updated |= thingHandler.updateChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_CHARGER,
- charger ? OnOffType.ON : OnOffType.OFF);
+ getOnOff(charger));
}
if (sdata.bat != null) { // no update for Sense
updated |= thingHandler.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_LEVEL,
int lowBattery = thingHandler.getThingConfig().lowBattery;
boolean changed = thingHandler.updateChannel(CHANNEL_GROUP_BATTERY, CHANNEL_SENSOR_BAT_LOW,
- !charger && getDouble(sdata.bat.value) < lowBattery ? OnOffType.ON : OnOffType.OFF);
+ getOnOff(!charger && getDouble(sdata.bat.value) < lowBattery));
updated |= changed;
if (!charger && changed && getDouble(sdata.bat.value) < lowBattery) {
thingHandler.postEvent(ALARM_TYPE_LOW_BATTERY, false);
return updated;
}
- private static Double convertToC(@Nullable Double temp, String unit) {
- if (temp == null) {
- return 0.0;
+ public static boolean updateTempChannel(@Nullable ShellyShortTemp sensor, ShellyThingInterface thingHandler,
+ String channel) {
+ return sensor != null ? updateTempChannel(thingHandler, CHANNEL_GROUP_SENSOR, channel, sensor.tC, "") : false;
+ }
+
+ public static boolean updateTempChannel(ShellyThingInterface thingHandler, String group, String channel,
+ @Nullable Double temp, @Nullable String unit) {
+ if (temp == null || temp == SHELLY_API_INVTEMP) {
+ return false;
+ }
+ return thingHandler.updateChannel(group, channel,
+ toQuantityType(convertToC(temp, unit), DIGITS_TEMP, SIUnits.CELSIUS));
+ }
+
+ private static Double convertToC(@Nullable Double temp, @Nullable String unit) {
+ if (temp == null || temp == SHELLY_API_INVTEMP) {
+ return SHELLY_API_INVTEMP;
}
- if (SHELLY_TEMP_FAHRENHEIT.equalsIgnoreCase(unit)) {
+ if (SHELLY_TEMP_FAHRENHEIT.equalsIgnoreCase(getString(unit))) {
// convert Fahrenheit to Celsius
return ImperialUnits.FAHRENHEIT.getConverterTo(SIUnits.CELSIUS).convert(temp).doubleValue();
}
logger.debug("{}: Set Auto-OFF timer to {}", thingName, command);
api.setAutoTimer(rIndex, SHELLY_TIMER_AUTOOFF, getNumber(command).doubleValue());
break;
+ case CHANNEL_EMETER_RESETTOTAL:
+ logger.debug("{}: Reset Meter Totals", thingName);
+ int mIndex = Integer.parseInt(substringAfter(groupName, CHANNEL_GROUP_METER)) - 1;
+ api.resetMeterTotal(mIndex);
+ updateChannel(groupName, CHANNEL_EMETER_RESETTOTAL, OnOffType.OFF);
+ break;
}
return true;
}
void setThingOffline(ThingStatusDetail detail, String messageKey, Object... arguments);
+ boolean isStopping();
+
String getThingType();
ThingStatus getThingStatus();
list.put(ACTION_PROTECT, "Protect Device");
}
- if ((profile.settings.coiot != null) && profile.settings.coiot.peer != null) {
+ if (profile.settings.coiot != null && profile.settings.coiot.peer != null) {
boolean mcast = profile.settings.coiot.peer.isEmpty()
|| SHELLY_COIOT_MCAST.equalsIgnoreCase(profile.settings.coiot.peer) || profile.isMotion;
list.put(mcast ? ACTION_SETCOIOT_PEER : ACTION_SETCOIOT_MCAST,
mcast ? "Set CoIoT Peer Mode" : "Set CoIoT Multicast Mode");
}
if (profile.isSensor && !profile.isMotion && profile.settings.wifiSta != null
- && profile.settings.wifiSta.enabled) {
+ && getBool(profile.settings.wifiSta.enabled)) {
// FW 1.10+: Reset STA list, force WiFi rescan and connect to stringest AP
list.put(ACTION_RESSTA, "Reconnect WiFi");
}
- if (!gen2 && profile.settings.apRoaming != null) {
+ if (!gen2 && profile.settings.apRoaming != null && profile.settings.apRoaming.enabled != null) {
list.put(!profile.settings.apRoaming.enabled ? ACTION_ENAPROAMING : ACTION_DISAPROAMING,
!profile.settings.apRoaming.enabled ? "Enable WiFi Roaming" : "Disable WiFi Roaming");
}
!profile.settings.bluetooth ? "Enable Bluetooth" : "Disable Bluetooth");
}
- boolean set = profile.settings.cloud != null && profile.settings.cloud.enabled;
+ boolean set = profile.settings.cloud != null && getBool(profile.settings.cloud.enabled);
list.put(set ? ACTION_DISCLOUD : ACTION_ENCLOUD, set ? "Disable Cloud" : "Enable Cloud");
list.put(ACTION_RESET, "-Factory Reset");
.add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_VOLTAGE, "meterVoltage", ITEMT_VOLT))
.add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_CURRENT, "meterCurrent", ITEMT_AMP))
.add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_PFACTOR, "meterPowerFactor", ITEMT_NUMBER))
+ .add(new ShellyChannel(m, CHGR_METER, CHANNEL_EMETER_RESETTOTAL, "meterResetTotals", ITEMT_SWITCH))
// Sensors
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_TEMP, "sensorTemp", ITEMT_TEMP))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_ILLUM, "sensorIllumination", ITEMT_STRING))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VOLTAGE, "sensorADC", ITEMT_VOLT))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_STATE, "sensorContact", ITEMT_CONTACT))
+ .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_OPEN, "sensorOpen", ITEMT_CONTACT))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_SSTATE, "sensorState", ITEMT_STRING))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_TILT, "sensorTilt", ITEMT_ANGLE))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION, "sensorMotion", ITEMT_SWITCH))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VIBRATION, "vibration", ITEMT_SWITCH))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_FLOOD, "sensorFlood", ITEMT_SWITCH))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_SMOKE, "sensorSmoke", ITEMT_SWITCH))
+ .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MUTE, "sensorMute", ITEMT_SWITCH))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_PPM, "sensorPPM", ITEMT_NUMBER))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VALVE, "sensorValve", ITEMT_STRING))
.add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_ALARM_STATE, "alarmState", ITEMT_STRING))
return newChannels;
}
- public static Map<String, Channel> createEMeterChannels(final Thing thing, final ShellySettingsEMeter emeter,
- String group) {
+ public static Map<String, Channel> createEMeterChannels(final Thing thing, final ShellyDeviceProfile profile,
+ final ShellySettingsEMeter emeter, String group) {
Map<String, Channel> newChannels = new LinkedHashMap<>();
addChannel(thing, newChannels, emeter.power != null, group, CHANNEL_METER_CURRENTWATTS);
addChannel(thing, newChannels, emeter.total != null, group, CHANNEL_METER_TOTALKWH);
addChannel(thing, newChannels, emeter.voltage != null, group, CHANNEL_EMETER_VOLTAGE);
addChannel(thing, newChannels, emeter.current != null, group, CHANNEL_EMETER_CURRENT);
addChannel(thing, newChannels, emeter.pf != null, group, CHANNEL_EMETER_PFACTOR); // EM has no PF. but power
-
+ addChannel(thing, newChannels, emeter.total != null && profile.numMeters > 1, group, CHANNEL_EMETER_RESETTOTAL); // 3EM
addChannel(thing, newChannels, true, group, CHANNEL_LAST_UPDATE);
return newChannels;
}
addChannel(thing, newChannels, sdata.lux != null && sdata.lux.illumination != null, CHANNEL_GROUP_SENSOR,
CHANNEL_SENSOR_ILLUM);
addChannel(thing, newChannels, sdata.flood != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_FLOOD);
- addChannel(thing, newChannels, sdata.smoke != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_FLOOD);
+ addChannel(thing, newChannels, sdata.smoke != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_SMOKE);
+ addChannel(thing, newChannels, sdata.mute != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_MUTE);
addChannel(thing, newChannels, profile.settings.externalPower != null || sdata.charger != null, CHGR_DEVST,
CHANNEL_DEVST_CHARGER);
addChannel(thing, newChannels, sdata.motion != null || (sdata.sensor != null && sdata.sensor.motion != null),
addChannel(thing, newChannels, true, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_PROFILE);
addChannel(thing, newChannels, true, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SCHEDULE);
addChannel(thing, newChannels, true, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_STATE);
+ addChannel(thing, newChannels, true, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_OPEN);
}
// Battery
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
}
public static OnOffType getOnOff(@Nullable Boolean value) {
- return (value != null ? value ? OnOffType.ON : OnOffType.OFF : OnOffType.OFF);
+ return (value != null && value ? OnOffType.ON : OnOffType.OFF);
+ }
+
+ public static OpenClosedType getOpenClosed(@Nullable Boolean value) {
+ return (value != null && value ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
}
public static OnOffType getOnOff(int value) {
thing-type.shelly.shellyix3.description = Shelly ix3 (Activation Device with 3 inputs)
thing-type.shelly.shellypludht.description = Shelly Plus HT - Temperature and Humidity Sensor
-# Plus/Pro devices
+# Plus Devices
thing-type.shelly.shellyplus1.description = Shelly Plus 1 (Single Relay Switch)
thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - Single Relay Switch with Power Meter
thing-type.shelly.shellyplus2-relay.description = Shelly Plus 2PM - Dual Relay Switch with Power Meter
thing-type.shelly.shellyplus2pm-roller.description = Shelly Plus 2PM - Roller Control with Power Meter
+thing-type.shelly.shellyplusplug.description = Shelly Plus Plug S/IT/UK/US . Outlet with Power Meter
thing-type.shelly.shellyplusht.description = Shelly Plus HT - Humidity and Temperature sensor with display
thing-type.shelly.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.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.shellypro3em.description = Shelly Pro 3EM - 3xPower Meter
thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay 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.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
thing-type.shelly.shellypro1.description = Shelly Pro 1 - Single Relay Switch
channel-type.shelly.lastPower1.description = Last power consumption #1 - one rounded minute
channel-type.shelly.meterTotal.label = Total Energy Consumption
channel-type.shelly.meterTotal.description = Total energy consumption in kW/h since the device powered up (resets on restart)
+channel-type.shelly.meterResetTotals.label = Reset Totals
+channel-type.shelly.meterResetTotals.description = Resets totals measurement data
channel-type.shelly.meterReturned.label = Total Returned Energy
channel-type.shelly.meterReturned.description = Total returned energy in kW/h
channel-type.shelly.meterVoltage.label = Voltage
channel-type.shelly.sensorFlood.description = Indicates flood / water detection when toggled ON
channel-type.shelly.sensorSmoke.label = Smoke Alarm
channel-type.shelly.sensorSmoke.description = Indicates smoke detection when toggled ON
+channel-type.shelly.sensorMute.label = Mute
+channel-type.shelly.sensorMute.description = Indicates mute setting (ON=muted)
channel-type.shelly.sensorLux.label = Lux
channel-type.shelly.sensorLux.description = Brightness from the sensor (Lux)
channel-type.shelly.sensorIllumination.label = Illumination
channel-type.shelly.sensorContact.description = State of the contact (open/closed)
channel-type.shelly.sensorContact.state.option.OPEN = Open
channel-type.shelly.sensorContact.state.option.CLOSED = Closed
+channel-type.shelly.sensorOpen.label = Open
+channel-type.shelly.sensorOpen.description = OPEN or CLOSED
+channel-type.shelly.sensorOpen.state.option.OPEN = Open
+channel-type.shelly.sensorOpen.state.option.CLOSED = Closed
channel-type.shelly.sensorState.label = Sensor State
channel-type.shelly.sensorState.description = Sensor State (Warm-Up/Normal/Fault/Unknown)
channel-type.shelly.sensorState.state.option.warmup = Warm-Up
</state>
</channel-type>
+ <channel-type id="meterResetTotals">
+ <item-type>Switch</item-type>
+ <label>@text/channel-type.shelly.meterResetTotals.label</label>
+ <description>@text/channel-type.shelly.meterResetTotals.description</description>
+ </channel-type>
+
<channel-type id="timestamp">
<item-type>DateTime</item-type>
<label>@text/channel-type.shelly.timestamp.label</label>
</state>
</channel-type>
+ <channel-type id="sensorOpen">
+ <item-type>Contact</item-type>
+ <label>@text/channel-type.shelly.sensorOpen.label</label>
+ <description>@text/channel-type.shelly.sensorOpen.description</description>
+ <state pattern="%s" readOnly="true">
+ <options>
+ <option value="OPEN">@text/channel-type.shelly.sensorOpen.state.option.OPEN</option>
+ <option value="CLOSED">@text/channel-type.shelly.sensorOpen.state.option.CLOSED</option>
+ </options>
+ </state>
+ </channel-type>
+
<channel-type id="sensorState">
<item-type>String</item-type>
<label>@text/channel-type.shelly.sensorState.label</label>
</state>
</channel-type>
+ <channel-type id="sensorMute">
+ <item-type>Switch</item-type>
+ <label>@text/channel-type.shelly.sensorMute.label</label>
+ <description>@text/channel-type.shelly.sensorMute.description</description>
+ </channel-type>
+
<channel-type id="sensorLux">
<item-type>Number:Illuminance</item-type>
<label>@text/channel-type.shelly.sensorLux.label</label>
<config-description-ref uri="thing-type:shelly:roller-gen2"/>
</thing-type>
+ <thing-type id="shellyplusplug">
+ <label>ShellyPlus Plug</label>
+ <description>@text/thing-type.shelly.shellyplusplug.description</description>
+ <category>PowerOutlet</category>
+ <channel-groups>
+ <channel-group id="relay" typeId="relayChannelPlug"/>
+ <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:relay-gen2"/>
+ </thing-type>
+
<thing-type id="shellyplusi4">
<label>ShellyPlus i4</label>
<config-description-ref uri="thing-type:shelly:relay-gen2"/>
</thing-type>
+ <thing-type id="shellypro3em">
+ <label>Shelly Pro 3EM</label>
+ <description>@text/thing-type.shelly.shellypro3em.description</description>
+ <channel-groups>
+ <channel-group id="meter1" typeId="meter">
+ <label>@text/channel-group-type.shelly.meter1.label</label>
+ </channel-group>
+ <channel-group id="meter2" typeId="meter">
+ <label>@text/channel-group-type.shelly.meter2.label</label>
+ </channel-group>
+ <channel-group id="meter3" typeId="meter">
+ <label>@text/channel-group-type.shelly.meter3.label</label>
+ </channel-group>
+ <channel-group id="relay" typeId="relayChannel"/>
+ <channel-group id="device" typeId="deviceStatus"/>
+ </channel-groups>
+
+ <representation-property>serviceName</representation-property>
+ <config-description-ref uri="thing-type:shelly:relay"/>
+ </thing-type>
<thing-type id="shellypro4pm">
<label>ShellyPro 4PM</label>
<config-description-ref uri="thing-type:shelly:battery-gen2"/>
</thing-type>
+ <thing-type id="shellyplussmoke">
+ <label>Shelly Plus Smoke</label>
+ <description>@text/thing-type.shelly.shellyplussmoke.description</description>
+ <category>SmokeDetector</category>
+ <channel-groups>
+ <channel-group id="sensors" typeId="sensorData"/>
+ <channel-group id="battery" typeId="batteryStatus"/>
+ <channel-group id="device" typeId="deviceStatus"/>
+ </channel-groups>
+
+ <representation-property>serviceName</representation-property>
+ <config-description-ref uri="thing-type:shelly:battery-gen2"/>
+ </thing-type>
+
</thing:thing-descriptions>