Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lcn] Add LCN binding #7509

Merged
merged 16 commits into from
Jun 17, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2020 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.lcn.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
* The {@link ILcnModuleActions} defines the interface for all thing actions supported by the binding.
* These methods, parameters, and return types are explained in {@link LcnModuleActions}.
*
* @author Fabian Wolter - Initial contribution
*/
@NonNullByDefault
public interface ILcnModuleActions {
void hitKey(@Nullable String table, int key, @Nullable String action);

void flickerOutput(int output, int depth, int ramp, int count);

void sendDynamicText(int row, @Nullable String textInput);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
*/
@ThingActionsScope(name = "lcn")
@NonNullByDefault
public class LcnModuleActions implements ThingActions {
public class LcnModuleActions implements ThingActions, ILcnModuleActions {
private final Logger logger = LoggerFactory.getLogger(LcnModuleActions.class);
private static final int DYN_TEXT_CHUNK_COUNT = 5;
private static final int DYN_TEXT_HEADER_LENGTH = 6;
Expand All @@ -58,6 +58,7 @@ public void setThingHandler(@Nullable ThingHandler handler) {
return moduleHandler;
}

@Override
@RuleAction(label = "LCN Hit Key", description = "Sends a \"hit key\" command to an LCN module")
public void hitKey(
@ActionInput(name = "table", required = true, type = "java.lang.String", label = "Table", description = "The key table (A-D)") @Nullable String table,
Expand Down Expand Up @@ -104,6 +105,7 @@ public void hitKey(
}
}

@Override
@RuleAction(label = "LCN Flicker Output", description = "Let a dimmer output flicker for a given count of flashes")
public void flickerOutput(
@ActionInput(name = "output", type = "java.lang.Integer", required = true, label = "Output", description = "The output number (1-4)") int output,
Expand All @@ -117,6 +119,7 @@ public void flickerOutput(
}
}

@Override
@RuleAction(label = "LCN Dynamic Text", description = "Send custom text to an LCN-GTxD display")
public void sendDynamicText(
@ActionInput(name = "row", type = "java.lang.Integer", required = true, label = "Row", description = "Display the text on the LCN-GTxD in the given row number (1-4)") int row,
Expand Down Expand Up @@ -154,16 +157,16 @@ public void sendDynamicText(
}
}

private static LcnModuleActions invokeMethodOf(@Nullable ThingActions actions) {
private static ILcnModuleActions invokeMethodOf(@Nullable ThingActions actions) {
if (actions == null) {
throw new IllegalArgumentException("actions cannot be null");
}
if (actions.getClass().getName().equals(LcnModuleActions.class.getName())) {
if (actions instanceof LcnModuleActions) {
return (LcnModuleActions) actions;
return (ILcnModuleActions) actions;
} else {
return (LcnModuleActions) Proxy.newProxyInstance(LcnModuleActions.class.getClassLoader(),
new Class[] { LcnModuleActions.class }, (Object proxy, Method method, Object[] args) -> {
return (ILcnModuleActions) Proxy.newProxyInstance(ILcnModuleActions.class.getClassLoader(),
new Class[] { ILcnModuleActions.class }, (Object proxy, Method method, Object[] args) -> {
Method m = actions.getClass().getDeclaredMethod(method.getName(),
method.getParameterTypes());
return m.invoke(actions, args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class PckGatewayHandler extends BaseBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(PckGatewayHandler.class);
private @Nullable Connection connection;
private Optional<Consumer<String>> pckListener = Optional.empty();
@Nullable
private PckGatewayConfiguration config;
fwolter marked this conversation as resolved.
Show resolved Hide resolved

public PckGatewayHandler(Bridge bridge) {
super(bridge);
Expand All @@ -62,13 +64,13 @@ public void handleCommand(ChannelUID channelUID, Command command) {

@Override
public synchronized void initialize() {
PckGatewayConfiguration config = getConfigAs(PckGatewayConfiguration.class);
PckGatewayConfiguration localConfig = config = getConfigAs(PckGatewayConfiguration.class);

String errorMessage = "Could not connect to LCN-PCHK/PKE: " + config.getHostname() + ": ";
String errorMessage = "Could not connect to LCN-PCHK/PKE: " + localConfig.getHostname() + ": ";

try {
OutputPortDimMode dimMode;
String mode = config.getMode();
String mode = localConfig.getMode();
if (LcnDefs.OutputPortDimMode.NATIVE50.name().equalsIgnoreCase(mode)) {
dimMode = LcnDefs.OutputPortDimMode.NATIVE50;
} else if (LcnDefs.OutputPortDimMode.NATIVE200.name().equalsIgnoreCase(mode)) {
Expand All @@ -77,9 +79,9 @@ public synchronized void initialize() {
throw new LcnException("DimMode " + mode + " is not supported");
}

ConnectionSettings settings = new ConnectionSettings("0", config.getHostname(), config.getPort(),
config.getUsername(), config.getPassword(), dimMode, LcnDefs.OutputPortStatusMode.PERCENT,
config.getTimeoutMs());
ConnectionSettings settings = new ConnectionSettings("0", localConfig.getHostname(), localConfig.getPort(),
localConfig.getUsername(), localConfig.getPassword(), dimMode, LcnDefs.OutputPortStatusMode.PERCENT,
localConfig.getTimeoutMs());

connection = new Connection(settings, scheduler, new ConnectionCallback() {
@Override
Expand Down Expand Up @@ -296,6 +298,7 @@ public void dispose() {
* @return the timeout in ms
*/
public long getTimeoutMs() {
return getConfigAs(PckGatewayConfiguration.class).getTimeoutMs();
PckGatewayConfiguration localConfig = config;
return localConfig != null ? localConfig.getTimeoutMs() : 3500;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public enum Variable {
S0INPUT4(3, Type.S0INPUT, LcnChannelGroup.S0INPUT); // LCN-BU4L

private final int number;
private Optional<Integer> thresholdNumber = Optional.empty();
private final Optional<Integer> thresholdNumber;
private final Type type;
private final LcnChannelGroup channelGroup;

Expand All @@ -82,14 +82,18 @@ public enum Type {
}

Variable(int number, Type type, LcnChannelGroup channelGroup) {
this.number = number;
this.type = type;
this.channelGroup = channelGroup;
this(number, Optional.empty(), type, channelGroup);
}

Variable(int number, int thresholdNumber, Type type, LcnChannelGroup channelGroup) {
this(number, type, channelGroup);
this.thresholdNumber = Optional.of(thresholdNumber);
this(number, Optional.of(thresholdNumber), type, channelGroup);
}

Variable(int number, Optional<Integer> thresholdNumber, Type type, LcnChannelGroup channelGroup) {
this.number = number;
this.type = type;
this.channelGroup = channelGroup;
this.thresholdNumber = thresholdNumber;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ public AbstractConnectionState(StateContext context, ScheduledExecutorService sc
* @param wantsAck true, if the module shall respond with an Ack upon successful processing
* @param data the PCK message to be sent
*/
public abstract void queue(LcnAddr addr, boolean wantsAck, byte[] data);
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

/**
* Shuts the Connection down finally. A shut-down connection cannot re-used.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.concurrent.TimeUnit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lcn.internal.common.LcnAddr;
import org.openhab.binding.lcn.internal.common.LcnException;

/**
Expand Down Expand Up @@ -47,9 +46,4 @@ protected void startTimeoutTimer() {
new LcnException("Network timeout in state " + getClass().getSimpleName())),
connection.getSettings().getTimeout(), TimeUnit.MILLISECONDS));
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.lcn.internal.common.LcnAddr;
import org.openhab.binding.lcn.internal.common.LcnException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -92,11 +91,6 @@ private void handleConnectionFailure(@Nullable Throwable e) {
context.handleConnectionFailed(e);
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
// nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.concurrent.TimeUnit;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lcn.internal.common.LcnAddr;

/**
* This state is active when the connection failed. A grace period is enforced to prevent fast cycling through the
Expand All @@ -40,11 +39,6 @@ public void startWorking() {
TimeUnit.SECONDS));
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
// nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.concurrent.ScheduledExecutorService;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lcn.internal.common.LcnAddr;

/**
* This is the starting state of the {@link Connection} {@link StateMachine}.
Expand All @@ -33,11 +32,6 @@ public void startWorking() {
nextState(ConnectionStateConnecting.class);
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
// nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.regex.Pattern;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lcn.internal.common.LcnAddr;
import org.openhab.binding.lcn.internal.common.LcnAddrGrp;
import org.openhab.binding.lcn.internal.common.LcnException;
import org.openhab.binding.lcn.internal.common.PckGenerator;
Expand Down Expand Up @@ -66,11 +65,6 @@ private void update() {
}
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
Matcher matcher = PATTERN_SK_RESPONSE.matcher(data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.concurrent.ScheduledExecutorService;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.lcn.internal.common.LcnAddr;
import org.openhab.binding.lcn.internal.common.PckGenerator;

/**
Expand All @@ -37,11 +36,6 @@ public void startWorking() {
nextState(ConnectionStateSegmentScan.class);
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
// nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.lcn.internal.common.LcnAddr;
import org.openhab.binding.lcn.internal.common.LcnDefs;
import org.openhab.binding.lcn.internal.common.LcnException;

Expand Down Expand Up @@ -48,11 +47,6 @@ public void startWorking() {
addTimer(localLegacyTimer);
}

@Override
public void queue(LcnAddr addr, boolean wantsAck, byte[] data) {
connection.queueOffline(addr, wantsAck, data);
}

@Override
public void onPckMessageReceived(String data) {
ScheduledFuture<?> localLegacyTimer = legacyTimer;
Expand Down