[Keba] Implement thing action to set display text (#18310)

* Implement Thing Action for setting display text

Signed-off-by: Simon Spielmann <simon.spielmann@gmx.de>
This commit is contained in:
Simon Spielmann
2025-03-07 15:27:41 +01:00
committed by GitHub
parent 40215b6519
commit 2e82fe6540
4 changed files with 140 additions and 7 deletions
@@ -48,6 +48,30 @@ All devices support the following channels:
| maxpilotcurrent | Number:ElectricCurrent | yes | current offered to the vehicle via control pilot signalization |
| maxpilotcurrentdutycyle | Number:Dimensionless | yes | duty cycle of the control pilot signal |
## Rule Actions
Certain Keba models support setting the text on the built-in display.
The text can be set via a rule action `setDisplay`. It comes in two variants:
```java
rule "Set Display Text"
when
System reached start level 100
then
val keContactActions = getActions("keba", "keba:kecontact:1")
// Default duration
keContactActions.setDisplay("TEXT$1")
// Explicit duration set
keContactActions.setDisplay("TEXT$2", 5, 10)
end
```
| Parameter | Description |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| text | Text shown on the display. Maximum 23 ASCII characters can be used. `~` == Σ, `$` == blank, `,` == comma |
| durationMin _(optional)_ | Defines the duration in seconds how long the text will displayed before another display command will be processed (internal MID metering relevant information may overrule this) |
| durationMax _(optional)_ | Defines the duration in seconds how long the text will displayed if no additional display command follows. |
## Example
demo.Things:
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2010-2025 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.keba.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.keba.internal.KebaBindingConstants;
import org.openhab.core.automation.annotation.ActionInput;
import org.openhab.core.automation.annotation.RuleAction;
import org.openhab.core.thing.binding.ThingActions;
import org.openhab.core.thing.binding.ThingActionsScope;
import org.openhab.core.thing.binding.ThingHandler;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ServiceScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link KeContactActions} is responsible for handling actions, which
* are sent to the binding.
*
* @author Simon Spielmann - Initial contribution
*/
@Component(scope = ServiceScope.PROTOTYPE, service = KeContactActions.class)
@ThingActionsScope(name = KebaBindingConstants.BINDING_ID)
@NonNullByDefault
public class KeContactActions implements ThingActions {
private final Logger logger = LoggerFactory.getLogger(KeContactActions.class);
private @Nullable KeContactHandler handler;
@Override
public void setThingHandler(ThingHandler handler) {
this.handler = (KeContactHandler) handler;
}
@Override
public @Nullable ThingHandler getThingHandler() {
return handler;
}
@RuleAction(label = "@text/actionLabel", description = "@text/actionDesc")
public void setDisplay(
@ActionInput(name = "text", label = "@text/actionInputTextLabel", description = "@text/actionInputTextDesc") @Nullable String text,
@ActionInput(name = "durationMin", label = "@text/actionInputDurationMinLabel", description = "@text/actionInputDurationMinDesc") int durationMin,
@ActionInput(name = "durationMax", label = "@text/actionInputDurationMaxLabel", description = "@text/actionInputDurationMaxDesc") int durationMax) {
if (handler == null) {
logger.warn("KeContact Action service ThingHandler is null!");
return;
}
handler.setDisplay(text, durationMin, durationMax);
}
public static void setDisplay(ThingActions actions, @Nullable String text, int durationMin, int durationMax) {
((KeContactActions) actions).setDisplay(text, durationMin, durationMax);
}
@RuleAction(label = "@text/actionLabel", description = "@text/actionDesc")
public void setDisplay(
@ActionInput(name = "text", label = "@text/actionInputTextLabel", description = "@text/actionInputTextDesc") @Nullable String text) {
if (handler == null) {
logger.warn("KeContact Action service ThingHandler is null!");
return;
}
handler.setDisplay(text, -1, -1);
}
public static void setDisplay(ThingActions actions, @Nullable String text) {
((KeContactActions) actions).setDisplay(text);
}
}
@@ -20,6 +20,8 @@ import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
@@ -41,6 +43,7 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
@@ -121,6 +124,11 @@ public class KeContactHandler extends BaseThingHandler {
}
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return List.of(KeContactActions.class);
}
private boolean isKebaReachable() throws IOException {
boolean isReachable = false;
SocketAddress sockAddr = new InetSocketAddress(getIPAddress(), SOCKET_CHECK_PORT_NUMBER);
@@ -571,13 +579,7 @@ public class KeContactHandler extends BaseThingHandler {
}
case CHANNEL_DISPLAY: {
if (command instanceof StringType) {
if (type == KebaType.P30 && (series == KebaSeries.C || series == KebaSeries.X)) {
String cmd = command.toString();
int maxLength = (cmd.length() < 23) ? cmd.length() : 23;
transceiver.send("display 0 0 0 0 " + cmd.substring(0, maxLength), this);
} else {
logger.warn("'Display' is not supported on a KEBA KeContact {}:{}", type, series);
}
setDisplay(command.toString(), -1, -1);
}
break;
}
@@ -602,4 +604,21 @@ public class KeContactHandler extends BaseThingHandler {
}
}
}
public void setDisplay(String text, int durationMin, int durationMax) {
if (type == KebaType.P30 && (series == KebaSeries.C || series == KebaSeries.X)) {
int maxLength = (text.length() < 23) ? text.length() : 23;
int a = 1;
if (durationMax < 0 || durationMax < 0) {
a = 0;
durationMin = 0;
durationMax = 0;
}
transceiver.send(
"display " + a + " " + durationMin + " " + durationMax + " 0 " + text.substring(0, maxLength),
this);
} else {
logger.warn("'Display' is not supported on a KEBA KeContact {}:{}", type, series);
}
}
}
@@ -90,3 +90,13 @@ channel-type.keba.x1.label = X1
channel-type.keba.x1.description = State of the X1 input
channel-type.keba.x2.label = X2
channel-type.keba.x2.description = State of the X2 output
# thing actions
actionLabel = set text in display
actionDesc = Sets a text to show in the display of the wallbox
actionInputTextLabel = Text
actionInputTextDesc = Text shown on the display. Maximum 23 ASCII characters can be used. ~ == \u03A3, $ == blank, == comma
actionInputDurationMinLabel = Duration (min)
actionInputDurationMinDesc = Defines the duration in seconds how long the text will displayed before another display command will be processed (internal MID metering relevant information may overrule this).
actionInputDurationMaxLabel = Duration (max)
actionInputDurationMaxDesc = Defines the duration in seconds how long the text will displayed if no additional display command follows.