[nikobus] fixed refresh handling (#9114)
* * fixed refresh handing due `channelLinked` not called anymore on startup for example (similar to https://github.com/openhab/openhab-core/issues/1707), * "Impacted Modules" can be empty if button is configured as "standalone" and does not impact modules, * minor doc fix * * check if configured impacted module for `impactedModules` is referencing an existing thing, * fixed warnings * Fixed review comment. Signed-off-by: Boris Krivonog <boris.krivonog@inova.si>pull/9134/head
parent
fde30fbada
commit
8743f0ee7a
|
@ -14,11 +14,9 @@ package org.openhab.binding.nikobus.internal.handler;
|
|||
|
||||
import static org.openhab.binding.nikobus.internal.NikobusBindingConstants.CHANNEL_OUTPUT_PREFIX;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -26,6 +24,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
|||
import org.openhab.binding.nikobus.internal.protocol.NikobusCommand;
|
||||
import org.openhab.binding.nikobus.internal.protocol.SwitchModuleCommandFactory;
|
||||
import org.openhab.binding.nikobus.internal.protocol.SwitchModuleGroup;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
|
@ -46,12 +45,21 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler {
|
|||
private final EnumSet<SwitchModuleGroup> pendingRefresh = EnumSet.noneOf(SwitchModuleGroup.class);
|
||||
private final Logger logger = LoggerFactory.getLogger(NikobusModuleHandler.class);
|
||||
private final Map<String, Integer> cachedStates = new HashMap<>();
|
||||
private final List<ChannelUID> linkedChannels = new ArrayList<>();
|
||||
|
||||
protected NikobusModuleHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
if (thing.getStatus() != ThingStatus.OFFLINE) {
|
||||
// Fetch all linked channels to get initial values.
|
||||
thing.getChannels().forEach(channel -> refreshChannel(channel.getUID()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
@ -67,6 +75,8 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand '{}' for channel '{}'", command, channelUID.getId());
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
refreshChannel(channelUID);
|
||||
} else {
|
||||
|
@ -85,26 +95,11 @@ abstract class NikobusModuleHandler extends NikobusBaseThingHandler {
|
|||
updateGroup(SwitchModuleGroup.mapFromChannel(channelUID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
synchronized (linkedChannels) {
|
||||
linkedChannels.add(channelUID);
|
||||
}
|
||||
super.channelLinked(channelUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelUnlinked(ChannelUID channelUID) {
|
||||
synchronized (linkedChannels) {
|
||||
linkedChannels.remove(channelUID);
|
||||
}
|
||||
super.channelUnlinked(channelUID);
|
||||
}
|
||||
|
||||
public void refreshModule() {
|
||||
Set<SwitchModuleGroup> groups = new HashSet<>();
|
||||
synchronized (linkedChannels) {
|
||||
for (ChannelUID channelUID : linkedChannels) {
|
||||
for (Channel channel : thing.getChannels()) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
if (isLinked(channelUID)) {
|
||||
groups.add(SwitchModuleGroup.mapFromChannel(channelUID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,27 +118,41 @@ public class NikobusPushButtonHandler extends NikobusBaseThingHandler {
|
|||
|
||||
impactedModules.clear();
|
||||
|
||||
try {
|
||||
ThingUID bridgeUID = thing.getBridgeUID();
|
||||
if (bridgeUID == null) {
|
||||
throw new IllegalArgumentException("Bridge does not exist!");
|
||||
Object impactedModulesObject = getConfig().get(CONFIG_IMPACTED_MODULES);
|
||||
if (impactedModulesObject != null) {
|
||||
try {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
throw new IllegalArgumentException("Bridge does not exist!");
|
||||
}
|
||||
|
||||
ThingUID bridgeUID = thing.getBridgeUID();
|
||||
if (bridgeUID == null) {
|
||||
throw new IllegalArgumentException("Unable to read BridgeUID!");
|
||||
}
|
||||
|
||||
String[] impactedModulesString = impactedModulesObject.toString().split(",");
|
||||
for (String impactedModuleString : impactedModulesString) {
|
||||
ImpactedModuleUID impactedModuleUID = new ImpactedModuleUID(impactedModuleString.trim());
|
||||
ThingTypeUID thingTypeUID = new ThingTypeUID(bridgeUID.getBindingId(),
|
||||
impactedModuleUID.getThingTypeId());
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, impactedModuleUID.getThingId());
|
||||
|
||||
if (!bridge.getThings().stream().anyMatch(thing -> thing.getUID().equals(thingUID))) {
|
||||
throw new IllegalArgumentException(
|
||||
"Impacted module " + thingUID + " not found for '" + impactedModuleString + "'");
|
||||
}
|
||||
|
||||
impactedModules.add(new ImpactedModule(thingUID, impactedModuleUID.getGroup()));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
String[] impactedModulesString = getConfig().get(CONFIG_IMPACTED_MODULES).toString().split(",");
|
||||
for (String impactedModuleString : impactedModulesString) {
|
||||
ImpactedModuleUID impactedModuleUID = new ImpactedModuleUID(impactedModuleString.trim());
|
||||
ThingTypeUID thingTypeUID = new ThingTypeUID(bridgeUID.getBindingId(),
|
||||
impactedModuleUID.getThingTypeId());
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, impactedModuleUID.getThingId());
|
||||
impactedModules.add(new ImpactedModule(thingUID, impactedModuleUID.getGroup()));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
|
||||
return;
|
||||
logger.debug("Impacted modules for {} = {}", thing.getUID(), impactedModules);
|
||||
}
|
||||
|
||||
logger.debug("Impacted modules for {} = {}", thing.getUID(), impactedModules);
|
||||
|
||||
NikobusPcLinkHandler pcLink = getPcLink();
|
||||
if (pcLink != null) {
|
||||
pcLink.addListener(getAddress(), this::commandReceived);
|
||||
|
@ -183,8 +197,10 @@ public class NikobusPushButtonHandler extends NikobusBaseThingHandler {
|
|||
|
||||
updateState(CHANNEL_BUTTON, OnOffType.ON);
|
||||
|
||||
Utils.cancel(requestUpdateFuture);
|
||||
requestUpdateFuture = scheduler.schedule(this::update, 400, TimeUnit.MILLISECONDS);
|
||||
if (!impactedModules.isEmpty()) {
|
||||
Utils.cancel(requestUpdateFuture);
|
||||
requestUpdateFuture = scheduler.schedule(this::update, 400, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void update() {
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
*/
|
||||
package org.openhab.binding.nikobus.internal.utils;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
|
||||
/**
|
||||
|
@ -21,6 +22,7 @@ import org.openhab.core.util.HexUtils;
|
|||
* @author Davy Vanherbergen - Initial contribution
|
||||
* @author Boris Krivonog - Removed dependency to javax.xml.bind.DatatypeConverter
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CRCUtil {
|
||||
|
||||
private static final int CRC_INIT = 0xFFFF;
|
||||
|
@ -35,7 +37,7 @@ public class CRCUtil {
|
|||
* String representing hex numbers.
|
||||
* @return input string + CRC.
|
||||
*/
|
||||
public static String appendCRC(String input) {
|
||||
public static @Nullable String appendCRC(@Nullable String input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -54,7 +56,7 @@ public class CRCUtil {
|
|||
}
|
||||
|
||||
check = check & CRC_INIT;
|
||||
String checksum = StringUtils.leftPad(Integer.toHexString(check), 4, "0");
|
||||
String checksum = leftPadWithZeros(Integer.toHexString(check), 4);
|
||||
return (input + checksum).toUpperCase();
|
||||
}
|
||||
|
||||
|
@ -85,6 +87,14 @@ public class CRCUtil {
|
|||
}
|
||||
}
|
||||
|
||||
return input + StringUtils.leftPad(Integer.toHexString(check), 2, "0").toUpperCase();
|
||||
return input + leftPadWithZeros(Integer.toHexString(check), 2).toUpperCase();
|
||||
}
|
||||
|
||||
private static String leftPadWithZeros(String text, int size) {
|
||||
StringBuilder builder = new StringBuilder(text);
|
||||
while (builder.length() < size) {
|
||||
builder.insert(0, '0');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,17 @@ package org.openhab.binding.nikobus.internal.utils;
|
|||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link Utils} class defines commonly used utility functions.
|
||||
*
|
||||
* @author Boris Krivonog - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Utils {
|
||||
public static void cancel(Future<?> future) {
|
||||
public static void cancel(@Nullable Future<?> future) {
|
||||
if (future != null) {
|
||||
future.cancel(true);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</parameter>
|
||||
<parameter name="impactedModules" type="text">
|
||||
<label>Impacted Modules</label>
|
||||
<description>Comma separated list of impacted modules, i.e. 4C6C-1,4C6C-2</description>
|
||||
<description>Comma separated list of impacted modules, i.e. switch-module:s1:1</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
|
Loading…
Reference in New Issue