[lcn] Add shutter positioning/angle, operating hours counters, tunable white, regulator mode, beeping (#13056)
* [lcn] Add shutter positioning/angle, operating hours counters, tunable white, regulator mode, beeping Also, fix possible race condition during connecting, when the PC coupler is not connected to the LCN data wire. Replace discontinued LCN-PKE by LCN-VISU. Signed-off-by: Fabian Wolter <github@fabian-wolter.de>
This commit is contained in:
parent
9bd8854e0b
commit
36bd806c28
@ -1,19 +1,21 @@
|
||||
# LCN Binding
|
||||
|
||||
[Local Control Network (LCN)](https://www.lcn.eu) is a building automation system for small and very large installations.
|
||||
[Local Control Network (LCN)](https://www.lcn.eu) is a building automation system.
|
||||
It is capable of controlling lights, shutters, access control etc. and can process data from several sensor types.
|
||||
It has been introduced in 1992.
|
||||
It was introduced in 1992.
|
||||
|
||||
A broad range of glass key panels, displays, remote controls, sensors and in- and outputs exist.
|
||||
The system can handle up to 30,000 bus members, called modules.
|
||||
LCN modules are available for DIN rail and in-wall mounting and feature versatile interfaces. The bus modules and most of the accessories are developed, manufactured and assembled in Germany.
|
||||
LCN modules are available for DIN rail and in-wall mounting and feature versatile interfaces.
|
||||
The bus modules and most of the accessories are developed, manufactured and assembled in Germany.
|
||||
|
||||
Bus members are inter-connected via a free wire in the standard NYM cable. Wireless components are available, though.
|
||||
Bus members are inter-connected via a free wire in the standard NYM cable.
|
||||
Wireless components are available, though.
|
||||
|
||||

|
||||
|
||||
This binding uses TCP/IP to access the LCN bus via the software LCN-PCHK (Windows/Linux) or the DIN rail device LCN-PKE.
|
||||
**This means 1 unused LCN-PCHK license or a LCN-PKE is required**
|
||||
This binding uses TCP/IP to access the LCN bus via the software LCN-PCHK (Windows/Linux) or the DIN rail device LCN-VISU.
|
||||
**This means 1 unused LCN-PCHK license or a LCN-VISU is required**
|
||||
|
||||
## Supported Things
|
||||
|
||||
@ -21,8 +23,7 @@ This binding uses TCP/IP to access the LCN bus via the software LCN-PCHK (Window
|
||||
|
||||
Any LCN module that should be controlled or visualized, need to be added to openHAB as a *Thing*.
|
||||
|
||||
LCN modules with firmware versions 120612 (2008) and 170602 (2013) were tested with this binding.
|
||||
No known features/changes that need special handling were added until now (2020).
|
||||
LCN modules with firmware versions 120612 (2008), 170602 (2013) and 1F080A (2021) were tested with this binding.
|
||||
Modules with older and newer firmware should work, too.
|
||||
The module hardware types (e.g. LCN-SH, LCN-HU, LCN-UPP, ...) are compatible to each other and can therefore be handled all in the same way.
|
||||
|
||||
@ -39,13 +40,13 @@ See [Discover LCN Modules](#discover-lcn-modules).
|
||||
### Bridge: LCN PCK Gateway
|
||||
|
||||
PCK is the protocol spoken over TCP/IP with a PCK gateway to communicate with the LCN bus.
|
||||
Examples for PCK gateways are the *LCN-PCHK* software running on Windows or Linux and the DIN rail mounting device *LCN-PKE*.
|
||||
Examples for PCK gateways are the *LCN-PCHK* software running on Windows or Linux and the DIN rail mounting device *LCN-VISU*.
|
||||
|
||||
For each LCN bus, interfaced to openHAB, a PCK gateway needs to be added to openHAB as a *Thing*.
|
||||
|
||||
Several PCK gateways can be added to openHAB to control multiple LCN busses in distinct locations.
|
||||
|
||||
The minimum recommended version is LCN-PCHK 2.8 (older versions will also work, but lack some functionality).
|
||||
The minimum recommended version is LCN-PCHK 3.3 (older versions will also work, but lack some functionality).
|
||||
Visit [https://www.lcn.eu](https://www.lcn.eu) for updates.
|
||||
|
||||
Thing Type ID: `pckGateway`
|
||||
@ -130,14 +131,18 @@ If a special command is needed, the [Hit Key](#hit-key) action (German: "Sende T
|
||||
| LCN Feature (English) | LCN Feature (German) | Channel | IDs | Type | Description |
|
||||
|---------------------------------|----------------------------------|------------------------|------|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Dimmer Output Control Single | Ausgang | output | 1-4 | Dimmer, Switch | Sets the dimming value of an output with a given ramp. |
|
||||
| Dimmer Output Control Color | Ausgang Farbe | output | color | Color, Switch | Sets the outputs 1-4 to control an RGBW lamp. |
|
||||
| Tunable White Mode | Tunable White Modus | output | tunablewhite | String | Sets the module's tunable white mode: `DISABLE`: Tunable white disabled. `OUTPUT1`: Output 1 is used for controlling. Output 2 is adjusted automatically. `BOTH`: Output 1 is used to control the brightness. Output 2 controls the temperature. |
|
||||
| Relay | Relais | relay | 1-8 | Switch | Controls a relay and visualizes its state. |
|
||||
| Visualize Binary Sensor | Binärsensor anzeigen | binarysensor | 1-8 | Contact | Visualizes the state of a binary sensor (special channel mapping for some devices). |
|
||||
| LED Control | LED-Steuerung | led | 1-12 | Text (ON, OFF, BLINK, FLICKER) | Controls an LED and visualizes its current state. |
|
||||
| Visualize Logic Operations | Logik Funktion anzeigen | logic | 1-4 | Text (NOT, OR, AND) | Visualizes the result of the logic operation. |
|
||||
| Visualize Binary Sensor | Binärsensor anzeigen | binarysensor | 1-8 | Contact | Visualizes the state of a binary sensor (special channel mapping for some devices). |
|
||||
| LED Control | LED-Steuerung | led | 1-12 | String | Controls an LED and visualizes its current state: `ON`, `OFF`, `BLINK`, `FLICKER` |
|
||||
| Visualize Logic Operations | Logik Funktion anzeigen | logic | 1-4 | String | Visualizes the result of the logic operation: `NOT`, `OR`, `AND` |
|
||||
| Motor/Shutter on Dimmer Outputs | Motor/Rollladen an Ausgängen | rollershutteroutput | 1-4 | Rollershutter | Control roller shutters on dimmer outputs |
|
||||
| Motor/Shutter on Relays | Motor/Rollladen an Relais | rollershutterrelay | 1-4 | Rollershutter | Control roller shutters on relays |
|
||||
| Motor/Shutter on Relays | Motor/Rollladen an Relais | rollershutterrelay | 1-4 | Rollershutter, Dimmer | Control position of roller shutters on relays (Supports UpDown, StopMove, Percent) |
|
||||
| Shutter Slat Angle on Relays | Rollladenlamellen an Relais | rollershutterrelayslat | 1-4 | Rollershutter, Dimmer | Control slat angle of roller shutters on relays (Supports UpDown, StopMove, Percent) |
|
||||
| Variables | Variable anzeigen | variable | 1-12 | Number | Sets and visualizes the value of a variable. |
|
||||
| Regulator Set Setpoint | Regler Sollwert ändern | rvarsetpoint | 1-2 | Number | Sets and visualizes the setpoint of a regulator. |
|
||||
| Regulator Set Mode | Reglerverhalten ändern | rvarmode | 1-2 | String | Sets the mode of the regulator: `HEATING` or `COOLING` |
|
||||
| Regulator Lock | Regler sperren | rvarlock | 1-2 | Switch | Locks a regulator and visualizes its locking state. |
|
||||
| Set Thresholds in Register 1 | Schwellwert in Register 1 ändern | thresholdregister1 | 1-4 | Number | Sets and visualizes a threshold in the given threshold register. |
|
||||
| Set Thresholds in Register 2 | Schwellwert in Register 2 ändern | thresholdregister2 | 1-4 | Number | Sets and visualizes a threshold in the given threshold register. |
|
||||
@ -158,8 +163,12 @@ If a special command is needed, the [Hit Key](#hit-key) action (German: "Sende T
|
||||
| Access Control | Zutrittskontrolle | code#remotecontrolcode | | Trigger | Receive serial numbers from remote control |
|
||||
| Remote Control Battery Low | Fernbedienung Batterie schwach | code#remotecontrolbatterylow | | Trigger | Triggered when the sending remote control has a low battery |
|
||||
| Host Command (Send Keys) | Kommando an Host (Sende Tasten) | hostcommand#sendKeys | - | Trigger | Receive *send keys* command from LCN module |
|
||||
| Operating Hours Counter Outputs | Betriebsstundenzähler Ausgänge | operatinghourscounter | output[1-4] | Number:Time | Visualize Operating Hours Counter for outputs |
|
||||
| Operating Hours Counter Outputs (rel. Work) | Betriebsstundenzähler Ausgänge (rel. Arbeit) | operatinghourscounter | outputrelativework[1-4] | Number:Time | Visualize Operating Hours Counter for outputs (relative work) |
|
||||
| Operating Hours Counter Relays | Betriebsstundenzähler Relais | operatinghourscounter | relay[1-8] | Number:Time | Visualize Operating Hours Counter for relays |
|
||||
| Operating Hours Counter Binary Sensor | Betriebsstundenzähler Binärsensoren | operatinghourscounter | binarysensor[1-8] | Number:Time | Visualize Operating Hours Counter for binary sensors |
|
||||
| Status Message | Statusmeldungen | - | - | - | Automatically done by openHAB Binding |
|
||||
| Audio Beep | Audio Piepen | - | - | - | Not implemented |
|
||||
| Audio Beep | Audio Piepen | N/A | N/A | N/A | Action: "beep" (see below) |
|
||||
| Audio LCN-MRS | Audio LCN-MRS | - | - | - | Not implemented |
|
||||
| Count/Compute | Zählen/Rechnen | - | - | - | Not implemented |
|
||||
| DALI | DALI | - | - | - | Not implemented |
|
||||
@ -180,7 +189,7 @@ If a special command is needed, the [Hit Key](#hit-key) action (German: "Sende T
|
||||
| Lock Relays | Sperre Relais | - | - | - | Not implemented |
|
||||
| Lock Thresholds | Sperre Schwellwerte | - | - | - | Not implemented |
|
||||
| Motor Position | Motor Position | - | - | - | Not implemented |
|
||||
| Relay Timer | Relais-Timer | N/A | N/A | N/A | Action: "startRelayTimer": Starts a relay timer for the given relay number with the given duration in milliseconds. |
|
||||
| Relay Timer | Relais-Timer | N/A | N/A | N/A | Action: "startRelayTimer" (see below) |
|
||||
| Send Keys Delayed | Sende Tasten verzögert | - | - | - | Not implemented |
|
||||
| Set S0 Counters | S0-Zähler setzen | - | - | - | Not implemented |
|
||||
| Status Command | Statuskommandos | - | - | - | Not implemented |
|
||||
@ -415,10 +424,43 @@ when
|
||||
then
|
||||
val actions = getActions("lcn","lcn:module:b827ebfea4bb:17B4196847")
|
||||
// relayNumber=3, duration=90
|
||||
actions.startRelayTimer(3,90)
|
||||
actions.startRelayTimer(3, 90)
|
||||
end
|
||||
```
|
||||
|
||||
### Beep
|
||||
|
||||
This *Action* realizes the LCN commmand "audio" (German: "Piepen").
|
||||
It lets the beeper connected to the LCN module beep.
|
||||
|
||||
When programming an "audio" *Action*, the following parameters can be set:
|
||||
|
||||
*volume* - Sound volume in percent (if null, the previous volume will be used)<br />
|
||||
*tonality* - The tonality as a String. You need to use quotes. See below.<br />
|
||||
*count* - Number of beeps (max. 50)
|
||||
|
||||
Tonalities:
|
||||
|
||||
- "N"=push button hit (normal)
|
||||
- "S"=special
|
||||
- "1"=push button make
|
||||
- "2"=push button break
|
||||
- "3"=standard
|
||||
- "4"=special
|
||||
- "5"=special short
|
||||
- "6"=error
|
||||
- "7"=long
|
||||
|
||||
```
|
||||
rule "Beep when dummy switch changed"
|
||||
when
|
||||
Item Dummy_Switch changed
|
||||
then
|
||||
val actions = getActions("lcn","lcn:module:b827ebfea4bb:b0b029b920")
|
||||
// volume=100, tonality="6", count=2
|
||||
actions.beep(100, "6", 2)
|
||||
end
|
||||
```
|
||||
|
||||
## Caveat and Limitations
|
||||
|
||||
@ -469,6 +511,7 @@ Switch M10_Relay1 {channel="lcn:module:b827ebfea4bb:S000M010:relay#1"}
|
||||
|
||||
// Roller Shutter on Relays 1+2
|
||||
Rollershutter M10_RollershutterRelay1 {channel="lcn:module:b827ebfea4bb:S000M010:rollershutterrelay#1"}
|
||||
Dimmer M10_RollershutterRelay1Slats {channel="lcn:module:68b8462b:S000M012:rollershutterrelayslat#1"}
|
||||
|
||||
// LEDs
|
||||
String M10_LED1 {channel="lcn:module:b827ebfea4bb:S000M010:led#1"}
|
||||
@ -545,6 +588,8 @@ sitemap lcn label="My home automation" {
|
||||
|
||||
// Roller Shutter on Relays
|
||||
Default item=M10_RollershutterRelay1 label="Roller Shutter on Relay 1-2"
|
||||
Dimmer item=M10_RollershutterRelay1 label="Roller Shutter Position on Relay 1-2"
|
||||
Default item=M10_RollershutterRelay1Slats label="Roller Shutter Slat Angle on Relay 1-2"
|
||||
|
||||
// LEDs
|
||||
Switch item=M10_LED1 label="LED 1" mappings=[ON=ON, OFF=OFF] // Don't display "Blink" or "Flicker"
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -39,9 +41,12 @@ public class LcnBindingConstants {
|
||||
public static final ThingTypeUID THING_TYPE_MODULE = new ThingTypeUID(BINDING_ID, "module");
|
||||
public static final ThingTypeUID THING_TYPE_GROUP = new ThingTypeUID(BINDING_ID, "group");
|
||||
/** Regex for address in PCK protocol */
|
||||
public static final String ADDRESS_REGEX = "[:=%]M(?<segId>\\d{3})(?<modId>\\d{3})";
|
||||
public static final String ADDRESS_WITHOUT_PREFIX = "M(?<segId>\\d{3})(?<modId>\\d{3})";
|
||||
public static final String ADDRESS_REGEX = "[:=%]" + ADDRESS_WITHOUT_PREFIX;
|
||||
public static final Pattern MEASUREMENT_PATTERN_BEFORE_2013 = Pattern
|
||||
.compile(LcnBindingConstants.ADDRESS_REGEX + "\\.(?<value>\\d{5})");
|
||||
/** LCN coding for ACK */
|
||||
public static final int CODE_ACK = -1;
|
||||
public static final Collection<String> ALLOWED_BEEP_TONALITIES = Set.of("N", "S", "1", "2", "3", "4", "5", "6",
|
||||
"7");
|
||||
}
|
||||
|
||||
@ -40,6 +40,8 @@ import org.slf4j.LoggerFactory;
|
||||
@NonNullByDefault
|
||||
public class LcnModuleActions implements ThingActions {
|
||||
private final Logger logger = LoggerFactory.getLogger(LcnModuleActions.class);
|
||||
private static final int MAX_BEEP_VOLUME = 100;
|
||||
private static final int MAX_BEEP_COUNT = 50;
|
||||
private static final int DYN_TEXT_CHUNK_COUNT = 5;
|
||||
private static final int DYN_TEXT_HEADER_LENGTH = 6;
|
||||
private static final int DYN_TEXT_CHUNK_LENGTH = 12;
|
||||
@ -173,6 +175,42 @@ public class LcnModuleActions implements ThingActions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the beeper connected to the LCN module beep.
|
||||
*
|
||||
* @param volume sound volume in percent. Can be null. Then, the last volume is used.
|
||||
* @param tonality N=normal, S=special, 1-7 tonalities 1-7. Can be null. Then, normal tonality is used.
|
||||
* @param count number of beeps. Can be null. Then, number of beeps is one.
|
||||
*/
|
||||
@RuleAction(label = "let the module's beeper beep", description = "Lets the beeper connected to the LCN module beep")
|
||||
public void beep(
|
||||
@ActionInput(name = "volume", required = false, type = "java.lang.Double", label = "Sound Volume", description = "The sound volume in percent.") @Nullable Double soundVolume,
|
||||
@ActionInput(name = "tonality", required = false, type = "java.lang.String", label = "Tonality", description = "Tonality (N, S, 1-7)") @Nullable String tonality,
|
||||
@ActionInput(name = "count", required = false, type = "java.lang.Integer", label = "Count", description = "Number of beeps") @Nullable Integer count) {
|
||||
try {
|
||||
if (soundVolume != null) {
|
||||
if (soundVolume < 0) {
|
||||
throw new LcnException("Volume cannot be negative: " + soundVolume);
|
||||
}
|
||||
getHandler().sendPck(PckGenerator.setBeepVolume(Math.min(soundVolume, MAX_BEEP_VOLUME)));
|
||||
}
|
||||
|
||||
Integer localCount = count;
|
||||
if (localCount == null) {
|
||||
localCount = 1;
|
||||
}
|
||||
|
||||
String filteredTonality = LcnBindingConstants.ALLOWED_BEEP_TONALITIES.stream() //
|
||||
.filter(t -> t.equals(tonality)) //
|
||||
.findAny() //
|
||||
.orElse("N");
|
||||
|
||||
getHandler().sendPck(PckGenerator.beep(filteredTonality, Math.min(localCount, MAX_BEEP_COUNT)));
|
||||
} catch (LcnException e) {
|
||||
logger.warn("Could not send beep command: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** Static alias to support the old DSL rules engine and make the action available there. */
|
||||
public static void hitKey(ThingActions actions, @Nullable String table, int key, @Nullable String action) {
|
||||
((LcnModuleActions) actions).hitKey(table, key, action);
|
||||
@ -193,6 +231,11 @@ public class LcnModuleActions implements ThingActions {
|
||||
((LcnModuleActions) actions).startRelayTimer(relaynumber, duration);
|
||||
}
|
||||
|
||||
/** Static alias to support the old DSL rules engine and make the action available there. */
|
||||
public static void beep(ThingActions actions, Double soundVolume, String tonality, Integer count) {
|
||||
((LcnModuleActions) actions).beep(soundVolume, tonality, count);
|
||||
}
|
||||
|
||||
private LcnModuleHandler getHandler() throws LcnException {
|
||||
LcnModuleHandler localModuleHandler = moduleHandler;
|
||||
if (localModuleHandler != null) {
|
||||
|
||||
@ -218,7 +218,7 @@ public class LcnModuleHandler extends BaseThingHandler {
|
||||
} else if (command instanceof PercentType) {
|
||||
subHandler.handleCommandPercent((PercentType) command, channelGroup, channelUid.getIdWithoutGroup());
|
||||
} else if (command instanceof StringType) {
|
||||
subHandler.handleCommandString((StringType) command, number.get());
|
||||
subHandler.handleCommandString((StringType) command, number.orElse(0));
|
||||
} else if (command instanceof DecimalType) {
|
||||
DecimalType decimalType = (DecimalType) command;
|
||||
DecimalType nativeValue = getConverter(channelUid).onCommandFromItem(decimalType.doubleValue());
|
||||
|
||||
@ -65,7 +65,7 @@ public class PckGatewayHandler extends BaseBridgeHandler {
|
||||
public synchronized void initialize() {
|
||||
PckGatewayConfiguration localConfig = config = getConfigAs(PckGatewayConfiguration.class);
|
||||
|
||||
String errorMessage = "Could not connect to LCN-PCHK/PKE: " + localConfig.getHostname() + ": ";
|
||||
String errorMessage = "Could not connect to LCN-PCHK/VISU: " + localConfig.getHostname() + ": ";
|
||||
|
||||
try {
|
||||
OutputPortDimMode dimMode;
|
||||
|
||||
@ -24,11 +24,14 @@ import org.openhab.binding.lcn.internal.subhandler.LcnModuleHostCommandSubHandle
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleKeyLockTableSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleLedSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleLogicSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleOperatingHoursCounterSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleOutputSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRelaySubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRollershutterOutputSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRollershutterRelaySubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRollershutterRelayPositionSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRollershutterRelaySlatAngleSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRvarLockSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRvarModeSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleRvarSetpointSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleS0CounterSubHandler;
|
||||
import org.openhab.binding.lcn.internal.subhandler.LcnModuleThresholdSubHandler;
|
||||
@ -44,12 +47,14 @@ public enum LcnChannelGroup {
|
||||
OUTPUT(4, LcnModuleOutputSubHandler::new),
|
||||
ROLLERSHUTTEROUTPUT(1, LcnModuleRollershutterOutputSubHandler::new),
|
||||
RELAY(8, LcnModuleRelaySubHandler::new),
|
||||
ROLLERSHUTTERRELAY(4, LcnModuleRollershutterRelaySubHandler::new),
|
||||
ROLLERSHUTTERRELAY(4, LcnModuleRollershutterRelayPositionSubHandler::new),
|
||||
ROLLERSHUTTERRELAYSLAT(4, LcnModuleRollershutterRelaySlatAngleSubHandler::new),
|
||||
LED(12, LcnModuleLedSubHandler::new),
|
||||
LOGIC(4, LcnModuleLogicSubHandler::new),
|
||||
BINARYSENSOR(8, LcnModuleBinarySensorSubHandler::new),
|
||||
VARIABLE(12, LcnModuleVariableSubHandler::new),
|
||||
RVARSETPOINT(2, LcnModuleRvarSetpointSubHandler::new),
|
||||
RVARMODE(2, LcnModuleRvarModeSubHandler::new),
|
||||
RVARLOCK(2, LcnModuleRvarLockSubHandler::new),
|
||||
THRESHOLDREGISTER1(5, LcnModuleThresholdSubHandler::new),
|
||||
THRESHOLDREGISTER2(4, LcnModuleThresholdSubHandler::new),
|
||||
@ -61,6 +66,7 @@ public enum LcnChannelGroup {
|
||||
KEYLOCKTABLEC(8, LcnModuleKeyLockTableSubHandler::new),
|
||||
KEYLOCKTABLED(8, LcnModuleKeyLockTableSubHandler::new),
|
||||
CODE(0, LcnModuleCodeSubHandler::new),
|
||||
OPERATINGHOURS(0, LcnModuleOperatingHoursCounterSubHandler::new),
|
||||
HOSTCOMMAND(0, LcnModuleHostCommandSubHandler::new);
|
||||
|
||||
private int count;
|
||||
|
||||
@ -56,7 +56,7 @@ public final class LcnDefs {
|
||||
public static final String LCNCONNSTATE_CONNECTED = "$io:#LCN:connected";
|
||||
/** LCN-PK/PKU is disconnected. */
|
||||
public static final String LCNCONNSTATE_DISCONNECTED = "$io:#LCN:disconnected";
|
||||
/** LCN-PCHK/PKE has not enough licenses to handle this connection. */
|
||||
/** LCN-PCHK/VISU has not enough licenses to handle this connection. */
|
||||
public static final String INSUFFICIENT_LICENSES = "$err:(license?)";
|
||||
|
||||
/**
|
||||
|
||||
@ -136,6 +136,21 @@ public final class PckGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command for setting the tunable white mode.
|
||||
*
|
||||
* @param mode 0..2
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException if out of range
|
||||
*/
|
||||
public static String setTunableWhiteMode(int mode) throws LcnException {
|
||||
if (mode < 0 || mode > 2) {
|
||||
throw new LcnException();
|
||||
}
|
||||
|
||||
return String.format("AW%d", mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a dim command for all output-ports.
|
||||
*
|
||||
@ -332,6 +347,42 @@ public final class PckGenerator {
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to control the position of roller shutters on relays.
|
||||
*
|
||||
* @param motorNumber of the roller shutter (0-based)
|
||||
* @param percent of the entire roller shutter height
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException if out of range
|
||||
*/
|
||||
public static String controlShutterPosition(int motorNumber, int percent) throws LcnException {
|
||||
return controlShutter(motorNumber, percent, "JH");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to control the slat angle of roller shutters on relays.
|
||||
*
|
||||
* @param motorNumber of the roller shutter (0-based)
|
||||
* @param percent of the slat angle
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException if out of range
|
||||
*/
|
||||
public static String controlShutterSlatAngle(int motorNumber, int percent) throws LcnException {
|
||||
return controlShutter(motorNumber, percent, "JW");
|
||||
}
|
||||
|
||||
private static String controlShutter(int motorNumber, int percent, String command) throws LcnException {
|
||||
if (motorNumber < 0 || motorNumber >= 4) {
|
||||
throw new LcnException("Roller shutter (relay) motor number out of range: " + motorNumber);
|
||||
}
|
||||
|
||||
if (percent < 0 || percent > 100) {
|
||||
throw new LcnException("Roller shutter (relay) position/angle out of range (percent): " + percent);
|
||||
}
|
||||
|
||||
return String.format("%s%03d%03d", command, percent, 1 << motorNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a binary-sensors status request.
|
||||
*
|
||||
@ -365,6 +416,30 @@ public final class PckGenerator {
|
||||
return String.format("X2%03d%03d%03d", 30, b1, b2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to change the regulator mode.
|
||||
*
|
||||
* @param number regulator number 0..1
|
||||
* @param cooling true=cooling, false=heating
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException
|
||||
*/
|
||||
public static String setRVarMode(int number, boolean cooling) throws LcnException {
|
||||
String regulator;
|
||||
switch (number) {
|
||||
case 0:
|
||||
regulator = "A";
|
||||
break;
|
||||
case 1:
|
||||
regulator = "B";
|
||||
break;
|
||||
default:
|
||||
throw new LcnException();
|
||||
}
|
||||
|
||||
return "RE" + regulator + "T" + (cooling ? "C" : "H");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to change the value of a variable.
|
||||
*
|
||||
@ -751,6 +826,41 @@ public final class PckGenerator {
|
||||
return command.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to set the beeping sound volume.
|
||||
*
|
||||
* @param volume the sound volume
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException if out of range
|
||||
*/
|
||||
public static String setBeepVolume(double volume) throws LcnException {
|
||||
if (volume < 0 || volume > 100) {
|
||||
throw new LcnException();
|
||||
}
|
||||
|
||||
return String.format("PIV%03d", Math.round(volume));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a command to let the beeper connected to the LCN module beep.
|
||||
*
|
||||
* @param volume the sound volume
|
||||
* @return the PCK command (without address header) as text
|
||||
* @throws LcnException if out of range
|
||||
*/
|
||||
public static String beep(String tonality, int count) throws LcnException {
|
||||
LcnBindingConstants.ALLOWED_BEEP_TONALITIES.stream() //
|
||||
.filter(t -> t.equals(tonality)) //
|
||||
.findAny() //
|
||||
.orElseThrow(LcnException::new);
|
||||
|
||||
if (count < 0) {
|
||||
throw new LcnException();
|
||||
}
|
||||
|
||||
return String.format("PI%s%d", tonality, Math.min(count, 50));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a null command, used for broadcast messages.
|
||||
*
|
||||
|
||||
@ -80,7 +80,7 @@ public abstract class AbstractConnectionState extends AbstractState<ConnectionSt
|
||||
*/
|
||||
protected void parseLcnBusDiconnectMessage(String pck) {
|
||||
if (pck.equals(LcnDefs.LCNCONNSTATE_DISCONNECTED)) {
|
||||
connection.getCallback().onOffline("LCN bus not connected to LCN-PCHK/PKE");
|
||||
connection.getCallback().onOffline("LCN-PCHK/VISU not connected to LCN data wire");
|
||||
nextState(ConnectionStateWaitForLcnBusConnectedAfterDisconnected::new);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class ConnectionStateMachine extends AbstractStateMachine<ConnectionState
|
||||
*
|
||||
* @param data the PCK message
|
||||
*/
|
||||
public void onInputReceived(String data) {
|
||||
public synchronized void onInputReceived(String data) {
|
||||
AbstractConnectionState localState = state;
|
||||
if (localState != null) {
|
||||
localState.onPckMessageReceived(data);
|
||||
|
||||
@ -51,7 +51,7 @@ public class ConnectionStateWaitForLcnBusConnected extends AbstractConnectionSta
|
||||
switch (data) {
|
||||
case LcnDefs.LCNCONNSTATE_DISCONNECTED:
|
||||
cancelLegacyTimer();
|
||||
connection.getCallback().onOffline("LCN bus not connected to LCN-PCHK/PKE");
|
||||
connection.getCallback().onOffline("LCN-PCHK/VISU not connected to LCN data wire");
|
||||
break;
|
||||
case LcnDefs.LCNCONNSTATE_CONNECTED:
|
||||
cancelLegacyTimer();
|
||||
@ -61,7 +61,7 @@ public class ConnectionStateWaitForLcnBusConnected extends AbstractConnectionSta
|
||||
case LcnDefs.INSUFFICIENT_LICENSES:
|
||||
cancelLegacyTimer();
|
||||
handleConnectionFailed(
|
||||
new LcnException("LCN-PCHK/PKE has not enough licenses to handle this connection"));
|
||||
new LcnException("LCN-PCHK/VISU has not enough licenses to handle this connection"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.lcn.internal.LcnBindingConstants;
|
||||
import org.openhab.binding.lcn.internal.LcnModuleHandler;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnDefs;
|
||||
@ -25,6 +26,7 @@ import org.openhab.binding.lcn.internal.common.LcnDefs.RelayStateModifier;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.binding.lcn.internal.common.PckGenerator;
|
||||
import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StopMoveType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
@ -34,8 +36,13 @@ import org.openhab.core.library.types.UpDownType;
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelaySubHandler extends AbstractLcnModuleSubHandler {
|
||||
public LcnModuleRollershutterRelaySubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
public abstract class AbstractLcnModuleRollershutterRelaySubHandler extends AbstractLcnModuleSubHandler {
|
||||
private static final String POSITION = "P";
|
||||
private static final String ANGLE = "W";
|
||||
private static final Pattern PATTERN = Pattern.compile(LcnBindingConstants.ADDRESS_REGEX + //
|
||||
"(?<type>[" + POSITION + "|" + ANGLE + "])(?<shutterNumber>\\d)(?<percent>\\d{3})");
|
||||
|
||||
public AbstractLcnModuleRollershutterRelaySubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
super(handler, info);
|
||||
}
|
||||
|
||||
@ -68,11 +75,21 @@ public class LcnModuleRollershutterRelaySubHandler extends AbstractLcnModuleSubH
|
||||
|
||||
@Override
|
||||
public void handleStatusMessage(Matcher matcher) {
|
||||
// status messages of roller shutters on relays are handled in the relay sub handler
|
||||
int shutterNumber = Integer.parseInt(matcher.group("shutterNumber")) - 1;
|
||||
int percent = Integer.parseInt(matcher.group("percent"));
|
||||
|
||||
LcnChannelGroup group;
|
||||
if (POSITION.equals(matcher.group("type"))) {
|
||||
group = LcnChannelGroup.ROLLERSHUTTERRELAY;
|
||||
} else {
|
||||
group = LcnChannelGroup.ROLLERSHUTTERRELAYSLAT;
|
||||
}
|
||||
|
||||
fireUpdate(group, shutterNumber, new PercentType(percent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Pattern> getPckStatusMessagePatterns() {
|
||||
return Collections.emptyList();
|
||||
return Collections.singleton(PATTERN);
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,6 @@
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -121,17 +120,17 @@ public abstract class AbstractLcnModuleSubHandler implements ILcnModuleSubHandle
|
||||
* @return true, if the message could be processed successfully
|
||||
*/
|
||||
public void tryParse(String pck) {
|
||||
Optional<Matcher> firstSuccessfulMatcher = getPckStatusMessagePatterns().stream().map(p -> p.matcher(pck))
|
||||
.filter(Matcher::matches).filter(m -> handler.isMyAddress(m.group("segId"), m.group("modId")))
|
||||
.findAny();
|
||||
|
||||
firstSuccessfulMatcher.ifPresent(matcher -> {
|
||||
try {
|
||||
handleStatusMessage(matcher);
|
||||
} catch (LcnException e) {
|
||||
logger.warn("Parse error: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
getPckStatusMessagePatterns().stream() //
|
||||
.map(p -> p.matcher(pck)) //
|
||||
.filter(Matcher::matches) //
|
||||
.filter(m -> handler.isMyAddress(m.group("segId"), m.group("modId"))) //
|
||||
.forEach(matcher -> {
|
||||
try {
|
||||
handleStatusMessage(matcher);
|
||||
} catch (LcnException e) {
|
||||
logger.warn("Parse error: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.lcn.internal.LcnBindingConstants;
|
||||
import org.openhab.binding.lcn.internal.LcnModuleHandler;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
||||
/**
|
||||
* Handles Commands and State changes of operating hours counters of an LCN module.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleOperatingHoursCounterSubHandler extends AbstractLcnModuleSubHandler {
|
||||
private static final Pattern PATTERN = Pattern.compile("\\$" + LcnBindingConstants.ADDRESS_WITHOUT_PREFIX + //
|
||||
"(?<type>[" + Type.createPattern() + "])(?<number>\\d)(?<durationSec>\\d+)");
|
||||
|
||||
private enum Type {
|
||||
OUTPUT("A", "output"),
|
||||
RELAY("R", "relay"),
|
||||
BINARY_INPUT("B", "binarysensor"),
|
||||
OUTPUT_RELATIVE_WORK("I", "outputrelativework");
|
||||
|
||||
String pattern;
|
||||
String id;
|
||||
|
||||
private Type(String pattern, String id) {
|
||||
this.pattern = pattern;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static String getId(String pattern) {
|
||||
return Stream.of(values()).filter(t -> t.pattern.equals(pattern)).findAny().get().id;
|
||||
}
|
||||
|
||||
public static String createPattern() {
|
||||
return Stream.of(values()).map(t -> t.pattern).collect(Collectors.joining("|"));
|
||||
}
|
||||
}
|
||||
|
||||
public LcnModuleOperatingHoursCounterSubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
super(handler, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRefresh(LcnChannelGroup channelGroup, int number) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Pattern> getPckStatusMessagePatterns() {
|
||||
return Arrays.asList(PATTERN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStatusMessage(Matcher matcher) {
|
||||
String number = matcher.group("number");
|
||||
String type = matcher.group("type");
|
||||
long durationSec = Long.parseLong(matcher.group("durationSec"));
|
||||
|
||||
handler.updateChannel(LcnChannelGroup.OPERATINGHOURS, Type.getId(type) + number,
|
||||
QuantityType.valueOf(durationSec, Units.SECOND));
|
||||
}
|
||||
}
|
||||
@ -29,6 +29,7 @@ import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -53,8 +54,8 @@ public class LcnModuleOutputSubHandler extends AbstractLcnModuleSubHandler {
|
||||
}
|
||||
|
||||
static {
|
||||
PERCENT_PATTERN = Pattern.compile(LcnBindingConstants.ADDRESS_REGEX + "A(?<outputId>\\d)(?<percent>\\d+)");
|
||||
NATIVE_PATTERN = Pattern.compile(LcnBindingConstants.ADDRESS_REGEX + "O(?<outputId>\\d)(?<value>\\d+)");
|
||||
PERCENT_PATTERN = Pattern.compile(LcnBindingConstants.ADDRESS_REGEX + "A(?<outputId>\\d)(?<percent>\\d{3})");
|
||||
NATIVE_PATTERN = Pattern.compile(LcnBindingConstants.ADDRESS_REGEX + "O(?<outputId>\\d)(?<value>\\d{3})");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,6 +143,25 @@ public class LcnModuleOutputSubHandler extends AbstractLcnModuleSubHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommandString(StringType command, int number) throws LcnException {
|
||||
int mode = 0;
|
||||
|
||||
switch (command.toString()) {
|
||||
case "DISABLE":
|
||||
mode = 0;
|
||||
break;
|
||||
case "OUTPUT1":
|
||||
mode = 1;
|
||||
break;
|
||||
case "BOTH":
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
handler.sendPck(PckGenerator.setTunableWhiteMode(mode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStatusMessage(Matcher matcher) {
|
||||
int outputId = Integer.parseInt(matcher.group("outputId")) - 1;
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.lcn.internal.LcnModuleHandler;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.binding.lcn.internal.common.PckGenerator;
|
||||
import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
|
||||
/**
|
||||
* Handles Commands and State changes of roller shutters connected to relay outputs of an LCN module.
|
||||
*
|
||||
* @author Fabian Wolter - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelayPositionSubHandler extends AbstractLcnModuleRollershutterRelaySubHandler {
|
||||
public LcnModuleRollershutterRelayPositionSubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
super(handler, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommandPercent(PercentType command, LcnChannelGroup channelGroup, int number)
|
||||
throws LcnException {
|
||||
handler.sendPck(PckGenerator.controlShutterPosition(number, command.intValue()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.lcn.internal.LcnModuleHandler;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.binding.lcn.internal.common.PckGenerator;
|
||||
import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
|
||||
/**
|
||||
* Handles Commands and State changes of roller shutters connected to relay outputs of an LCN module.
|
||||
*
|
||||
* @author Fabian Wolter - Initial Contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelaySlatAngleSubHandler extends AbstractLcnModuleRollershutterRelaySubHandler {
|
||||
public LcnModuleRollershutterRelaySlatAngleSubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
super(handler, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommandPercent(PercentType command, LcnChannelGroup channelGroup, int number)
|
||||
throws LcnException {
|
||||
handler.sendPck(PckGenerator.controlShutterSlatAngle(number, command.intValue()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.lcn.internal.LcnModuleHandler;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.binding.lcn.internal.common.PckGenerator;
|
||||
import org.openhab.binding.lcn.internal.connection.ModInfo;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
||||
/**
|
||||
* Handles the heating/cooling mode of a regulator.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRvarModeSubHandler extends AbstractLcnModuleVariableSubHandler {
|
||||
public LcnModuleRvarModeSubHandler(LcnModuleHandler handler, ModInfo info) {
|
||||
super(handler, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleStatusMessage(Matcher matcher) throws LcnException {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommandString(StringType command, int number) throws LcnException {
|
||||
boolean cooling;
|
||||
switch (command.toString()) {
|
||||
case "HEATING":
|
||||
cooling = false;
|
||||
break;
|
||||
case "COOLING":
|
||||
cooling = true;
|
||||
break;
|
||||
default:
|
||||
throw new LcnException();
|
||||
}
|
||||
|
||||
handler.sendPck(PckGenerator.setRVarMode(number, cooling));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Pattern> getPckStatusMessagePatterns() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ thing-type.lcn.group.description = An LCN group with multiple modules, configure
|
||||
thing-type.lcn.module.label = LCN Module
|
||||
thing-type.lcn.module.description = An LCN bus module, e.g. LCN-UPP, LCN-SH, LCN-HU
|
||||
thing-type.lcn.pckGateway.label = LCN-PCHK Gateway
|
||||
thing-type.lcn.pckGateway.description = An LCN gateway speaking the PCK language. E.g. LCN-PCHK software or the DIN rail device LCN-PKE.
|
||||
thing-type.lcn.pckGateway.description = An LCN gateway speaking the PCK language. E.g. LCN-PCHK software or the DIN rail device LCN-VISU.
|
||||
|
||||
# thing types config
|
||||
|
||||
@ -107,6 +107,31 @@ channel-group-type.lcn.logics.channel.1.label = Logic Operation 1
|
||||
channel-group-type.lcn.logics.channel.2.label = Logic Operation 2
|
||||
channel-group-type.lcn.logics.channel.3.label = Logic Operation 3
|
||||
channel-group-type.lcn.logics.channel.4.label = Logic Operation 4
|
||||
channel-group-type.lcn.operatinghourscounters.label = Operating Hours Counters
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor1.label = Binary Sensor 1
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor2.label = Binary Sensor 2
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor3.label = Binary Sensor 3
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor4.label = Binary Sensor 4
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor5.label = Binary Sensor 5
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor6.label = Binary Sensor 6
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor7.label = Binary Sensor 7
|
||||
channel-group-type.lcn.operatinghourscounters.channel.binarysensor8.label = Binary Sensor 8
|
||||
channel-group-type.lcn.operatinghourscounters.channel.output1.label = Output 1
|
||||
channel-group-type.lcn.operatinghourscounters.channel.output2.label = Output 2
|
||||
channel-group-type.lcn.operatinghourscounters.channel.output3.label = Output 3
|
||||
channel-group-type.lcn.operatinghourscounters.channel.output4.label = Output 4
|
||||
channel-group-type.lcn.operatinghourscounters.channel.outputrelativework1.label = Output 1 Relative Work
|
||||
channel-group-type.lcn.operatinghourscounters.channel.outputrelativework2.label = Output 2 Relative Work
|
||||
channel-group-type.lcn.operatinghourscounters.channel.outputrelativework3.label = Output 3 Relative Work
|
||||
channel-group-type.lcn.operatinghourscounters.channel.outputrelativework4.label = Output 4 Relative Work
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay1.label = Relay 1
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay2.label = Relay 2
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay3.label = Relay 3
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay4.label = Relay 4
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay5.label = Relay 5
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay6.label = Relay 6
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay7.label = Relay 7
|
||||
channel-group-type.lcn.operatinghourscounters.channel.relay8.label = Relay 8
|
||||
channel-group-type.lcn.outputs.label = Dimmer Outputs
|
||||
channel-group-type.lcn.outputs.channel.1.label = Output 1
|
||||
channel-group-type.lcn.outputs.channel.2.label = Output 2
|
||||
@ -124,14 +149,22 @@ channel-group-type.lcn.relays.channel.7.label = Relay 7
|
||||
channel-group-type.lcn.relays.channel.8.label = Relay 8
|
||||
channel-group-type.lcn.rollershutteroutputs.label = Roller Shutter (Dimmer)
|
||||
channel-group-type.lcn.rollershutteroutputs.channel.1.label = Shutter 1-2
|
||||
channel-group-type.lcn.rollershutterrelays.label = Roller Shutter (Relay)
|
||||
channel-group-type.lcn.rollershutterrelays.channel.1.label = Shutter 1-2
|
||||
channel-group-type.lcn.rollershutterrelays.channel.2.label = Shutter 3-4
|
||||
channel-group-type.lcn.rollershutterrelays.channel.3.label = Shutter 5-6
|
||||
channel-group-type.lcn.rollershutterrelays.channel.4.label = Shutter 7-8
|
||||
channel-group-type.lcn.rollershutterrelays.label = Shutter (Relay)
|
||||
channel-group-type.lcn.rollershutterrelays.channel.1.label = Position 1-2
|
||||
channel-group-type.lcn.rollershutterrelays.channel.2.label = Position 3-4
|
||||
channel-group-type.lcn.rollershutterrelays.channel.3.label = Position 5-6
|
||||
channel-group-type.lcn.rollershutterrelays.channel.4.label = Position 7-8
|
||||
channel-group-type.lcn.rollershutterrelayslats.label = Shutter Slat Angle (Relay)
|
||||
channel-group-type.lcn.rollershutterrelayslats.channel.1.label = Slat Angle 1-2
|
||||
channel-group-type.lcn.rollershutterrelayslats.channel.2.label = Slat Angle 3-4
|
||||
channel-group-type.lcn.rollershutterrelayslats.channel.3.label = Slat Angle 5-6
|
||||
channel-group-type.lcn.rollershutterrelayslats.channel.4.label = Slat Angle 7-8
|
||||
channel-group-type.lcn.rvarlocks.label = RVar Lock State
|
||||
channel-group-type.lcn.rvarlocks.channel.1.label = R1Var Lock
|
||||
channel-group-type.lcn.rvarlocks.channel.2.label = R2Var Lock
|
||||
channel-group-type.lcn.rvarmodes.label = RVar Heating/Cooling
|
||||
channel-group-type.lcn.rvarmodes.channel.1.label = R1Var Mode
|
||||
channel-group-type.lcn.rvarmodes.channel.2.label = R2Var Mode
|
||||
channel-group-type.lcn.rvarsetpoints.label = RVar Setpoints
|
||||
channel-group-type.lcn.rvarsetpoints.channel.1.label = R1Var Setpoint
|
||||
channel-group-type.lcn.rvarsetpoints.channel.2.label = R2Var Setpoint
|
||||
@ -191,6 +224,7 @@ channel-type.lcn.logic.label = Logic Operation
|
||||
channel-type.lcn.logic.state.option.NOT = Not (not fulfilled)
|
||||
channel-type.lcn.logic.state.option.OR = Or (partly fulfilled)
|
||||
channel-type.lcn.logic.state.option.AND = And (fulfilled)
|
||||
channel-type.lcn.operatinghourscounter.label = Operating Hours Counter
|
||||
channel-type.lcn.output.label = Output
|
||||
channel-type.lcn.relay.label = Relay
|
||||
channel-type.lcn.remotecontrolcodes.label = Remote Control (Codes)
|
||||
@ -198,8 +232,15 @@ channel-type.lcn.remotecontrolkeys.label = Remote Control (Keys)
|
||||
channel-type.lcn.remotecontrolsbatterylow.label = Low Battery
|
||||
channel-type.lcn.rollershutter.label = Roller Shutter
|
||||
channel-type.lcn.rvarlock.label = RVar Lock State
|
||||
channel-type.lcn.rvarmode.label = RVar Heating/Cooling
|
||||
channel-type.lcn.rvarmode.state.option.HEATING = Heating
|
||||
channel-type.lcn.rvarmode.state.option.COOLING = Cooling
|
||||
channel-type.lcn.sendKeys.label = Send Keys
|
||||
channel-type.lcn.transponders.label = Transponder Codes
|
||||
channel-type.lcn.tunablewhite.label = Tunable White Mode
|
||||
channel-type.lcn.tunablewhite.state.option.DISABLE = Tunable White Disabled
|
||||
channel-type.lcn.tunablewhite.state.option.OUTPUT1 = Control Output 1 (Output 2 is auto)
|
||||
channel-type.lcn.tunablewhite.state.option.BOTH = Output 1 Brightness/Output 2 Temperature
|
||||
channel-type.lcn.variable.label = Variable
|
||||
|
||||
# channel types config
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
<bridge-type id="pckGateway">
|
||||
<label>LCN-PCHK Gateway</label>
|
||||
<description>An LCN gateway speaking the PCK language. E.g. LCN-PCHK software or the DIN rail device LCN-PKE.</description>
|
||||
<description>An LCN gateway speaking the PCK language. E.g. LCN-PCHK software or the DIN rail device LCN-VISU.</description>
|
||||
|
||||
<config-description-ref uri="thing-type:lcn:pckGateway"/>
|
||||
</bridge-type>
|
||||
@ -24,10 +24,12 @@
|
||||
<channel-group typeId="leds" id="led"/>
|
||||
<channel-group typeId="relays" id="relay"/>
|
||||
<channel-group typeId="rollershutterrelays" id="rollershutterrelay"/>
|
||||
<channel-group typeId="rollershutterrelayslats" id="rollershutterrelayslat"/>
|
||||
<channel-group typeId="logics" id="logic"/>
|
||||
<channel-group typeId="binarysensors" id="binarysensor"/>
|
||||
<channel-group typeId="variables" id="variable"/>
|
||||
<channel-group typeId="rvarsetpoints" id="rvarsetpoint"/>
|
||||
<channel-group typeId="rvarmodes" id="rvarmode"/>
|
||||
<channel-group typeId="rvarlocks" id="rvarlock"/>
|
||||
<channel-group typeId="thresholdregisters1" id="thresholdregister1"/>
|
||||
<channel-group typeId="thresholdregisters2" id="thresholdregister2"/>
|
||||
@ -39,6 +41,7 @@
|
||||
<channel-group typeId="keyslocktablec" id="keylocktablec"/>
|
||||
<channel-group typeId="keyslocktabled" id="keylocktabled"/>
|
||||
<channel-group typeId="codes" id="code"/>
|
||||
<channel-group typeId="operatinghourscounters" id="operatinghourscounter"/>
|
||||
<channel-group typeId="hostcommands" id="hostcommand"/>
|
||||
</channel-groups>
|
||||
<properties>
|
||||
@ -91,6 +94,19 @@
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="tunablewhite">
|
||||
<item-type>String</item-type>
|
||||
<label>Tunable White Mode</label>
|
||||
<state>
|
||||
<options>
|
||||
<option value="DISABLE">Tunable White Disabled</option>
|
||||
<option value="OUTPUT1">Control Output 1 (Output 2 is auto)</option>
|
||||
<option value="BOTH">Output 1 Brightness/Output 2 Temperature</option>
|
||||
</options>
|
||||
</state>
|
||||
<autoUpdatePolicy>recommend</autoUpdatePolicy><!-- There's no status message in LCN -->
|
||||
</channel-type>
|
||||
|
||||
<channel-group-type id="outputs">
|
||||
<label>Dimmer Outputs</label>
|
||||
<channels>
|
||||
@ -109,6 +125,7 @@
|
||||
<channel typeId="color" id="color">
|
||||
<label>RGB Color Control (Outputs 1-3)</label>
|
||||
</channel>
|
||||
<channel typeId="tunablewhite" id="tunablewhite"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
@ -151,7 +168,7 @@
|
||||
<channel-type id="rollershutter">
|
||||
<item-type>Rollershutter</item-type>
|
||||
<label>Roller Shutter</label>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy>
|
||||
<autoUpdatePolicy>veto</autoUpdatePolicy><!-- The position messages come as the shutter moves -->
|
||||
<config-description>
|
||||
<parameter name="invertUpDown" type="boolean">
|
||||
<label>Invert Up/Down</label>
|
||||
@ -163,19 +180,37 @@
|
||||
</channel-type>
|
||||
|
||||
<channel-group-type id="rollershutterrelays">
|
||||
<label>Roller Shutter (Relay)</label>
|
||||
<label>Shutter (Relay)</label>
|
||||
<channels>
|
||||
<channel typeId="rollershutter" id="1">
|
||||
<label>Shutter 1-2</label>
|
||||
<label>Position 1-2</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="2">
|
||||
<label>Shutter 3-4</label>
|
||||
<label>Position 3-4</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="3">
|
||||
<label>Shutter 5-6</label>
|
||||
<label>Position 5-6</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="4">
|
||||
<label>Shutter 7-8</label>
|
||||
<label>Position 7-8</label>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="rollershutterrelayslats">
|
||||
<label>Shutter Slat Angle (Relay)</label>
|
||||
<channels>
|
||||
<channel typeId="rollershutter" id="1">
|
||||
<label>Slat Angle 1-2</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="2">
|
||||
<label>Slat Angle 3-4</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="3">
|
||||
<label>Slat Angle 5-6</label>
|
||||
</channel>
|
||||
<channel typeId="rollershutter" id="4">
|
||||
<label>Slat Angle 7-8</label>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
@ -378,6 +413,30 @@
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="rvarmode" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>RVar Heating/Cooling</label>
|
||||
<state>
|
||||
<options>
|
||||
<option value="HEATING">Heating</option>
|
||||
<option value="COOLING">Cooling</option>
|
||||
</options>
|
||||
</state>
|
||||
<autoUpdatePolicy>recommend</autoUpdatePolicy><!-- There's no status message in LCN -->
|
||||
</channel-type>
|
||||
|
||||
<channel-group-type id="rvarmodes">
|
||||
<label>RVar Heating/Cooling</label>
|
||||
<channels>
|
||||
<channel typeId="rvarmode" id="1">
|
||||
<label>R1Var Mode</label>
|
||||
</channel>
|
||||
<channel typeId="rvarmode" id="2">
|
||||
<label>R2Var Mode</label>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="rvarlock" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>RVar Lock State</label>
|
||||
@ -664,6 +723,90 @@
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="operatinghourscounters">
|
||||
<label>Operating Hours Counters</label>
|
||||
<channels>
|
||||
<channel typeId="operatinghourscounter" id="output1">
|
||||
<label>Output 1</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="output2">
|
||||
<label>Output 2</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="output3">
|
||||
<label>Output 3</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="output4">
|
||||
<label>Output 4</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay1">
|
||||
<label>Relay 1</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay2">
|
||||
<label>Relay 2</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay3">
|
||||
<label>Relay 3</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay4">
|
||||
<label>Relay 4</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay5">
|
||||
<label>Relay 5</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay6">
|
||||
<label>Relay 6</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay7">
|
||||
<label>Relay 7</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="relay8">
|
||||
<label>Relay 8</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor1">
|
||||
<label>Binary Sensor 1</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor2">
|
||||
<label>Binary Sensor 2</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor3">
|
||||
<label>Binary Sensor 3</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor4">
|
||||
<label>Binary Sensor 4</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor5">
|
||||
<label>Binary Sensor 5</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor6">
|
||||
<label>Binary Sensor 6</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor7">
|
||||
<label>Binary Sensor 7</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="binarysensor8">
|
||||
<label>Binary Sensor 8</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="outputrelativework1">
|
||||
<label>Output 1 Relative Work</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="outputrelativework2">
|
||||
<label>Output 2 Relative Work</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="outputrelativework3">
|
||||
<label>Output 3 Relative Work</label>
|
||||
</channel>
|
||||
<channel typeId="operatinghourscounter" id="outputrelativework4">
|
||||
<label>Output 4 Relative Work</label>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="operatinghourscounter" advanced="true">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Operating Hours Counter</label>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="sendKeys" advanced="true">
|
||||
<kind>trigger</kind>
|
||||
<label>Send Keys</label>
|
||||
|
||||
@ -200,4 +200,44 @@ public class ModuleActionsTest {
|
||||
|
||||
verify(handler).sendPck("TS---L00100000");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeepNull() throws LcnException {
|
||||
a.beep(null, null, null);
|
||||
|
||||
verify(handler).sendPck("PIN1");
|
||||
verify(handler, times(1)).sendPck(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeepSpecial() throws LcnException {
|
||||
a.beep(null, "S", 5);
|
||||
|
||||
verify(handler).sendPck("PIS5");
|
||||
verify(handler, times(1)).sendPck(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeepVolume() throws LcnException {
|
||||
a.beep(50d, "3", 5);
|
||||
|
||||
verify(handler).sendPck("PIV050");
|
||||
verify(handler).sendPck("PI35");
|
||||
verify(handler, times(2)).sendPck(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeepInvalidVolume() throws LcnException {
|
||||
a.beep(-1d, "3", 5);
|
||||
|
||||
verify(handler, times(0)).sendPck(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeepInvalidTonality() throws LcnException {
|
||||
a.beep(null, "X", 5);
|
||||
|
||||
verify(handler).sendPck("PIN5");
|
||||
verify(handler, times(1)).sendPck(anyString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -19,6 +20,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StopMoveType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
@ -28,15 +30,16 @@ import org.openhab.core.library.types.UpDownType;
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelaySubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) LcnModuleRollershutterRelaySubHandler l;
|
||||
public class AbstractLcnModuleRollershutterRelaySubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) AbstractLcnModuleRollershutterRelaySubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleRollershutterRelaySubHandler(handler, info);
|
||||
l = new AbstractLcnModuleRollershutterRelaySubHandler(handler, info) {
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -98,4 +101,32 @@ public class LcnModuleRollershutterRelaySubHandlerTest extends AbstractTestLcnMo
|
||||
l.handleCommandStopMove(StopMoveType.MOVE, LcnChannelGroup.ROLLERSHUTTERRELAY, 3);
|
||||
verify(handler).sendPck("R8------1-");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShutter1Percent0Position() {
|
||||
tryParseAllHandlers(":M000005P1000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "1", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShutter4Percent100Position() {
|
||||
tryParseAllHandlers(":M000005P4100");
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "4", new PercentType(100));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShutter1Percent0Angle() {
|
||||
tryParseAllHandlers(":M000005W1000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, "1", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShutter4Percent100Angle() {
|
||||
tryParseAllHandlers(":M000005W4100");
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, "4", new PercentType(100));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,9 @@ package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
@ -35,8 +38,35 @@ public class AbstractTestLcnModuleSubHandler {
|
||||
|
||||
protected @Mock @NonNullByDefault({}) LcnModuleHandler handler;
|
||||
protected @Mock @NonNullByDefault({}) ModInfo info;
|
||||
private @NonNullByDefault({}) Collection<AbstractLcnModuleSubHandler> allHandlers;
|
||||
|
||||
public void setUp() {
|
||||
when(handler.isMyAddress("000", "005")).thenReturn(true);
|
||||
|
||||
allHandlers = new ArrayList<>();
|
||||
allHandlers.add(new LcnModuleBinarySensorSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleCodeSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleHostCommandSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleKeyLockTableSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleLedSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleLogicSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleMetaAckSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleMetaFirmwareSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleOperatingHoursCounterSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleOutputSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleRelaySubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleRollershutterOutputSubHandler(handler, info));
|
||||
allHandlers.add(new AbstractLcnModuleRollershutterRelaySubHandler(handler, info) {
|
||||
});
|
||||
allHandlers.add(new LcnModuleRvarLockSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleRvarModeSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleRvarSetpointSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleS0CounterSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleThresholdSubHandler(handler, info));
|
||||
allHandlers.add(new LcnModuleVariableSubHandler(handler, info));
|
||||
}
|
||||
|
||||
protected void tryParseAllHandlers(String pck) {
|
||||
allHandlers.forEach(h -> h.tryParse(pck));
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -27,19 +28,15 @@ import org.openhab.core.library.types.OpenClosedType;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleBinarySensorSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) LcnModuleBinarySensorSubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleBinarySensorSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusAllClosed() {
|
||||
l.tryParse("=M000005Bx000");
|
||||
tryParseAllHandlers("=M000005Bx000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "1", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "2", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "3", OpenClosedType.CLOSED);
|
||||
@ -48,11 +45,12 @@ public class LcnModuleBinarySensorSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "6", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "7", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "8", OpenClosedType.CLOSED);
|
||||
verify(handler, times(8)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusAllOpen() {
|
||||
l.tryParse("=M000005Bx255");
|
||||
tryParseAllHandlers("=M000005Bx255");
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "1", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "2", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "3", OpenClosedType.OPEN);
|
||||
@ -60,11 +58,12 @@ public class LcnModuleBinarySensorSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "6", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "7", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "8", OpenClosedType.OPEN);
|
||||
verify(handler, times(8)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatus1And7Closed() {
|
||||
l.tryParse("=M000005Bx065");
|
||||
tryParseAllHandlers("=M000005Bx065");
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "1", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "2", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "3", OpenClosedType.CLOSED);
|
||||
@ -73,5 +72,6 @@ public class LcnModuleBinarySensorSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "6", OpenClosedType.CLOSED);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "7", OpenClosedType.OPEN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.BINARYSENSOR, "8", OpenClosedType.CLOSED);
|
||||
verify(handler, times(8)).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -26,48 +27,49 @@ import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleHostCommandSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) LcnModuleHostCommandSubHandler subHandler;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
subHandler = new LcnModuleHostCommandSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testA1Hit() {
|
||||
subHandler.tryParse("+M004000005.STH065001");
|
||||
tryParseAllHandlers("+M004000005.STH065001");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "A1:HIT");
|
||||
verify(handler).triggerChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testA1Make() {
|
||||
subHandler.tryParse("+M004000005.STH066001");
|
||||
tryParseAllHandlers("+M004000005.STH066001");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "A1:MAKE");
|
||||
verify(handler).triggerChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testC8Break() {
|
||||
subHandler.tryParse("+M004000005.STH112128");
|
||||
tryParseAllHandlers("+M004000005.STH112128");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "C8:BREAK");
|
||||
verify(handler).triggerChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testC1Hit() {
|
||||
subHandler.tryParse("+M004000005.STH080001");
|
||||
tryParseAllHandlers("+M004000005.STH080001");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "C1:HIT");
|
||||
verify(handler).triggerChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiple() {
|
||||
subHandler.tryParse("+M004000005.STH121034");
|
||||
tryParseAllHandlers("+M004000005.STH121034");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "A2:HIT");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "A6:HIT");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "B2:MAKE");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "B6:MAKE");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "C2:BREAK");
|
||||
verify(handler).triggerChannel(LcnChannelGroup.HOSTCOMMAND, "sendKeys", "C6:BREAK");
|
||||
verify(handler, times(6)).triggerChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -40,7 +41,7 @@ public class LcnModuleKeyLockTableSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
|
||||
@Test
|
||||
public void testStatus() {
|
||||
l.tryParse("=M000005.TX098036000255");
|
||||
tryParseAllHandlers("=M000005.TX098036000255");
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLEA, "1", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLEA, "2", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLEA, "3", OnOffType.OFF);
|
||||
@ -73,6 +74,7 @@ public class LcnModuleKeyLockTableSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLED, "6", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLED, "7", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.KEYLOCKTABLED, "8", OnOffType.ON);
|
||||
verify(handler, times(32)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -34,19 +35,16 @@ public class LcnModuleLogicSubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
private static final StringType NOT = new StringType("NOT");
|
||||
private static final StringType OR = new StringType("OR");
|
||||
private static final StringType AND = new StringType("AND");
|
||||
private @NonNullByDefault({}) LcnModuleLogicSubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleLogicSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusLedOffLogicNot() {
|
||||
l.tryParse("=M000005.TLAAAAAAAAAAAANNNN");
|
||||
tryParseAllHandlers("=M000005.TLAAAAAAAAAAAANNNN");
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "1", OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "2", OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "3", OFF);
|
||||
@ -63,11 +61,12 @@ public class LcnModuleLogicSubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "2", NOT);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "3", NOT);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "4", NOT);
|
||||
verify(handler, times(16)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusMixed() {
|
||||
l.tryParse("=M000005.TLAEBFAAAAAAAFNVNT");
|
||||
tryParseAllHandlers("=M000005.TLAEBFAAAAAAAFNVNT");
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "1", OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "2", ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LED, "3", BLINK);
|
||||
@ -84,23 +83,27 @@ public class LcnModuleLogicSubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "2", AND);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "3", NOT);
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "4", OR);
|
||||
verify(handler, times(16)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusSingleLogic1Not() {
|
||||
l.tryParse("=M000005S1000");
|
||||
tryParseAllHandlers("=M000005S1000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "1", NOT);
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusSingleLogic4Or() {
|
||||
l.tryParse("=M000005S4025");
|
||||
tryParseAllHandlers("=M000005S4025");
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "4", OR);
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusSingleLogic3And() {
|
||||
l.tryParse("=M000005S3050");
|
||||
tryParseAllHandlers("=M000005S3050");
|
||||
verify(handler).updateChannel(LcnChannelGroup.LOGIC, "3", AND);
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleOperatingHoursCounterSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1Duration0() {
|
||||
tryParseAllHandlers("$M000005A10000000000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "output1", QuantityType.valueOf(0, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1Duration9999999999() {
|
||||
tryParseAllHandlers("$M000005A49999999999");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "output4",
|
||||
QuantityType.valueOf(9999999999L, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutputRelativeWork1Duration0() {
|
||||
tryParseAllHandlers("$M000005I10000000000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "outputrelativework1",
|
||||
QuantityType.valueOf(0, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutputRelativeWork1Duration9999999999() {
|
||||
tryParseAllHandlers("$M000005I49999999999");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "outputrelativework4",
|
||||
QuantityType.valueOf(9999999999L, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusRelay1Duration0() {
|
||||
tryParseAllHandlers("$M000005R10000000000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "relay1", QuantityType.valueOf(0, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusRelay1Duration9999999999() {
|
||||
tryParseAllHandlers("$M000005R49999999999");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "relay4",
|
||||
QuantityType.valueOf(9999999999L, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusBinarySensor1Duration0() {
|
||||
tryParseAllHandlers("$M000005B10000000000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "binarysensor1",
|
||||
QuantityType.valueOf(0, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusBinarySensor1Duration9999999999() {
|
||||
tryParseAllHandlers("$M000005B49999999999");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OPERATINGHOURS, "binarysensor4",
|
||||
QuantityType.valueOf(9999999999L, Units.SECOND));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@ -25,6 +26,8 @@ import org.openhab.binding.lcn.internal.common.LcnDefs;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
@ -45,62 +48,78 @@ public class LcnModuleOutputSubHandlerTest extends AbstractTestLcnModuleSubHandl
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1OffPercent() {
|
||||
l.tryParse("=M000005A1000");
|
||||
tryParseAllHandlers(":M000005A1000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "1", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput2OffPercent() {
|
||||
l.tryParse("=M000005A2000");
|
||||
tryParseAllHandlers(":M000005A2000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "2", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1OffNative() {
|
||||
l.tryParse("=M000005O1000");
|
||||
tryParseAllHandlers(":M000005O1000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "1", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput2OffNative() {
|
||||
l.tryParse("=M000005O2000");
|
||||
tryParseAllHandlers(":M000005O2000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "2", new PercentType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1OnPercent() {
|
||||
l.tryParse("=M000005A1100");
|
||||
tryParseAllHandlers(":M000005A1100");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "1", new PercentType(100));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.UP);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput2OnPercent() {
|
||||
l.tryParse("=M000005A2100");
|
||||
tryParseAllHandlers(":M000005A2100");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "2", new PercentType(100));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.DOWN);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1OnNative() {
|
||||
l.tryParse("=M000005O1200");
|
||||
tryParseAllHandlers(":M000005O1200");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "1", new PercentType(100));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.UP);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput2OnNative() {
|
||||
l.tryParse("=M000005O2200");
|
||||
tryParseAllHandlers(":M000005O2200");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "2", new PercentType(100));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.DOWN);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput2On50Percent() {
|
||||
l.tryParse("=M000005A2050");
|
||||
tryParseAllHandlers(":M000005A2050");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "2", new PercentType(50));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.DOWN);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusOutput1On50Native() {
|
||||
l.tryParse("=M000005O1100");
|
||||
tryParseAllHandlers(":M000005O1100");
|
||||
verify(handler).updateChannel(LcnChannelGroup.OUTPUT, "1", new PercentType(50));
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTEROUTPUT, "1", UpDownType.UP);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -195,4 +214,22 @@ public class LcnModuleOutputSubHandlerTest extends AbstractTestLcnModuleSubHandl
|
||||
l.handleCommandDimmerOutput(new DimmerOutputCommand(BigDecimal.valueOf(40), false, true, 0), 0);
|
||||
verify(handler).sendPck("AY040040");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandTuneableWhite0() throws LcnException {
|
||||
l.handleCommandString(new StringType("DISABLE"), 0);
|
||||
verify(handler).sendPck("AW0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandTuneableWhite1() throws LcnException {
|
||||
l.handleCommandString(new StringType("OUTPUT1"), 0);
|
||||
verify(handler).sendPck("AW1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandTuneableWhite2() throws LcnException {
|
||||
l.handleCommandString(new StringType("BOTH"), 0);
|
||||
verify(handler).sendPck("AW2");
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -21,6 +22,7 @@ import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
@ -41,7 +43,7 @@ public class LcnModuleRelaySubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
|
||||
@Test
|
||||
public void testStatusAllOff() {
|
||||
l.tryParse("=M000005Rx000");
|
||||
tryParseAllHandlers("=M000005Rx000");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "1", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "2", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "3", OnOffType.OFF);
|
||||
@ -50,11 +52,16 @@ public class LcnModuleRelaySubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "6", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "7", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "8", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "1", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "2", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "3", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "4", UpDownType.UP);
|
||||
verify(handler, times(12)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusAllOn() {
|
||||
l.tryParse("=M000005Rx255");
|
||||
tryParseAllHandlers("=M000005Rx255");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "1", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "2", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "3", OnOffType.ON);
|
||||
@ -62,11 +69,16 @@ public class LcnModuleRelaySubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "6", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "7", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "8", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "1", UpDownType.DOWN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "2", UpDownType.DOWN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "3", UpDownType.DOWN);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "4", UpDownType.DOWN);
|
||||
verify(handler, times(12)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusRelay1Relay7On() {
|
||||
l.tryParse("=M000005Rx065");
|
||||
tryParseAllHandlers("=M000005Rx065");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "1", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "2", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "3", OnOffType.OFF);
|
||||
@ -75,6 +87,11 @@ public class LcnModuleRelaySubHandlerTest extends AbstractTestLcnModuleSubHandle
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "6", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "7", OnOffType.ON);
|
||||
verify(handler).updateChannel(LcnChannelGroup.RELAY, "8", OnOffType.OFF);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "1", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "2", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "3", UpDownType.UP);
|
||||
verify(handler).updateChannel(LcnChannelGroup.ROLLERSHUTTERRELAY, "4", UpDownType.UP);
|
||||
verify(handler, times(12)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.binding.lcn.internal.common.PckGenerator;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelayPositionSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) AbstractLcnModuleRollershutterRelaySubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleRollershutterRelayPositionSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent0() throws LcnException {
|
||||
l.handleCommandPercent(PercentType.ZERO, LcnChannelGroup.ROLLERSHUTTERRELAY, 0);
|
||||
verify(handler).sendPck("JH000001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent100() throws LcnException {
|
||||
l.handleCommandPercent(PercentType.HUNDRED, LcnChannelGroup.ROLLERSHUTTERRELAY, 0);
|
||||
verify(handler).sendPck("JH100001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent50() throws LcnException {
|
||||
l.handleCommandPercent(new PercentType(50), LcnChannelGroup.ROLLERSHUTTERRELAY, 0);
|
||||
verify(handler).sendPck("JH050001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor4percent50() throws LcnException {
|
||||
l.handleCommandPercent(new PercentType(50), LcnChannelGroup.ROLLERSHUTTERRELAY, 3);
|
||||
verify(handler).sendPck("JH050008");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidMotor() throws LcnException {
|
||||
assertThrows(LcnException.class, () -> {
|
||||
l.handleCommandPercent(new PercentType(50), LcnChannelGroup.ROLLERSHUTTERRELAY, 4);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidPercent() throws LcnException {
|
||||
assertThrows(LcnException.class, () -> {
|
||||
PckGenerator.controlShutterPosition(0, 101);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.lcn.internal.common.LcnChannelGroup;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRollershutterRelaySlatAngleSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) AbstractLcnModuleRollershutterRelaySubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleRollershutterRelaySlatAngleSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent0() throws LcnException {
|
||||
l.handleCommandPercent(PercentType.ZERO, LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, 0);
|
||||
verify(handler).sendPck("JW000001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent100() throws LcnException {
|
||||
l.handleCommandPercent(PercentType.HUNDRED, LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, 0);
|
||||
verify(handler).sendPck("JW100001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor1percent50() throws LcnException {
|
||||
l.handleCommandPercent(new PercentType(50), LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, 0);
|
||||
verify(handler).sendPck("JW050001");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMotor4percent50() throws LcnException {
|
||||
l.handleCommandPercent(new PercentType(50), LcnChannelGroup.ROLLERSHUTTERRELAYSLAT, 3);
|
||||
verify(handler).sendPck("JW050008");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.subhandler;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.lcn.internal.common.LcnException;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
|
||||
/**
|
||||
* Test class.
|
||||
*
|
||||
* @author Fabian Wolter - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleRvarModeSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) LcnModuleRvarModeSubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleRvarModeSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testhandleCommand1Cooling() throws LcnException {
|
||||
l.handleCommandString(new StringType("COOLING"), 0);
|
||||
verify(handler).sendPck("REATC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testhandleCommand1Heating() throws LcnException {
|
||||
l.handleCommandString(new StringType("HEATING"), 0);
|
||||
verify(handler).sendPck("REATH");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testhandleCommand2Cooling() throws LcnException {
|
||||
l.handleCommandString(new StringType("COOLING"), 1);
|
||||
verify(handler).sendPck("REBTC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testhandleCommand2Heating() throws LcnException {
|
||||
l.handleCommandString(new StringType("HEATING"), 1);
|
||||
verify(handler).sendPck("REBTH");
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -103,36 +104,41 @@ public class LcnModuleRvarSetpointSubHandlerTest extends AbstractTestLcnModuleSu
|
||||
|
||||
@Test
|
||||
public void testRvar1() {
|
||||
l.tryParse("=M000005.S11234");
|
||||
tryParseAllHandlers("=M000005.S11234");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARSETPOINT, "1", new DecimalType(1234));
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARLOCK, "1", OnOffType.OFF);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRvar2() {
|
||||
l.tryParse("=M000005.S21234");
|
||||
tryParseAllHandlers("=M000005.S21234");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARSETPOINT, "2", new DecimalType(1234));
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARLOCK, "2", OnOffType.OFF);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRvar1SensorDefective() {
|
||||
l.tryParse("=M000005.S132512");
|
||||
tryParseAllHandlers("=M000005.S132512");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARSETPOINT, "1", new StringType("DEFECTIVE"));
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARLOCK, "1", OnOffType.OFF);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRvar1Locked() {
|
||||
l.tryParse("=M000005.S134002");
|
||||
tryParseAllHandlers("=M000005.S134002");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARSETPOINT, "1", new DecimalType(1234));
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARLOCK, "1", OnOffType.ON);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRvar2Locked() {
|
||||
l.tryParse("=M000005.S234002");
|
||||
tryParseAllHandlers("=M000005.S234002");
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARSETPOINT, "2", new DecimalType(1234));
|
||||
verify(handler).updateChannel(LcnChannelGroup.RVARLOCK, "2", OnOffType.ON);
|
||||
verify(handler, times(2)).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -27,31 +28,30 @@ import org.openhab.core.library.types.DecimalType;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LcnModuleS0CounterSubHandlerTest extends AbstractTestLcnModuleSubHandler {
|
||||
private @NonNullByDefault({}) LcnModuleS0CounterSubHandler l;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
|
||||
l = new LcnModuleS0CounterSubHandler(handler, info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZero() {
|
||||
l.tryParse("=M000005.C10");
|
||||
tryParseAllHandlers("=M000005.C10");
|
||||
verify(handler).updateChannel(LcnChannelGroup.S0INPUT, "1", new DecimalType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxValue() {
|
||||
l.tryParse("=M000005.C14294967295");
|
||||
tryParseAllHandlers("=M000005.C14294967295");
|
||||
verify(handler).updateChannel(LcnChannelGroup.S0INPUT, "1", new DecimalType(4294967295L));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
l.tryParse("=M000005.C412345");
|
||||
tryParseAllHandlers("=M000005.C412345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.S0INPUT, "4", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -41,30 +42,34 @@ public class LcnModuleThresholdSubHandlerTest extends AbstractTestLcnModuleSubHa
|
||||
|
||||
@Test
|
||||
public void testThreshold11() {
|
||||
l.tryParse("=M000005.T1112345");
|
||||
tryParseAllHandlers("=M000005.T1112345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "1", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreshold14() {
|
||||
l.tryParse("=M000005.T140");
|
||||
tryParseAllHandlers("=M000005.T140");
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "4", new DecimalType(0));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreshold41() {
|
||||
l.tryParse("=M000005.T4112345");
|
||||
tryParseAllHandlers("=M000005.T4112345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER4, "1", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThresholdLegacy() {
|
||||
l.tryParse("=M000005.S1123451123411123000000000112345");
|
||||
tryParseAllHandlers("=M000005.S1123451123411123000000000112345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "1", new DecimalType(12345));
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "2", new DecimalType(11234));
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "3", new DecimalType(11123));
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "4", new DecimalType(0));
|
||||
verify(handler).updateChannel(LcnChannelGroup.THRESHOLDREGISTER1, "5", new DecimalType(1));
|
||||
verify(handler, times(5)).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.lcn.internal.subhandler;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -42,21 +43,24 @@ public class LcnModuleVariableSubHandlerTest extends AbstractTestLcnModuleSubHan
|
||||
|
||||
@Test
|
||||
public void testStatusVariable1() {
|
||||
l.tryParse("=M000005.A00112345");
|
||||
tryParseAllHandlers("=M000005.A00112345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.VARIABLE, "1", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusVariable12() {
|
||||
l.tryParse("=M000005.A01212345");
|
||||
tryParseAllHandlers("=M000005.A01212345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.VARIABLE, "12", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusLegacyVariable3() {
|
||||
when(info.getLastRequestedVarWithoutTypeInResponse()).thenReturn(Variable.VARIABLE3);
|
||||
l.tryParse("=M000005.12345");
|
||||
tryParseAllHandlers("=M000005.12345");
|
||||
verify(handler).updateChannel(LcnChannelGroup.VARIABLE, "3", new DecimalType(12345));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,13 +81,15 @@ public class LcnModuleVariableSubHandlerTest extends AbstractTestLcnModuleSubHan
|
||||
|
||||
@Test
|
||||
public void testStatusVariable10SensorDefective() {
|
||||
l.tryParse("=M000005.A01032512");
|
||||
tryParseAllHandlers("=M000005.A01032512");
|
||||
verify(handler).updateChannel(LcnChannelGroup.VARIABLE, "10", new StringType("DEFECTIVE"));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusVariable8NotConfigured() {
|
||||
l.tryParse("=M000005.A00865535");
|
||||
tryParseAllHandlers("=M000005.A00865535");
|
||||
verify(handler).updateChannel(LcnChannelGroup.VARIABLE, "8", new StringType("Not configured in LCN-PRO"));
|
||||
verify(handler).updateChannel(any(), any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user