mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[knx] postUpdate for contact-control sends to bus (#16263)
contact-control items need to send to the bus like a switch item, to trigger a state update in the external device. * Add a new profile for contact-control items * Add a profile factory and a profile advisor class * Handle postUpdate like a command and send message on KNX bus Fixes #16115. Signed-off-by: Holger Friedrich <mail@holger-friedrich.de> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
23ac34fd80
commit
fbb3d099fd
@ -21,6 +21,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link KNXBindingConstants} class defines common constants, which are
|
||||
@ -89,6 +90,9 @@ public class KNXBindingConstants {
|
||||
public static final String CHANNEL_SWITCH = "switch";
|
||||
public static final String CHANNEL_SWITCH_CONTROL = "switch-control";
|
||||
|
||||
public static final ChannelTypeUID CHANNEL_CONTACT_CONTROL_UID = new ChannelTypeUID(BINDING_ID,
|
||||
CHANNEL_CONTACT_CONTROL);
|
||||
|
||||
public static final Set<String> CONTROL_CHANNEL_TYPES = Set.of( //
|
||||
CHANNEL_COLOR_CONTROL, //
|
||||
CHANNEL_CONTACT_CONTROL, //
|
||||
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.knx.internal.profiles;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
import org.openhab.core.thing.profiles.StateProfile;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is the implementation of a specialized profile for KNX contact-control-items.
|
||||
*
|
||||
* In contrast to the profile {@code FOLLOW} from {@link org.openhab.core.thing.profiles.SystemProfiles}
|
||||
* used for other *-control items, it sends to the bus also for contact items.
|
||||
*
|
||||
* @author Holger Friedrich - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class KNXContactControlProfile implements StateProfile {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(KNXContactControlProfile.class);
|
||||
private final ProfileCallback callback;
|
||||
private final ThingRegistry thingRegistry;
|
||||
|
||||
public KNXContactControlProfile(ProfileCallback callback, ThingRegistry thingRegistry) {
|
||||
this.callback = callback;
|
||||
this.thingRegistry = thingRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileTypeUID getProfileTypeUID() {
|
||||
return KNXProfileFactory.UID_CONTACT_CONTROL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateUpdateFromItem(State state) {
|
||||
ChannelUID linkedChannelUID = callback.getItemChannelLink().getLinkedUID();
|
||||
logger.trace("onStateUpdateFromItem({}) to {}", state.toString(), linkedChannelUID);
|
||||
|
||||
if (!(state instanceof Command)) {
|
||||
logger.debug("The given state {} could not be transformed to a command", state);
|
||||
return;
|
||||
}
|
||||
Command command = (Command) state;
|
||||
|
||||
// this does not have effect for contact items
|
||||
// callback.handleCommand(command);
|
||||
// workaround is to call handleCommand of the Thing directly
|
||||
@Nullable
|
||||
Thing linkedThing = thingRegistry.get(linkedChannelUID.getThingUID());
|
||||
if (linkedThing != null) {
|
||||
@Nullable
|
||||
ThingHandler linkedThingHandler = linkedThing.getHandler();
|
||||
if (linkedThingHandler != null) {
|
||||
linkedThingHandler.handleCommand(linkedChannelUID, command);
|
||||
} else {
|
||||
logger.warn("Failed to send to {}, no ThingHandler", linkedChannelUID);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Failed to send to {}, no linked Thing", linkedChannelUID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandFromHandler(Command command) {
|
||||
logger.trace("onCommandFromHandler {}", command.toString());
|
||||
callback.sendCommand(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandFromItem(Command command) {
|
||||
logger.trace("onCommandFromItem {}", command.toString());
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateUpdateFromHandler(State state) {
|
||||
logger.trace("onStateUpdateFromHandler {}", state.toString());
|
||||
// no-op
|
||||
}
|
||||
}
|
@ -50,6 +50,11 @@ public class KNXProfileAdvisor implements ProfileAdvisor {
|
||||
|
||||
private ProfileTypeUID getSuggestedProfileTypeUID(ChannelTypeUID channelTypeUID) {
|
||||
if (isControl(channelTypeUID)) {
|
||||
if (CHANNEL_CONTACT_CONTROL.equals(channelTypeUID.getId())) {
|
||||
// Special handling for contact-control, as contact items do not send to bus:
|
||||
// contact-control need to send out on postUpdate, as contact-control switches external device
|
||||
return KNXProfileFactory.UID_CONTACT_CONTROL;
|
||||
}
|
||||
return SystemProfiles.FOLLOW;
|
||||
} else {
|
||||
return SystemProfiles.DEFAULT;
|
||||
|
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.knx.internal.profiles;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.knx.internal.KNXBindingConstants;
|
||||
import org.openhab.core.library.CoreItemFactory;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.profiles.Profile;
|
||||
import org.openhab.core.thing.profiles.ProfileAdvisor;
|
||||
import org.openhab.core.thing.profiles.ProfileCallback;
|
||||
import org.openhab.core.thing.profiles.ProfileContext;
|
||||
import org.openhab.core.thing.profiles.ProfileFactory;
|
||||
import org.openhab.core.thing.profiles.ProfileType;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeProvider;
|
||||
import org.openhab.core.thing.profiles.ProfileTypeUID;
|
||||
import org.openhab.core.thing.profiles.StateProfileType;
|
||||
import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* This class defines and provides specialized KNX profiles.
|
||||
*
|
||||
* @author Holger Friedrich - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component
|
||||
public class KNXProfileFactory implements ProfileFactory, ProfileAdvisor, ProfileTypeProvider {
|
||||
|
||||
static final ProfileTypeUID UID_CONTACT_CONTROL = new ProfileTypeUID(KNXBindingConstants.BINDING_ID,
|
||||
"contact-control");
|
||||
|
||||
private static final StateProfileType CONTACT_CONTROL_TYPE = ProfileTypeBuilder
|
||||
.newState(UID_CONTACT_CONTROL, "contact-control").withSupportedItemTypes(CoreItemFactory.CONTACT)
|
||||
.withSupportedChannelTypeUIDs(KNXBindingConstants.CHANNEL_CONTACT_CONTROL_UID).build();
|
||||
|
||||
private final ThingRegistry thingRegistry;
|
||||
|
||||
@Activate
|
||||
public KNXProfileFactory(@Reference ThingRegistry thingRegistry) {
|
||||
this.thingRegistry = thingRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
|
||||
return Stream.of(UID_CONTACT_CONTROL).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
|
||||
return Stream.of(CONTACT_CONTROL_TYPE).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(Channel channel, @Nullable String itemType) {
|
||||
return getSuggestedProfileTypeUID(channel.getChannelTypeUID(), itemType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(ChannelType channelType, @Nullable String itemType) {
|
||||
return getSuggestedProfileTypeUID(channelType.getUID(), itemType);
|
||||
}
|
||||
|
||||
private @Nullable ProfileTypeUID getSuggestedProfileTypeUID(@Nullable ChannelTypeUID channelTypeUID,
|
||||
@Nullable String itemType) {
|
||||
if (KNXBindingConstants.CHANNEL_CONTACT_CONTROL_UID.equals(channelTypeUID) && itemType != null) {
|
||||
switch (itemType) {
|
||||
case CoreItemFactory.CONTACT:
|
||||
return UID_CONTACT_CONTROL;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback,
|
||||
ProfileContext profileContext) {
|
||||
if (UID_CONTACT_CONTROL.equals(profileTypeUID)) {
|
||||
return new KNXContactControlProfile(callback, thingRegistry);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user