## Supported Devices
-### Generation 1:
+### Generation 1
| thing-type | Model | Vendor ID |
|--------------------|--------------------------------------------------------|-----------|
public static final String CHANNEL_CONTROL_SETTEMP = "targetTemp";
public static final String CHANNEL_CONTROL_POSITION = "position";
public static final String CHANNEL_CONTROL_MODE = "mode";
- public static final String CHANNEL_CONTROL_PROFILE = "selectedProfile";
public static final String CHANNEL_CONTROL_BCONTROL = "boost";
public static final String CHANNEL_CONTROL_BTIMER = "boostTimer";
public static final String CHANNEL_CONTROL_SCHEDULE = "schedule";
+ public static final String CHANNEL_CONTROL_PROFILE = "selectedProfile";
// External sensors for Shelly1/1PM
public static final String CHANNEL_ESENDOR_TEMP1 = CHANNEL_SENSOR_TEMP + "1";
private final Shelly1CoapServer coapServer;
private final ShellyThingTable thingTable;
private ShellyBindingConfiguration bindingConfig = new ShellyBindingConfiguration();
- private String localIP = "";
- private int httpPort = -1;
/**
* Activate the bundle: save properties
this.thingTable = thingTable;
bindingConfig.updateFromProperties(configProperties);
- localIP = bindingConfig.localIP;
+ String localIP = bindingConfig.localIP;
if (localIP.isEmpty()) {
localIP = ShellyUtils.getString(networkAddressService.getPrimaryIpv4HostAddress());
}
}
this.httpClient = httpClientFactory.getCommonHttpClient();
- httpPort = HttpServiceUtil.getHttpServicePort(componentContext.getBundleContext());
+ int httpPort = HttpServiceUtil.getHttpServicePort(componentContext.getBundleContext());
if (httpPort == -1) {
httpPort = 8080;
}
logger.debug("Using OH HTTP port {}", httpPort);
+ bindingConfig.localIP = localIP;
+ bindingConfig.httpPort = httpPort;
this.coapServer = new Shelly1CoapServer();
}
if (thingType.equals(THING_TYPE_SHELLYPROTECTED_STR)) {
logger.debug("{}: Create new thing of type {} using ShellyProtectedHandler", thing.getLabel(),
thingTypeUID.toString());
- handler = new ShellyProtectedHandler(thing, messages, bindingConfig, coapServer, localIP, httpPort,
- httpClient);
+ handler = new ShellyProtectedHandler(thing, messages, bindingConfig, thingTable, coapServer, httpClient);
} else if (thingType.equals(THING_TYPE_SHELLYBULB_STR) || thingType.equals(THING_TYPE_SHELLYDUO_STR)
|| thingType.equals(THING_TYPE_SHELLYRGBW2_COLOR_STR)
|| thingType.equals(THING_TYPE_SHELLYRGBW2_WHITE_STR)
|| thingType.equals(THING_TYPE_SHELLYVINTAGE_STR)) {
logger.debug("{}: Create new thing of type {} using ShellyLightHandler", thing.getLabel(),
thingTypeUID.toString());
- handler = new ShellyLightHandler(thing, messages, bindingConfig, coapServer, localIP, httpPort, httpClient);
+ handler = new ShellyLightHandler(thing, messages, bindingConfig, thingTable, coapServer, httpClient);
} else if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
logger.debug("{}: Create new thing of type {} using ShellyRelayHandler", thing.getLabel(),
thingTypeUID.toString());
- handler = new ShellyRelayHandler(thing, messages, bindingConfig, coapServer, localIP, httpPort, httpClient);
+ handler = new ShellyRelayHandler(thing, messages, bindingConfig, thingTable, coapServer, httpClient);
}
if (handler != null) {
return -1;
}
- public String getValueProfile(int profileId) {
- int id = profileId;
- if (settings.thermostats != null) {
- ShellyThermnostat t = settings.thermostats.get(0);
- id = profileId == 0 ? getInteger(t.profile) : profileId;
- if (id <= 0) {
- return "DISABLED";
- }
- return id <= t.profileNames.length ? getString(t.profileNames[id - 1]) : "" + id;
+ public String[] getValveProfileList(int valveId) {
+ if (isTRV && settings.thermostats != null && valveId <= settings.thermostats.size()) {
+ ShellyThermnostat t = settings.thermostats.get(valveId);
+ return t.profileNames;
}
+ return new String[0];
+ }
+ public String getValueProfile(int valveId, int profileId) {
+ int id = profileId;
+ if (id <= 0 && settings.thermostats != null) {
+ id = settings.thermostats.get(0).profile;
+ }
return "" + id;
}
/**
* Shelly Dimmer returns light[]. However, the structure doesn't match the lights[] of a Bulb/RGBW2.
- * The tag lights[] will be replaced with dimmers[] so this could be mapped to a different Gson structure.
+ * The tag lights[] will be replaced with dimmers[] so this could be mapped to a different Gson structure.
* The function requires that it's only called when the device is a dimmer - on get settings and get status
*
* @param json Input Json as received by the API
// Due to the fact that the device reports only the current/last status, but no real events, we need to distinguish
// between a real update or just a repeated status on periodic updates
- protected int lastCfgCount = -1;
protected int[] lastEventCount = { -1, -1, -1, -1, -1, -1, -1, -1 }; // 4Pro has 4 relays, so 8 should be fine
protected String[] inputEvent = { "", "", "", "", "", "", "", "" };
protected String lastWakeup = "";
@NonNullByDefault
public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly1CoIoTInterface {
private final Logger logger = LoggerFactory.getLogger(Shelly1CoIoTVersion2.class);
+ private int lastCfgCount = -1;
public Shelly1CoIoTVersion2(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
Map<String, CoIotDescrSen> sensorMap) {
case "3117": // S, mode, 0-5 (0=disabled)
value = getDouble(s.value).intValue();
updateChannel(updates, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_PROFILE,
- getStringType(profile.getValueProfile((int) value)));
+ getStringType(profile.getValueProfile(0, (int) value)));
updateChannel(updates, CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SCHEDULE, getOnOff(value > 0));
break;
case "3118": // Valve state
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
-import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapHandler;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.discovery.ShellyThingCreator;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions;
+import org.openhab.binding.shelly.internal.provider.ShellyStateDescriptionProvider;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
import org.openhab.binding.shelly.internal.util.ShellyChannelCache;
import org.openhab.binding.shelly.internal.util.ShellyVersionDTO;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.thing.binding.builder.ThingBuilder;
+import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
+import org.openhab.core.types.StateOption;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@NonNullByDefault
public class ShellyBaseHandler extends BaseThingHandler
implements ShellyDeviceListener, ShellyManagerInterface, ShellyThingInterface {
+ private class OptionEntry {
+ public ChannelTypeUID uid;
+ public String key;
+ public String value;
+
+ public OptionEntry(ChannelTypeUID uid, String key, String value) {
+ this.uid = uid;
+ this.key = key;
+ this.value = value;
+ }
+ }
+
protected final Logger logger = LoggerFactory.getLogger(ShellyBaseHandler.class);
protected final ShellyChannelDefinitions channelDefinitions;
+ private final CopyOnWriteArrayList<OptionEntry> stateOptions = new CopyOnWriteArrayList<>();
public String thingName = "";
public String thingType = "";
private final int cacheCount = UPDATE_SETTINGS_INTERVAL_SECONDS / UPDATE_STATUS_INTERVAL_SECONDS;
private final ShellyChannelCache cache;
- private String localIP = "";
- private String localPort = "";
-
private String lastWakeupReason = "";
private int vibrationFilter = 0;
* @param httpPort from httpService
*/
public ShellyBaseHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
- final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
- int httpPort, final HttpClient httpClient) {
+ final ShellyBindingConfiguration bindingConfig, ShellyThingTable thingTable,
+ final Shelly1CoapServer coapServer, final HttpClient httpClient) {
super(thing);
this.thingName = getString(thing.getLabel());
this.config = getConfigAs(ShellyThingConfiguration.class);
this.httpClient = httpClient;
- this.localIP = localIP;
- this.localPort = String.valueOf(httpPort);
this.api = new Shelly1HttpApi(thingName, config, httpClient);
coap = new Shelly1CoapHandler(this, coapServer);
|| key.equalsIgnoreCase(config.serviceName) || key.equalsIgnoreCase(thing.getUID().getAsString());
}
+ @Override
+ public Collection<Class<? extends ThingHandlerService>> getServices() {
+ return Set.of(ShellyStateDescriptionProvider.class);
+ }
+
public String getUID() {
return getThing().getUID().getAsString();
}
public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
super.handleConfigurationUpdate(configurationParameters);
logger.debug("{}: Thing config updated, re-initialize", thingName);
- coap.stop();
+ if (coap != null) {
+ coap.stop();
+ }
requestUpdates(1, true);// force re-initialization
}
stopping = false;
refreshSettings = false;
lastWakeupReason = "";
- profile.initFromThingType(thingType);
- api.setConfig(thingName, config);
cache.setThingName(thingName);
cache.clear();
config.serviceName = getString(profile.hostname).toLowerCase();
}
+ api.setConfig(thingName, config);
+ api.initialize();
ShellyDeviceProfile tmpPrf = api.getDeviceProfile(thingType);
if (this.getThing().getThingTypeUID().equals(THING_TYPE_SHELLYPROTECTED)) {
changeThingType(thingName, tmpPrf.mode);
tmpPrf.status = api.getStatus();
tmpPrf.updateFromStatus(tmpPrf.status);
+ if (tmpPrf.isTRV) {
+ String[] profileNames = tmpPrf.getValveProfileList(0);
+ String channelId = mkChannelId(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_PROFILE);
+ logger.debug("{}: Adding TRV profile names to channel description: {}", thingName, profileNames);
+ clearStateOptions(channelId);
+ addStateOption(channelId, "0", "DISABLED");
+ for (int i = 0; i < profileNames.length; i++) {
+ addStateOption(channelId, "" + (i + 1), profileNames[i]);
+ }
+ }
+
showThingConfig(tmpPrf);
- // update thing properties
checkVersion(tmpPrf, tmpPrf.status);
if (config.eventsCoIoT && (tmpPrf.settings.coiot != null) && (tmpPrf.settings.coiot.enabled != null)) {
break;
case CHANNEL_CONTROL_PROFILE:
logger.debug("{}: Select profile {}", thingName, command);
- int id = -1;
- if (command instanceof Number) {
- id = (int) getNumber(command);
- } else {
- String cmd = command.toString();
- if (isDigit(cmd.charAt(0))) {
- id = Integer.parseInt(cmd);
- } else if (cmd.equalsIgnoreCase("DISABLED")) {
- id = 0;
- } else if (profile.settings.thermostats != null) {
- ShellyThermnostat t = profile.settings.thermostats.get(0);
- for (int i = 0; i < t.profileNames.length; i++) {
- if (t.profileNames[i].equalsIgnoreCase(cmd)) {
- id = i + 1;
- }
- }
- }
- }
+ String cmd = command.toString();
+ int id = Integer.parseInt(cmd);
if (id < 0 || id > 5) {
logger.warn("{}: Invalid profile Id {} requested", thingName, profile);
} else {
restartWatchdog();
if (update && !autoCoIoT && !isUpdateScheduled()) {
- logger.debug("{}: Command processed, request status update", thingName);
requestUpdates(1, false);
}
} catch (ShellyApiException e) {
initializeThing(); // may fire an exception if initialization failed
}
// Get profile, if refreshSettings == true reload settings from device
- logger.trace("{}: Updating status (scheduledUpdates={}, refreshSettings={})", thingName,
- scheduledUpdates, refreshSettings);
ShellySettingsStatus status = api.getStatus();
boolean restarted = checkRestarted(status);
profile = getProfile(refreshSettings || restarted);
}
}
+ @Override
+ public ThingStatus getThingStatus() {
+ return getThing().getStatus();
+ }
+
+ @Override
+ public ThingStatusDetail getThingStatusDetail() {
+ return getThing().getStatusInfo().getStatusDetail();
+ }
+
+ @Override
public boolean isThingOnline() {
return getThing().getStatus() == ThingStatus.ONLINE;
}
if (status.uptime != null) {
stats.lastUptime = getLong(status.uptime);
}
- stats.coiotMessages = coap.getMessageCount();
- stats.coiotErrors = coap.getErrorCount();
-
+ if (coap != null) {
+ stats.coiotMessages = coap.getMessageCount();
+ stats.coiotErrors = coap.getErrorCount();
+ }
if (!alarm.isEmpty()) {
postEvent(alarm, false);
}
InetAddress addr = InetAddress.getByName(config.deviceIp);
String saddr = addr.getHostAddress();
if (!config.deviceIp.equals(saddr)) {
- logger.debug("{}: hostname {} resolved to IP address {}", thingName, config.deviceIp, saddr);
+ logger.debug("{}: hostname {} resolved to IP address {}", thingName, config.deviceIp, saddr);
config.deviceIp = saddr;
}
} catch (UnknownHostException e) {
}
config.serviceName = getString(properties.get(PROPERTY_SERVICE_NAME));
- config.localIp = localIP;
- config.localPort = localPort;
+ config.localIp = bindingConfig.localIP;
+ config.localPort = String.valueOf(bindingConfig.httpPort);
if (config.userId.isEmpty() && !bindingConfig.defaultUserId.isEmpty()) {
config.userId = bindingConfig.defaultUserId;
config.password = bindingConfig.defaultPassword;
* @param profile The device profile
* @param status the /status result
*/
- protected void updateProperties(ShellyDeviceProfile profile, ShellySettingsStatus status) {
- logger.debug("{}: Update properties", thingName);
+ public void updateProperties(ShellyDeviceProfile profile, ShellySettingsStatus status) {
Map<String, Object> properties = fillDeviceProperties(profile);
String deviceName = getString(profile.settings.name);
properties.put(PROPERTY_SERVICE_NAME, config.serviceName);
return profile;
}
+ @Override
+ public List<StateOption> getStateOptions(ChannelTypeUID uid) {
+ List<StateOption> options = new ArrayList<>();
+ for (OptionEntry oe : stateOptions) {
+ if (oe.uid.equals(uid)) {
+ options.add(new StateOption(oe.key, oe.value));
+ }
+ }
+
+ if (!options.isEmpty()) {
+ logger.debug("{}: Return {} state options for channel uid {}", thingName, options.size(), uid.getId());
+ }
+ return options;
+ }
+
+ private void addStateOption(String channelId, String key, String value) {
+ ChannelTypeUID uid = channelDefinitions.getChannelTypeUID(channelId);
+ stateOptions.addIfAbsent(new OptionEntry(uid, key, value));
+ }
+
+ private void clearStateOptions(String channelId) {
+ ChannelTypeUID uid = channelDefinitions.getChannelTypeUID(channelId);
+ for (OptionEntry oe : stateOptions) {
+ if (oe.uid.equals(uid)) {
+ stateOptions.remove(oe);
+ }
+ }
+ }
+
protected ShellyDeviceProfile getDeviceProfile() {
return profile;
}
logger.debug("{}: Duplicate vibration events will be absorbed for the next {} sec", thingName,
vibrationFilter * UPDATE_STATUS_INTERVAL_SECONDS);
} else {
- logger.debug("{}: Vibration event absorbed, {} sec remaining", thingName,
+ logger.debug("{}: Vibration event absorbed, {} sec remaining", thingName,
vibrationFilter * UPDATE_STATUS_INTERVAL_SECONDS);
return;
}
logger.debug("{}: Shelly statusJob stopped", thingName);
}
- coap.stop();
+ if (coap != null) {
+ coap.stop();
+ }
profile.initialized = false;
}
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_SCHEDULE,
getOnOff(t.schedule));
updated |= thingHandler.updateChannel(CHANNEL_GROUP_CONTROL, CHANNEL_CONTROL_PROFILE,
- getStringType(profile.getValueProfile(pid)));
+ 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,
* @param httpPort port of the openHAB HTTP API
*/
public ShellyLightHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
- final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
- int httpPort, final HttpClient httpClient) {
- super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
+ final ShellyBindingConfiguration bindingConfig, final ShellyThingTable thingTable,
+ final Shelly1CoapServer coapServer, final HttpClient httpClient) {
+ super(thing, translationProvider, bindingConfig, thingTable, coapServer, httpClient);
channelColors = new TreeMap<>();
}
* @param httpPort port of the openHAB HTTP API
*/
public ShellyProtectedHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
- final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
- int httpPort, final HttpClient httpClient) {
- super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
+ final ShellyBindingConfiguration bindingConfig, ShellyThingTable thingTable,
+ final Shelly1CoapServer coapService, final HttpClient httpClient) {
+ super(thing, translationProvider, bindingConfig, thingTable, coapService, httpClient);
}
@Override
* @param httpPort port of the openHAB HTTP API
*/
public ShellyRelayHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
- final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
- int httpPort, final HttpClient httpClient) {
- super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
+ final ShellyBindingConfiguration bindingConfig, ShellyThingTable thingTable,
+ final Shelly1CoapServer coapServer, final HttpClient httpClient) {
+ super(thing, translationProvider, bindingConfig, thingTable, coapServer, httpClient);
}
@Override
*/
public boolean updateRelays(ShellySettingsStatus status) throws ShellyApiException {
boolean updated = false;
- // Check for Relay in Standard Mode
+
if (profile.hasRelays && !profile.isDimmer) {
double voltage = -1;
if (status.voltage == null && profile.settings.supplyVoltage != null) {
ShellySettingsStatus dstatus = fromJson(gson, Shelly1ApiJsonDTO.fixDimmerJson(orgStatus.json),
ShellySettingsStatus.class);
- logger.trace("{}: Updating {} dimmers(s)", thingName, dstatus.dimmers.size());
+ logger.trace("{}: Updating {} dimmers(s)", thingName, dstatus.dimmers.size());
int l = 0;
for (ShellyShortLightStatus dimmer : dstatus.dimmers) {
Integer r = l + 1;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.State;
+import org.openhab.core.types.StateOption;
/**
* The {@link ShellyThingInterface} implements the interface for Shelly Manager to access the thing handler
public ShellyDeviceProfile getProfile(boolean forceRefresh) throws ShellyApiException;
+ public List<StateOption> getStateOptions(ChannelTypeUID uid);
+
public double getChannelDouble(String group, String channel);
public boolean updateChannel(String group, String channel, State value);
public void setThingOffline(ThingStatusDetail detail, String messageKey);
+ public ThingStatus getThingStatus();
+
+ public ThingStatusDetail getThingStatusDetail();
+
+ public boolean isThingOnline();
+
public boolean requestUpdates(int requestCount, boolean refreshSettings);
public void triggerUpdateFromCoap();
return newChannels;
}
+ public ChannelTypeUID getChannelTypeUID(String channelId) {
+ ShellyChannel channelDef = getDefinition(channelId);
+ return new ChannelTypeUID(BINDING_ID, channelDef.typeId);
+ }
+
private static void addChannel(Thing thing, Map<String, Channel> newChannels, boolean supported, String group,
String channelName) throws IllegalArgumentException {
if (supported) {
--- /dev/null
+/**
+ * Copyright (c) 2010-2022 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+
+package org.openhab.binding.shelly.internal.provider;
+
+import java.util.Locale;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerService;
+import org.openhab.core.thing.type.ChannelTypeUID;
+import org.openhab.core.types.StateDescription;
+
+/**
+ * This class provides the list of valid inputs for the input channel of a source.
+ *
+ * @author Markus Michels - Initial contribution
+ *
+ */
+@NonNullByDefault
+public class ShellyStateDescriptionProvider extends BaseDynamicStateDescriptionProvider implements ThingHandlerService {
+ private @Nullable ShellyThingInterface handler;
+
+ @Override
+ public void setThingHandler(ThingHandler handler) {
+ this.handler = (ShellyThingInterface) handler;
+ }
+
+ @Override
+ public @Nullable ThingHandler getThingHandler() {
+ return (ThingHandler) handler;
+ }
+
+ @SuppressWarnings("null")
+ @Override
+ public @Nullable StateDescription getStateDescription(Channel channel, @Nullable StateDescription original,
+ @Nullable Locale locale) {
+ ChannelTypeUID uid = channel.getChannelTypeUID();
+ if (uid != null && handler != null) {
+ setStateOptions(channel.getUID(), handler.getStateOptions(uid));
+ }
+ return super.getStateDescription(channel, original, locale);
+ }
+}
if (classOfT.isInstance(json)) {
return wrap(classOfT).cast(json);
} else if (json.isEmpty()) { // update GSON might return null
- throw new ShellyApiException(PRE + className + "from empty JSON");
+ throw new ShellyApiException(PRE + className + " from empty JSON");
} else {
try {
@Nullable
return obj;
} catch (JsonSyntaxException e) {
throw new ShellyApiException(
- PRE + className + "from JSON (syntax/format error: " + e.getMessage() + "): " + json, e);
+ PRE + className + " from JSON (syntax/format error: " + e.getMessage() + "): " + json, e);
} catch (RuntimeException e) {
throw new ShellyApiException(PRE + className + " from JSON: " + json, e);
}
channel-type.shelly.controlMode.description = Sensor/Control Mode
channel-type.shelly.controlMode.state.option.manual = Manual
channel-type.shelly.controlMode.state.option.automatic = Automatic
-channel-type.shelly.controlSchedule.label = Schedule active
-channel-type.shelly.controlSchedule.description = ON: A scheduled program is active
channel-type.shelly.controlProfile.label = Selected Profile
-channel-type.shelly.controlProfile.description = Selected Profile configured in the Shelly App
+channel-type.shelly.controlProfile.description = Id of the selected Profile configured in the Shelly App
+channel-type.shelly.controlSchedule.label = Schedule Active
+channel-type.shelly.controlSchedule.description = ON: A scheduled program is active
channel-type.shelly.boostControl.label = Boost Mode
channel-type.shelly.boostControl.description = ON: Boost mode is activated (overwrites automatic temperature mode)
channel-type.shelly.boostTimer.label = Boost Timer