mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[shelly] Improved TRV profile handling (selectable list via dynamic state options (#13227)
provider); some improvements & fixes Signed-off-by: Markus Michels <markus7017@gmail.com>
This commit is contained in:
parent
6c78fb3161
commit
5b038786d5
@ -27,7 +27,7 @@ Also check out the [Shelly Manager](doc/ShellyManager.md), which
|
||||
|
||||
## Supported Devices
|
||||
|
||||
### Generation 1:
|
||||
### Generation 1
|
||||
|
||||
| thing-type | Model | Vendor ID |
|
||||
|--------------------|--------------------------------------------------------|-----------|
|
||||
|
@ -138,10 +138,10 @@ public class ShellyBindingConstants {
|
||||
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";
|
||||
|
@ -65,8 +65,6 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
|
||||
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
|
||||
@ -85,7 +83,7 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
|
||||
this.thingTable = thingTable;
|
||||
|
||||
bindingConfig.updateFromProperties(configProperties);
|
||||
localIP = bindingConfig.localIP;
|
||||
String localIP = bindingConfig.localIP;
|
||||
if (localIP.isEmpty()) {
|
||||
localIP = ShellyUtils.getString(networkAddressService.getPrimaryIpv4HostAddress());
|
||||
}
|
||||
@ -94,11 +92,13 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@ -117,8 +117,7 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
|
||||
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)
|
||||
@ -126,11 +125,11 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
|
||||
|| 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) {
|
||||
|
@ -330,17 +330,19 @@ public class ShellyDeviceProfile {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1143,7 +1143,7 @@ public class Shelly1ApiJsonDTO {
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -58,7 +58,6 @@ public class Shelly1CoIoTProtocol {
|
||||
|
||||
// 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 = "";
|
||||
|
@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
|
||||
@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) {
|
||||
@ -107,7 +108,7 @@ public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly
|
||||
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
|
||||
|
@ -21,9 +21,13 @@ import static org.openhab.core.thing.Thing.*;
|
||||
|
||||
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;
|
||||
|
||||
@ -39,7 +43,6 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputSta
|
||||
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;
|
||||
@ -48,6 +51,7 @@ import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
|
||||
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;
|
||||
@ -62,10 +66,13 @@ import org.openhab.core.thing.ThingStatus;
|
||||
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;
|
||||
@ -79,8 +86,21 @@ 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 = "";
|
||||
@ -111,9 +131,6 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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;
|
||||
|
||||
@ -128,8 +145,8 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
* @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());
|
||||
@ -140,8 +157,6 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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);
|
||||
@ -153,6 +168,11 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
|| 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();
|
||||
}
|
||||
@ -213,7 +233,9 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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
|
||||
}
|
||||
|
||||
@ -231,8 +253,6 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
stopping = false;
|
||||
refreshSettings = false;
|
||||
lastWakeupReason = "";
|
||||
profile.initFromThingType(thingType);
|
||||
api.setConfig(thingName, config);
|
||||
cache.setThingName(thingName);
|
||||
cache.clear();
|
||||
|
||||
@ -260,6 +280,8 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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);
|
||||
@ -293,8 +315,18 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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)) {
|
||||
@ -411,24 +443,8 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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 {
|
||||
@ -463,7 +479,6 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
|
||||
restartWatchdog();
|
||||
if (update && !autoCoIoT && !isUpdateScheduled()) {
|
||||
logger.debug("{}: Command processed, request status update", thingName);
|
||||
requestUpdates(1, false);
|
||||
}
|
||||
} catch (ShellyApiException e) {
|
||||
@ -517,8 +532,6 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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);
|
||||
@ -590,6 +603,17 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingStatus getThingStatus() {
|
||||
return getThing().getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingStatusDetail getThingStatusDetail() {
|
||||
return getThing().getStatusInfo().getStatusDetail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isThingOnline() {
|
||||
return getThing().getStatus() == ThingStatus.ONLINE;
|
||||
}
|
||||
@ -699,9 +723,10 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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);
|
||||
}
|
||||
@ -911,7 +936,7 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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) {
|
||||
@ -919,8 +944,8 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1221,8 +1246,7 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
* @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);
|
||||
@ -1347,6 +1371,35 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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;
|
||||
}
|
||||
@ -1361,7 +1414,7 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
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;
|
||||
}
|
||||
@ -1379,7 +1432,9 @@ public class ShellyBaseHandler extends BaseThingHandler
|
||||
logger.debug("{}: Shelly statusJob stopped", thingName);
|
||||
}
|
||||
|
||||
coap.stop();
|
||||
if (coap != null) {
|
||||
coap.stop();
|
||||
}
|
||||
profile.initialized = false;
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ public class ShellyComponents {
|
||||
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,
|
||||
|
@ -66,9 +66,9 @@ public class ShellyLightHandler extends ShellyBaseHandler {
|
||||
* @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<>();
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,9 @@ public class ShellyProtectedHandler extends ShellyBaseHandler {
|
||||
* @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
|
||||
|
@ -64,9 +64,9 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
|
||||
* @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
|
||||
@ -329,7 +329,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
|
||||
*/
|
||||
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) {
|
||||
@ -384,7 +384,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
|
||||
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;
|
||||
|
@ -25,8 +25,11 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettings
|
||||
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
|
||||
@ -38,6 +41,8 @@ public interface ShellyThingInterface {
|
||||
|
||||
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);
|
||||
@ -48,6 +53,12 @@ public interface ShellyThingInterface {
|
||||
|
||||
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();
|
||||
|
@ -514,6 +514,11 @@ public class ShellyChannelDefinitions {
|
||||
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) {
|
||||
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -81,7 +81,7 @@ public class ShellyUtils {
|
||||
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
|
||||
@ -92,7 +92,7 @@ public class ShellyUtils {
|
||||
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);
|
||||
}
|
||||
|
@ -388,10 +388,10 @@ channel-type.shelly.controlMode.label = Mode
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user