-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[knx] postUpdate for contact-control sends to bus
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>
- Loading branch information
1 parent
444d824
commit 4b0918d
Showing
4 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
...knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXContactControlProfile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/** | ||
* 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 default implementation for a follow profile. | ||
* | ||
* In contrast to the {@link SystemDefaultProfile} it does not forward any commands to the ThingHandler. Instead, it | ||
* turn {@link State} updates into {@link Command}s (if possible) and then forwards those to the {@link ThingHandler}. | ||
* <p> | ||
* This allows devices to be operated as "followers" of another one directly, without the need to write any rules. | ||
* <p> | ||
* The ThingHandler may send commands to the framework, but no state updates are forwarded. | ||
* | ||
* @author Simon Kaufmann - 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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
...inding.knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXProfileFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 all profiles and their types of this binding. | ||
* | ||
* @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; | ||
} | ||
} | ||
} |