From e59fc5f735d09dc9a713b8e57c446ee45a9b56d4 Mon Sep 17 00:00:00 2001 From: Wouter Born Date: Thu, 14 May 2020 10:57:13 +0200 Subject: [PATCH] [nibeheatpump] Use serial transport Related to #7573 Signed-off-by: Wouter Born --- .../org.openhab.binding.nibeheatpump/pom.xml | 4 -- .../internal/NibeHeatPumpHandlerFactory.java | 17 ++++++- .../internal/connection/ConnectorFactory.java | 45 ------------------- .../internal/connection/SerialConnector.java | 30 +++++++------ .../connection/SimulatorConnector.java | 2 +- .../internal/handler/NibeHeatPumpHandler.java | 32 +++++++++++-- .../NibeHeatPumpHandlerCommand2NibeTest.java | 13 ++++-- .../NibeHeatPumpHandlerNibe2StateTest.java | 9 +++- 8 files changed, 78 insertions(+), 74 deletions(-) delete mode 100644 bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java diff --git a/bundles/org.openhab.binding.nibeheatpump/pom.xml b/bundles/org.openhab.binding.nibeheatpump/pom.xml index e6d687b88b857..0e1bdd43531bd 100644 --- a/bundles/org.openhab.binding.nibeheatpump/pom.xml +++ b/bundles/org.openhab.binding.nibeheatpump/pom.xml @@ -14,8 +14,4 @@ openHAB Add-ons :: Bundles :: Nibe Heatpump Binding - - gnu.io;version="[3.12,6)" - - diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java index 4215cf23eb486..960769853e5fc 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java @@ -14,14 +14,19 @@ import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.SUPPORTED_THING_TYPES_UIDS; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.nibeheatpump.internal.handler.NibeHeatPumpHandler; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link NibeHeatPumpHandlerFactory} is responsible for creating things and @@ -29,20 +34,28 @@ * * @author Pauli Anttila - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.nibeheatpump") public class NibeHeatPumpHandlerFactory extends BaseThingHandlerFactory { + private final SerialPortManager serialPortManager; + + @Activate + public NibeHeatPumpHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { - return new NibeHeatPumpHandler(thing, parsePumpModel(thing)); + return new NibeHeatPumpHandler(thing, parsePumpModel(thing), serialPortManager); } return null; diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java deleted file mode 100644 index 1b0e2bc49ee98..0000000000000 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeheatpump.internal.connection; - -import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.*; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; - -/** - * The {@link ConnectorFactory} implements factory class to create Nibe connectors. - * - * - * @author Pauli Anttila - Initial contribution - */ -public class ConnectorFactory { - - public static NibeHeatPumpConnector getConnector(ThingTypeUID type) throws NibeHeatPumpException { - if (type != null) { - if (THING_TYPE_F1X45_UDP.equals(type) || THING_TYPE_F1X55_UDP.equals(type) - || THING_TYPE_F750_UDP.equals(type) || THING_TYPE_F470_UDP.equals(type)) { - return new UDPConnector(); - } else if (THING_TYPE_F1X45_SERIAL.equals(type) || THING_TYPE_F1X55_SERIAL.equals(type) - || THING_TYPE_F750_SERIAL.equals(type) || THING_TYPE_F470_SERIAL.equals(type)) { - return new SerialConnector(); - } else if (THING_TYPE_F1X45_SIMULATOR.equals(type) || THING_TYPE_F1X55_SIMULATOR.equals(type) - || THING_TYPE_F750_SIMULATOR.equals(type) || THING_TYPE_F470_SIMULATOR.equals(type)) { - return new SimulatorConnector(); - } - } - - String description = String.format("Unknown connector type %s", type); - throw new NibeHeatPumpException(description); - } -} diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java index e9da07f984b5e..d0de047b2514d 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java @@ -23,6 +23,13 @@ import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.util.HexUtils; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration; import org.openhab.binding.nibeheatpump.internal.message.MessageFactory; @@ -35,14 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * Connector for serial port communication. * @@ -55,14 +54,16 @@ public class SerialConnector extends NibeHeatPumpBaseConnector { private InputStream in; private OutputStream out; private SerialPort serialPort; + private final SerialPortManager serialPortManager; private Thread readerThread; private NibeHeatPumpConfiguration conf; private final List readQueue = new ArrayList<>(); private final List writeQueue = new ArrayList<>(); - SerialConnector() { + public SerialConnector(SerialPortManager serialPortManager) { logger.debug("Nibe heatpump Serial Port message listener created"); + this.serialPortManager = serialPortManager; } @Override @@ -73,7 +74,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump conf = configuration; try { - CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(conf.serialPort); + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(conf.serialPort); + if (portIdentifier == null) { + throw new NibeHeatPumpException("Connection failed, no such port: " + conf.serialPort); + } serialPort = portIdentifier.open(this.getClass().getName(), 2000); serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); @@ -88,12 +92,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump if (in.markSupported()) { in.reset(); } - } catch (NoSuchPortException e) { - throw new NibeHeatPumpException("Connection failed, no such a port", e); } catch (PortInUseException e) { - throw new NibeHeatPumpException("Connection failed, port in use", e); + throw new NibeHeatPumpException("Connection failed, port in use: " + conf.serialPort, e); } catch (UnsupportedCommOperationException | IOException e) { - throw new NibeHeatPumpException("Connection failed, reason: {}" + e.getMessage(), e); + throw new NibeHeatPumpException("Connection failed, reason: " + e.getMessage(), e); } readQueue.clear(); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java index 0e5eb21646d36..6fa3888165c16 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java @@ -75,7 +75,7 @@ public class SimulatorConnector extends NibeHeatPumpBaseConnector { private final Map cache = Collections.synchronizedMap(new HashMap<>()); - SimulatorConnector() { + public SimulatorConnector() { logger.debug("Nibe heatpump Test message listener created"); } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java index 14a6536c54e61..5baf99014200d 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.nibeheatpump.internal.handler; +import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.*; + import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; @@ -34,17 +36,21 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpCommandResult; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration; -import org.openhab.binding.nibeheatpump.internal.connection.ConnectorFactory; import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpConnector; import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpEventListener; +import org.openhab.binding.nibeheatpump.internal.connection.SerialConnector; +import org.openhab.binding.nibeheatpump.internal.connection.SimulatorConnector; +import org.openhab.binding.nibeheatpump.internal.connection.UDPConnector; import org.openhab.binding.nibeheatpump.internal.message.ModbusDataReadOutMessage; import org.openhab.binding.nibeheatpump.internal.message.ModbusReadRequestMessage; import org.openhab.binding.nibeheatpump.internal.message.ModbusReadResponseMessage; @@ -70,6 +76,7 @@ public class NibeHeatPumpHandler extends BaseThingHandler implements NibeHeatPum private static final int TIMEOUT = 4500; private final Logger logger = LoggerFactory.getLogger(NibeHeatPumpHandler.class); private final PumpModel pumpModel; + private final SerialPortManager serialPortManager; private final List itemsToPoll = Collections.synchronizedList(new ArrayList<>()); private final List itemsToEnableWrite = new ArrayList<>(); private final Map stateMap = Collections.synchronizedMap(new HashMap<>()); @@ -135,9 +142,28 @@ && getThing().getStatusInfo().getStatus() == ThingStatus.ONLINE) { private ScheduledFuture pollingJob; private long lastUpdateTime = 0; - public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel) { + public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel, SerialPortManager serialPortManager) { super(thing); this.pumpModel = pumpModel; + this.serialPortManager = serialPortManager; + } + + private NibeHeatPumpConnector getConnector() throws NibeHeatPumpException { + ThingTypeUID type = thing.getThingTypeUID(); + + if (THING_TYPE_F1X45_UDP.equals(type) || THING_TYPE_F1X55_UDP.equals(type) || THING_TYPE_F750_UDP.equals(type) + || THING_TYPE_F470_UDP.equals(type)) { + return new UDPConnector(); + } else if (THING_TYPE_F1X45_SERIAL.equals(type) || THING_TYPE_F1X55_SERIAL.equals(type) + || THING_TYPE_F750_SERIAL.equals(type) || THING_TYPE_F470_SERIAL.equals(type)) { + return new SerialConnector(serialPortManager); + } else if (THING_TYPE_F1X45_SIMULATOR.equals(type) || THING_TYPE_F1X55_SIMULATOR.equals(type) + || THING_TYPE_F750_SIMULATOR.equals(type) || THING_TYPE_F470_SIMULATOR.equals(type)) { + return new SimulatorConnector(); + } + + String description = String.format("Unknown connector type %s", type); + throw new NibeHeatPumpException(description); } @Override @@ -260,7 +286,7 @@ public void initialize() { try { parseWriteEnabledItems(); - connector = ConnectorFactory.getConnector(thing.getThingTypeUID()); + connector = getConnector(); } catch (IllegalArgumentException | NibeHeatPumpException e) { String description = String.format("Illegal configuration, %s", e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java index 3fe3766b18d31..2473a85614d4c 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java @@ -13,6 +13,7 @@ package org.openhab.binding.nibeheatpump.internal.handler; import static org.junit.Assert.assertEquals; +import static org.mockito.MockitoAnnotations.initMocks; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -23,10 +24,12 @@ import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.Mock; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; import org.openhab.binding.nibeheatpump.internal.models.VariableInformation; @@ -40,15 +43,15 @@ public class NibeHeatPumpHandlerCommand2NibeTest { private NibeHeatPumpHandler product; // the class under test private Method m; private static String METHOD_NAME = "convertCommandToNibeValue"; - private Class[] parameterTypes; + private Class[] parameterTypes; private Object[] parameters; private int fCoilAddress; - private Command fCommand; - private int fExpected; + private @Mock SerialPortManager serialPortManager; + @Parameterized.Parameters(name = "{index}: f({0}, {1})={2}") public static Collection data() { return Arrays.asList(new Object[][] { { 47028, new DecimalType("-1"), (byte) 0xFF }, @@ -68,7 +71,9 @@ public NibeHeatPumpHandlerCommand2NibeTest(final int coilAddress, final Command @Before public void setUp() throws Exception { - product = new NibeHeatPumpHandler(null, PumpModel.F1X55); + initMocks(this); + + product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager); parameterTypes = new Class[2]; parameterTypes[0] = VariableInformation.class; parameterTypes[1] = Command.class; diff --git a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java index f40efb7f0dc53..03dd6129ee5fb 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java @@ -13,6 +13,7 @@ package org.openhab.binding.nibeheatpump.internal.handler; import static org.junit.Assert.assertEquals; +import static org.mockito.MockitoAnnotations.initMocks; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -21,10 +22,12 @@ import java.util.Collection; import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.Mock; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; import org.openhab.binding.nibeheatpump.internal.models.VariableInformation; @@ -50,6 +53,8 @@ public class NibeHeatPumpHandlerNibe2StateTest { private String fType; private String fExpected; + private @Mock SerialPortManager serialPortManager; + @Parameterized.Parameters(name = "{index}: f({0}, {1}, {3})={4}") public static Collection data() { return Arrays.asList(new Object[][] { // @@ -93,7 +98,9 @@ public NibeHeatPumpHandlerNibe2StateTest(final int coilAddress, final int value, @Before public void setUp() throws Exception { - product = new NibeHeatPumpHandler(null, PumpModel.F1X55); + initMocks(this); + + product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager); parameterTypes = new Class[3]; parameterTypes[0] = VariableInformation.class; parameterTypes[1] = int.class;