[hdpowerview] Channels are visible depending on shade capabilities (#13275)

* [hdpowerview] create channels dynamically
* [hdpowerview] revert from channel creation to channel removal
* [hdpowerview] add category

Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This commit is contained in:
Andrew Fiddian-Green
2022-08-23 21:03:43 +01:00
committed by GitHub
parent bc9cf8e07a
commit 0a41c3f2f6
3 changed files with 66 additions and 19 deletions

View File

@@ -15,6 +15,7 @@ package org.openhab.binding.hdpowerview.internal.handler;
import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*;
import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -50,6 +51,7 @@ import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
@@ -80,10 +82,10 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
private static final String DETECTED_SECONDARY_RAIL = "secondaryRailDetected";
private static final String DETECTED_TILT_ANYWHERE = "tiltAnywhereDetected";
private final Map<String, String> detectedCapabilities = new HashMap<>();
private static final ShadeCapabilitiesDatabase DB = new ShadeCapabilitiesDatabase();
private final Map<String, String> detectedCapabilities = new HashMap<>();
private final Logger logger = LoggerFactory.getLogger(HDPowerViewShadeHandler.class);
private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
private @Nullable ScheduledFuture<?> refreshPositionFuture = null;
private @Nullable ScheduledFuture<?> refreshSignalFuture = null;
@@ -107,7 +109,6 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
"@text/offline.conf-error.invalid-bridge-handler");
return;
}
updateStatus(ThingStatus.UNKNOWN);
}
@@ -265,13 +266,15 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
// Already cached.
return;
}
Capabilities capabilities = db.getCapabilities(shade.type, shade.capabilities);
Capabilities capabilities = DB.getCapabilities(shade.type, shade.capabilities);
if (capabilities.getValue() < 0) {
logger.debug("Unable to set capabilities for shade {}", shade.id);
return;
}
logger.debug("Caching capabilities {} for shade {}", capabilities.getValue(), shade.id);
this.capabilities = capabilities;
updateDynamicChannels(capabilities);
}
private Capabilities getCapabilitiesOrDefault() {
@@ -298,17 +301,17 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
final int type = shadeData.type;
String propKey = HDPowerViewBindingConstants.PROPERTY_SHADE_TYPE;
String propOldVal = properties.getOrDefault(propKey, "");
String propNewVal = db.getType(type).toString();
String propNewVal = DB.getType(type).toString();
if (!propNewVal.equals(propOldVal)) {
propChanged = true;
getThing().setProperty(propKey, propNewVal);
if ((type > 0) && !db.isTypeInDatabase(type)) {
db.logTypeNotInDatabase(type);
if ((type > 0) && !DB.isTypeInDatabase(type)) {
DB.logTypeNotInDatabase(type);
}
}
// update 'capabilities' property
Capabilities capabilities = db.getCapabilities(shadeData.capabilities);
Capabilities capabilities = DB.getCapabilities(shadeData.capabilities);
final int capabilitiesVal = capabilities.getValue();
propKey = HDPowerViewBindingConstants.PROPERTY_SHADE_CAPABILITIES;
propOldVal = properties.getOrDefault(propKey, "");
@@ -316,14 +319,14 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
if (!propNewVal.equals(propOldVal)) {
propChanged = true;
getThing().setProperty(propKey, propNewVal);
if ((capabilitiesVal >= 0) && !db.isCapabilitiesInDatabase(capabilitiesVal)) {
db.logCapabilitiesNotInDatabase(type, capabilitiesVal);
if ((capabilitiesVal >= 0) && !DB.isCapabilitiesInDatabase(capabilitiesVal)) {
DB.logCapabilitiesNotInDatabase(type, capabilitiesVal);
}
}
if (propChanged && db.isCapabilitiesInDatabase(capabilitiesVal) && db.isTypeInDatabase(type)
&& (capabilitiesVal != db.getType(type).getCapabilities()) && (shadeData.capabilities != null)) {
db.logCapabilitiesMismatch(type, capabilitiesVal);
if (propChanged && DB.isCapabilitiesInDatabase(capabilitiesVal) && DB.isTypeInDatabase(type)
&& (capabilitiesVal != DB.getType(type).getCapabilities()) && (shadeData.capabilities != null)) {
DB.logCapabilitiesMismatch(type, capabilitiesVal);
}
}
@@ -364,7 +367,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
if (!capsNewVal.equals(capsOldVal)) {
detectedCapabilities.put(capsKey, capsNewVal);
if (capsNewBool != capabilities.supportsSecondary()) {
db.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool);
DB.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool);
}
}
@@ -376,7 +379,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
if (!capsNewVal.equals(capsOldVal)) {
detectedCapabilities.put(capsKey, capsNewVal);
if (capsNewBool != capabilities.supportsTiltAnywhere()) {
db.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool);
DB.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool);
}
}
}
@@ -596,4 +599,45 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
}
}
}
/**
* If the given channel exists in the thing, but is NOT required in the thing, then add it to a list of channels to
* be removed. Or if the channel does NOT exist in the thing, but is required in the thing, then log a warning.
*
* @param removeList the list of channels to be removed from the thing.
* @param channelId the id of the channel to be (eventually) removed.
* @param channelRequired true if the thing requires this channel.
*/
private void removeListProcessChannel(List<Channel> removeList, String channelId, boolean channelRequired) {
Channel channel = thing.getChannel(channelId);
if (!channelRequired && channel != null) {
removeList.add(channel);
} else if (channelRequired && channel == null) {
logger.warn("Shade {} does not have a '{}' channel => please reinitialize the thing", shadeId, channelId);
}
}
/**
* Remove previously statically created channels if the shade does not support them.
*/
private void updateDynamicChannels(Capabilities capabilities) {
List<Channel> removeList = new ArrayList<>();
removeListProcessChannel(removeList, CHANNEL_SHADE_POSITION, capabilities.supportsPrimary());
removeListProcessChannel(removeList, CHANNEL_SHADE_SECONDARY_POSITION,
capabilities.supportsSecondary() || capabilities.supportsSecondaryOverlapped());
removeListProcessChannel(removeList, CHANNEL_SHADE_VANE,
capabilities.supportsTiltAnywhere() || capabilities.supportsTiltOnClosed());
if (!removeList.isEmpty()) {
if (logger.isDebugEnabled()) {
StringJoiner joiner = new StringJoiner(", ");
removeList.forEach(c -> joiner.add(c.getUID().getId()));
logger.debug("Removing unsupported channels for {}: {}", shadeId, joiner.toString());
}
updateThing(editThing().withoutChannels(removeList).build());
}
}
}

View File

@@ -8,6 +8,7 @@
<item-type>Rollershutter</item-type>
<label>Position</label>
<description>The vertical position of the shade</description>
<category>blinds</category>
</channel-type>
<channel-type id="shade-vane">