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>
This commit is contained in:
parent
bed592c3a4
commit
d5fc6950dc
@ -21,6 +21,7 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link KNXBindingConstants} class defines common constants, which are
|
* 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 = "switch";
|
||||||
public static final String CHANNEL_SWITCH_CONTROL = "switch-control";
|
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( //
|
public static final Set<String> CONTROL_CHANNEL_TYPES = Set.of( //
|
||||||
CHANNEL_COLOR_CONTROL, //
|
CHANNEL_COLOR_CONTROL, //
|
||||||
CHANNEL_CONTACT_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) {
|
private ProfileTypeUID getSuggestedProfileTypeUID(ChannelTypeUID channelTypeUID) {
|
||||||
if (isControl(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;
|
return SystemProfiles.FOLLOW;
|
||||||
} else {
|
} else {
|
||||||
return SystemProfiles.DEFAULT;
|
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