From 5a8d9ac00896ae79548fc7fdb5a55caa677d7f72 Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Mon, 20 Sep 2021 19:58:26 +0200 Subject: [PATCH] [powermax] Add null annotations Signed-off-by: Laurent Garnier --- .../config/PowermaxIpConfiguration.java | 21 +- .../config/PowermaxSerialConfiguration.java | 19 +- .../config/PowermaxX10Configuration.java | 5 +- .../config/PowermaxZoneConfiguration.java | 5 +- .../internal/connector/PowermaxConnector.java | 54 ++-- .../connector/PowermaxConnectorInterface.java | 2 + .../connector/PowermaxReaderThread.java | 6 +- .../connector/PowermaxSerialConnector.java | 46 +-- .../connector/PowermaxTcpConnector.java | 26 +- .../console/PowermaxCommandExtension.java | 26 +- .../discovery/PowermaxDiscoveryService.java | 4 +- .../handler/PowermaxBridgeHandler.java | 297 ++++++++++-------- .../handler/PowermaxThingHandler.java | 50 +-- .../internal/message/PowermaxAckMessage.java | 8 +- .../internal/message/PowermaxBaseMessage.java | 49 +-- .../internal/message/PowermaxCommManager.java | 78 ++--- .../message/PowermaxDeniedMessage.java | 8 +- .../message/PowermaxDownloadRetryMessage.java | 5 +- .../message/PowermaxEventLogMessage.java | 5 +- .../internal/message/PowermaxInfoMessage.java | 5 +- .../message/PowermaxMessageConstants.java | 3 + .../message/PowermaxMessageEvent.java | 3 + .../message/PowermaxMessageEventListener.java | 3 + .../message/PowermaxPanelMessage.java | 5 +- .../message/PowermaxPowerMasterMessage.java | 5 +- .../message/PowermaxPowerlinkMessage.java | 5 +- .../internal/message/PowermaxReceiveType.java | 3 + .../internal/message/PowermaxSendType.java | 15 +- .../message/PowermaxSettingsMessage.java | 5 +- .../message/PowermaxStatusMessage.java | 5 +- .../message/PowermaxTimeoutMessage.java | 5 +- .../message/PowermaxZonesNameMessage.java | 5 +- .../message/PowermaxZonesTypeMessage.java | 5 +- .../internal/state/PowermasterSensorType.java | 3 + .../internal/state/PowermaxArmMode.java | 3 + .../internal/state/PowermaxPanelSettings.java | 116 ++++--- .../internal/state/PowermaxPanelType.java | 3 + .../internal/state/PowermaxSensorType.java | 3 + .../internal/state/PowermaxState.java | 92 ++++-- .../state/PowermaxStateContainer.java | 23 +- .../internal/state/PowermaxStateEvent.java | 3 + .../state/PowermaxStateEventListener.java | 3 + .../internal/state/PowermaxX10Settings.java | 10 +- .../internal/state/PowermaxZoneName.java | 3 + .../internal/state/PowermaxZoneSettings.java | 29 +- .../internal/state/PowermaxZoneState.java | 9 +- 46 files changed, 661 insertions(+), 425 deletions(-) diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxIpConfiguration.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxIpConfiguration.java index 0c8724e3bcc91..f812759eff1e4 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxIpConfiguration.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxIpConfiguration.java @@ -12,21 +12,24 @@ */ package org.openhab.binding.powermax.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link PowermaxIpConfiguration} is responsible for holding * configuration informations associated to a Powermax IP thing type * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxIpConfiguration { - public String ip; - public Integer tcpPort; - public Integer motionOffDelay; - public Boolean allowArming; - public Boolean allowDisarming; - public String pinCode; - public Boolean forceStandardMode; - public String panelType; - public Boolean autoSyncTime; + public String ip = ""; + public int tcpPort = 0; + public int motionOffDelay = 3; + public boolean allowArming = false; + public boolean allowDisarming = false; + public String pinCode = ""; + public boolean forceStandardMode = false; + public String panelType = "PowerMaxPro"; + public boolean autoSyncTime = false; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxSerialConfiguration.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxSerialConfiguration.java index 6e37f8526db94..6975646a95b8d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxSerialConfiguration.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxSerialConfiguration.java @@ -12,20 +12,23 @@ */ package org.openhab.binding.powermax.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link PowermaxSerialConfiguration} is responsible for holding * configuration informations associated to a Powermax serial thing type * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxSerialConfiguration { - public String serialPort; - public Integer motionOffDelay; - public Boolean allowArming; - public Boolean allowDisarming; - public String pinCode; - public Boolean forceStandardMode; - public String panelType; - public Boolean autoSyncTime; + public String serialPort = ""; + public int motionOffDelay = 3; + public boolean allowArming = false; + public boolean allowDisarming = false; + public String pinCode = ""; + public boolean forceStandardMode = false; + public String panelType = "PowerMaxPro"; + public boolean autoSyncTime = false; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxX10Configuration.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxX10Configuration.java index 61b6fd1edb645..64f1d57893b20 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxX10Configuration.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxX10Configuration.java @@ -12,15 +12,18 @@ */ package org.openhab.binding.powermax.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link PowermaxX10Configuration} is responsible for holding * configuration informations associated to a Powermax IP thing type * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxX10Configuration { public static final String DEVICE_NUMBER = "deviceNumber"; - public Integer deviceNumber; + public int deviceNumber = -1; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxZoneConfiguration.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxZoneConfiguration.java index ac1317cdec16a..a34fd74916539 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxZoneConfiguration.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/config/PowermaxZoneConfiguration.java @@ -12,15 +12,18 @@ */ package org.openhab.binding.powermax.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link PowermaxZoneConfiguration} is responsible for holding * configuration informations associated to a Powermax IP thing type * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxZoneConfiguration { public static final String ZONE_NUMBER = "zoneNumber"; - public Integer zoneNumber; + public int zoneNumber = -1; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnector.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnector.java index 4764c764ad300..d5b56752da27b 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnector.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnector.java @@ -18,6 +18,8 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.message.PowermaxBaseMessage; import org.openhab.binding.powermax.internal.message.PowermaxMessageEvent; import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener; @@ -30,15 +32,16 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public abstract class PowermaxConnector implements PowermaxConnectorInterface { private final Logger logger = LoggerFactory.getLogger(PowermaxConnector.class); - private InputStream input; - private OutputStream output; + private @Nullable InputStream input; + private @Nullable OutputStream output; private boolean connected; protected String readerThreadName; - private Thread readerThread; + private @Nullable Thread readerThread; private long waitingForResponse; private List listeners = new ArrayList<>(); @@ -58,26 +61,29 @@ public PowermaxConnector(String readerThreadName) { protected void cleanup(boolean closeStreams) { logger.debug("cleanup(): cleaning up Connection"); - if (readerThread != null) { - readerThread.interrupt(); + Thread thread = readerThread; + if (thread != null) { + thread.interrupt(); try { - readerThread.join(); + thread.join(); } catch (InterruptedException e) { } } if (closeStreams) { - if (output != null) { + OutputStream out = output; + if (out != null) { try { - output.close(); + out.close(); } catch (IOException e) { logger.debug("Error while closing the output stream: {}", e.getMessage()); } } - if (input != null) { + InputStream in = input; + if (in != null) { try { - input.close(); + in.close(); } catch (IOException e) { logger.debug("Error while closing the input stream: {}", e.getMessage()); } @@ -107,16 +113,20 @@ public void handleIncomingMessage(byte[] incomingMessage) { /** * Handles a communication failure */ - public void handleCommunicationFailure(String message) { + public void handleCommunicationFailure(@Nullable String message) { close(); - listeners.forEach(listener -> listener.onCommunicationFailure(message)); + listeners.forEach(listener -> listener.onCommunicationFailure(message != null ? message : "")); } @Override public void sendMessage(byte[] data) { try { - output.write(data); - output.flush(); + OutputStream out = output; + if (out == null) { + throw new IOException("output stream is undefined"); + } + out.write(data); + out.flush(); } catch (IOException e) { logger.debug("sendMessage(): Writing error: {}", e.getMessage(), e); handleCommunicationFailure(e.getMessage()); @@ -125,7 +135,11 @@ public void sendMessage(byte[] data) { @Override public int read(byte[] buffer) throws IOException { - return input.read(buffer); + InputStream in = input; + if (in == null) { + throw new IOException("input stream is undefined"); + } + return in.read(buffer); } @Override @@ -141,7 +155,7 @@ public void removeEventListener(PowermaxMessageEventListener listener) { /** * @return the input stream */ - public InputStream getInput() { + public @Nullable InputStream getInput() { return input; } @@ -150,14 +164,14 @@ public InputStream getInput() { * * @param input the input stream */ - public void setInput(InputStream input) { + public void setInput(@Nullable InputStream input) { this.input = input; } /** * @return the output stream */ - public OutputStream getOutput() { + public @Nullable OutputStream getOutput() { return output; } @@ -166,7 +180,7 @@ public OutputStream getOutput() { * * @param output the output stream */ - public void setOutput(OutputStream output) { + public void setOutput(@Nullable OutputStream output) { this.output = output; } @@ -190,7 +204,7 @@ public void setConnected(boolean connected) { /** * @return the thread that handles the message reading */ - public Thread getReaderThread() { + public @Nullable Thread getReaderThread() { return readerThread; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnectorInterface.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnectorInterface.java index 9cf3241622fa1..c36f21b58877b 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnectorInterface.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxConnectorInterface.java @@ -14,6 +14,7 @@ import java.io.IOException; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener; /** @@ -21,6 +22,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public interface PowermaxConnectorInterface { /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxReaderThread.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxReaderThread.java index 9eb94870acfaa..8e78790bc864d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxReaderThread.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxReaderThread.java @@ -16,6 +16,7 @@ import java.io.InterruptedIOException; import java.util.Arrays; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.powermax.internal.message.PowermaxCommManager; import org.openhab.binding.powermax.internal.message.PowermaxReceiveType; import org.openhab.core.util.HexUtils; @@ -27,13 +28,14 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxReaderThread extends Thread { - private final Logger logger = LoggerFactory.getLogger(PowermaxReaderThread.class); - private static final int READ_BUFFER_SIZE = 20; private static final int MAX_MSG_SIZE = 0xC0; + private final Logger logger = LoggerFactory.getLogger(PowermaxReaderThread.class); + private PowermaxConnector connector; /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxSerialConnector.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxSerialConnector.java index 9fa671d8c4bc6..906c842fb64be 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxSerialConnector.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxSerialConnector.java @@ -13,7 +13,11 @@ package org.openhab.binding.powermax.internal.connector; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.io.transport.serial.SerialPort; import org.openhab.core.io.transport.serial.SerialPortEvent; import org.openhab.core.io.transport.serial.SerialPortEventListener; @@ -27,6 +31,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxSerialConnector extends PowermaxConnector implements SerialPortEventListener { private final Logger logger = LoggerFactory.getLogger(PowermaxSerialConnector.class); @@ -34,7 +39,7 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial private final String serialPortName; private final int baudRate; private final SerialPortManager serialPortManager; - private SerialPort serialPort; + private @Nullable SerialPort serialPort; /** * Constructor @@ -50,7 +55,6 @@ public PowermaxSerialConnector(SerialPortManager serialPortManager, String seria this.serialPortManager = serialPortManager; this.serialPortName = serialPortName; this.baudRate = baudRate; - this.serialPort = null; } @Override @@ -65,26 +69,31 @@ public void open() throws Exception { SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000); serialPort = commPort; - serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - serialPort.enableReceiveThreshold(1); - serialPort.enableReceiveTimeout(250); + commPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + commPort.enableReceiveThreshold(1); + commPort.enableReceiveTimeout(250); - setInput(serialPort.getInputStream()); - setOutput(serialPort.getOutputStream()); + InputStream inputStream = commPort.getInputStream(); + setInput(inputStream); + OutputStream outputStream = commPort.getOutputStream(); + setOutput(outputStream); - getOutput().flush(); - if (getInput().markSupported()) { - getInput().reset(); + if (outputStream != null) { + outputStream.flush(); + } + if (inputStream != null && inputStream.markSupported()) { + inputStream.reset(); } // RXTX serial port library causes high CPU load // Start event listener, which will just sleep and slow down event // loop - serialPort.addEventListener(this); - serialPort.notifyOnDataAvailable(true); + commPort.addEventListener(this); + commPort.notifyOnDataAvailable(true); - setReaderThread(new PowermaxReaderThread(this, readerThreadName)); - getReaderThread().start(); + PowermaxReaderThread readerThread = new PowermaxReaderThread(this, readerThreadName); + setReaderThread(readerThread); + readerThread.start(); setConnected(true); } @@ -93,14 +102,15 @@ public void open() throws Exception { public void close() { logger.debug("close(): Closing Serial Connection"); - if (serialPort != null) { - serialPort.removeEventListener(); + SerialPort commPort = serialPort; + if (commPort != null) { + commPort.removeEventListener(); } super.cleanup(true); - if (serialPort != null) { - serialPort.close(); + if (commPort != null) { + commPort.close(); } serialPort = null; diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxTcpConnector.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxTcpConnector.java index 40014a1c1378a..8adf17de378d6 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxTcpConnector.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/connector/PowermaxTcpConnector.java @@ -18,6 +18,8 @@ import java.net.SocketAddress; import java.net.SocketTimeoutException; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +28,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxTcpConnector extends PowermaxConnector { private final Logger logger = LoggerFactory.getLogger(PowermaxTcpConnector.class); @@ -33,7 +36,7 @@ public class PowermaxTcpConnector extends PowermaxConnector { private final String ipAddress; private final int tcpPort; private final int connectTimeout; - private Socket tcpSocket; + private @Nullable Socket tcpSocket; /** * Constructor. @@ -54,16 +57,18 @@ public PowermaxTcpConnector(String ip, int port, int timeout, String readerThrea public void open() throws Exception { logger.debug("open(): Opening TCP Connection"); - tcpSocket = new Socket(); - tcpSocket.setSoTimeout(250); + Socket socket = new Socket(); + tcpSocket = socket; + socket.setSoTimeout(250); SocketAddress socketAddress = new InetSocketAddress(ipAddress, tcpPort); - tcpSocket.connect(socketAddress, connectTimeout); + socket.connect(socketAddress, connectTimeout); - setInput(tcpSocket.getInputStream()); - setOutput(tcpSocket.getOutputStream()); + setInput(socket.getInputStream()); + setOutput(socket.getOutputStream()); - setReaderThread(new PowermaxReaderThread(this, readerThreadName)); - getReaderThread().start(); + PowermaxReaderThread readerThread = new PowermaxReaderThread(this, readerThreadName); + setReaderThread(readerThread); + readerThread.start(); setConnected(true); } @@ -74,9 +79,10 @@ public void close() { super.cleanup(false); - if (tcpSocket != null) { + Socket socket = tcpSocket; + if (socket != null) { try { - tcpSocket.close(); + socket.close(); } catch (IOException e) { logger.debug("Error while closing the socket: {}", e.getMessage()); } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/console/PowermaxCommandExtension.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/console/PowermaxCommandExtension.java index 3d58f5250eed9..74df11541e5c5 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/console/PowermaxCommandExtension.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/console/PowermaxCommandExtension.java @@ -15,7 +15,9 @@ import java.util.Arrays; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.powermax.internal.handler.PowermaxBridgeHandler; +import org.openhab.binding.powermax.internal.state.PowermaxState; import org.openhab.core.io.console.Console; import org.openhab.core.io.console.extensions.AbstractConsoleCommandExtension; import org.openhab.core.io.console.extensions.ConsoleCommandExtension; @@ -23,6 +25,7 @@ import org.openhab.core.thing.ThingRegistry; import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.binding.ThingHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -31,6 +34,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault @Component(service = ConsoleCommandExtension.class) public class PowermaxCommandExtension extends AbstractConsoleCommandExtension { @@ -38,10 +42,12 @@ public class PowermaxCommandExtension extends AbstractConsoleCommandExtension { private static final String DOWNLOAD_SETUP = "download_setup"; private static final String BRIDGE_STATE = "bridge_state"; - private ThingRegistry thingRegistry; + private final ThingRegistry thingRegistry; - public PowermaxCommandExtension() { + @Activate + public PowermaxCommandExtension(final @Reference ThingRegistry thingRegistry) { super("powermax", "Interact with the Powermax binding."); + this.thingRegistry = thingRegistry; } @Override @@ -83,8 +89,11 @@ public void execute(String[] args, Console console) { console.println("Command '" + args[1] + "' handled."); break; case BRIDGE_STATE: - for (String line : handler.getCurrentState().toString().split("\n")) { - console.println(line); + PowermaxState state = handler.getCurrentState(); + if (state != null) { + for (String line : state.toString().split("\n")) { + console.println(line); + } } break; default: @@ -104,13 +113,4 @@ public List getUsages() { buildCommandUsage(" " + DOWNLOAD_SETUP, "download setup"), buildCommandUsage(" " + BRIDGE_STATE, "show current state") }); } - - @Reference - protected void setThingRegistry(ThingRegistry thingRegistry) { - this.thingRegistry = thingRegistry; - } - - protected void unsetThingRegistry(ThingRegistry thingRegistry) { - this.thingRegistry = null; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/discovery/PowermaxDiscoveryService.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/discovery/PowermaxDiscoveryService.java index 9333e6d064170..feab2c0df3a2b 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/discovery/PowermaxDiscoveryService.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/discovery/PowermaxDiscoveryService.java @@ -48,10 +48,10 @@ public class PowermaxDiscoveryService extends AbstractDiscoveryService implements PowermaxPanelSettingsListener, ThingHandlerService { - private final Logger logger = LoggerFactory.getLogger(PowermaxDiscoveryService.class); - private static final int SEARCH_TIME = 5; + private final Logger logger = LoggerFactory.getLogger(PowermaxDiscoveryService.class); + private @Nullable PowermaxBridgeHandler bridgeHandler; /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java index 405c2b97d705f..b4e1bee805834 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java @@ -23,6 +23,8 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.config.PowermaxIpConfiguration; import org.openhab.binding.powermax.internal.config.PowermaxSerialConfiguration; import org.openhab.binding.powermax.internal.discovery.PowermaxDiscoveryService; @@ -36,6 +38,7 @@ import org.openhab.binding.powermax.internal.state.PowermaxStateContainer.Value; import org.openhab.binding.powermax.internal.state.PowermaxStateEvent; import org.openhab.binding.powermax.internal.state.PowermaxStateEventListener; +import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.library.types.OnOffType; @@ -59,6 +62,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxBridgeHandler extends BaseBridgeHandler implements PowermaxStateEventListener { private final Logger logger = LoggerFactory.getLogger(PowermaxBridgeHandler.class); @@ -68,9 +72,6 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax private static final long ONE_MINUTE = TimeUnit.MINUTES.toMillis(1); private static final long FIVE_MINUTES = TimeUnit.MINUTES.toMillis(5); - /** Default delay in milliseconds to reset a motion detection */ - private static final long DEFAULT_MOTION_OFF_DELAY = TimeUnit.MINUTES.toMillis(3); - private static final int NB_EVENT_LOG = 10; private static final PowermaxPanelType DEFAULT_PANEL_TYPE = PowermaxPanelType.POWERMAX_PRO; @@ -79,7 +80,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax private static final int MAX_DOWNLOAD_ATTEMPTS = 3; - private ScheduledFuture globalJob; + private @Nullable ScheduledFuture globalJob; private List listeners = new CopyOnWriteArrayList<>(); @@ -96,7 +97,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax private PowermaxState currentState; /** The object in charge of the communication with the Powermax alarm system */ - private PowermaxCommManager commManager; + private @Nullable PowermaxCommManager commManager; private int remainingDownloadAttempts; @@ -104,6 +105,8 @@ public PowermaxBridgeHandler(Bridge thing, SerialPortManager serialPortManager, super(thing); this.serialPortManager = serialPortManager; this.timeZoneProvider = timeZoneProvider; + this.pinCode = ""; + this.currentState = new PowermaxState(new PowermaxPanelSettings(DEFAULT_PANEL_TYPE), timeZoneProvider); } @Override @@ -111,12 +114,14 @@ public Collection> getServices() { return Collections.singleton(PowermaxDiscoveryService.class); } - public PowermaxState getCurrentState() { - return currentState; + public @Nullable PowermaxState getCurrentState() { + PowermaxCommManager localCommManager = commManager; + return (localCommManager == null) ? null : currentState; } - public PowermaxPanelSettings getPanelSettings() { - return (commManager == null) ? null : commManager.getPanelSettings(); + public @Nullable PowermaxPanelSettings getPanelSettings() { + PowermaxCommManager localCommManager = commManager; + return (localCommManager == null) ? null : localCommManager.getPanelSettings(); } @Override @@ -137,7 +142,8 @@ public void initialize() { } if (errorMsg == null) { - if (globalJob == null || globalJob.isCancelled()) { + ScheduledFuture job = globalJob; + if (job == null || job.isCancelled()) { // Delay the startup in case the handler is restarted immediately globalJob = scheduler.scheduleWithFixedDelay(() -> { try { @@ -146,7 +152,7 @@ public void initialize() { updateRingingState(); if (isConnected()) { checkKeepAlive(); - commManager.retryDownloadSetup(remainingDownloadAttempts); + retryDownloadSetup(); } else { tryReconnect(); } @@ -160,30 +166,27 @@ public void initialize() { } } - private String initializeBridgeSerial(PowermaxSerialConfiguration config, String threadName) { + private @Nullable String initializeBridgeSerial(PowermaxSerialConfiguration config, String threadName) { String errorMsg = null; - if (config.serialPort != null && !config.serialPort.trim().isEmpty() - && !config.serialPort.trim().startsWith("rfc2217")) { - motionOffDelay = getMotionOffDelaySetting(config.motionOffDelay, DEFAULT_MOTION_OFF_DELAY); - boolean allowArming = getBooleanSetting(config.allowArming, false); - boolean allowDisarming = getBooleanSetting(config.allowDisarming, false); + String serialPort = config.serialPort.trim(); + if (!serialPort.isEmpty() && !serialPort.startsWith("rfc2217")) { + motionOffDelay = config.motionOffDelay * ONE_MINUTE; pinCode = config.pinCode; - forceStandardMode = getBooleanSetting(config.forceStandardMode, false); + forceStandardMode = config.forceStandardMode; PowermaxPanelType panelType = getPanelTypeSetting(config.panelType, DEFAULT_PANEL_TYPE); - boolean autoSyncTime = getBooleanSetting(config.autoSyncTime, false); - PowermaxArmMode.DISARMED.setAllowedCommand(allowDisarming); - PowermaxArmMode.ARMED_HOME.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_AWAY.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(allowArming); + PowermaxArmMode.DISARMED.setAllowedCommand(config.allowDisarming); + PowermaxArmMode.ARMED_HOME.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_AWAY.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(config.allowArming); - commManager = new PowermaxCommManager(config.serialPort, panelType, forceStandardMode, autoSyncTime, + commManager = new PowermaxCommManager(serialPort, panelType, forceStandardMode, config.autoSyncTime, serialPortManager, threadName, timeZoneProvider); } else { - if (config.serialPort != null && config.serialPort.trim().startsWith("rfc2217")) { + if (serialPort.startsWith("rfc2217")) { errorMsg = "Please use the IP Connection thing type for a serial over IP connection."; } else { errorMsg = "serialPort setting must be defined in thing configuration"; @@ -192,26 +195,24 @@ private String initializeBridgeSerial(PowermaxSerialConfiguration config, String return errorMsg; } - private String initializeBridgeIp(PowermaxIpConfiguration config, String threadName) { + private @Nullable String initializeBridgeIp(PowermaxIpConfiguration config, String threadName) { String errorMsg = null; - if (config.ip != null && !config.ip.trim().isEmpty() && config.tcpPort != null) { - motionOffDelay = getMotionOffDelaySetting(config.motionOffDelay, DEFAULT_MOTION_OFF_DELAY); - boolean allowArming = getBooleanSetting(config.allowArming, false); - boolean allowDisarming = getBooleanSetting(config.allowDisarming, false); + String ip = config.ip.trim(); + if (!ip.isEmpty() && config.tcpPort > 0) { + motionOffDelay = config.motionOffDelay * ONE_MINUTE; pinCode = config.pinCode; - forceStandardMode = getBooleanSetting(config.forceStandardMode, false); + forceStandardMode = config.forceStandardMode; PowermaxPanelType panelType = getPanelTypeSetting(config.panelType, DEFAULT_PANEL_TYPE); - boolean autoSyncTime = getBooleanSetting(config.autoSyncTime, false); - PowermaxArmMode.DISARMED.setAllowedCommand(allowDisarming); - PowermaxArmMode.ARMED_HOME.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_AWAY.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(allowArming); - PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(allowArming); + PowermaxArmMode.DISARMED.setAllowedCommand(config.allowDisarming); + PowermaxArmMode.ARMED_HOME.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_AWAY.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_HOME_INSTANT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_AWAY_INSTANT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_NIGHT.setAllowedCommand(config.allowArming); + PowermaxArmMode.ARMED_NIGHT_INSTANT.setAllowedCommand(config.allowArming); - commManager = new PowermaxCommManager(config.ip, config.tcpPort, panelType, forceStandardMode, autoSyncTime, + commManager = new PowermaxCommManager(ip, config.tcpPort, panelType, forceStandardMode, config.autoSyncTime, threadName, timeZoneProvider); } else { errorMsg = "ip and port settings must be defined in thing configuration"; @@ -222,8 +223,9 @@ private String initializeBridgeIp(PowermaxIpConfiguration config, String threadN @Override public void dispose() { logger.debug("Handler disposed for thing {}", getThing().getUID()); - if (globalJob != null && !globalJob.isCancelled()) { - globalJob.cancel(true); + ScheduledFuture job = globalJob; + if (job != null && !job.isCancelled()) { + job.cancel(true); globalJob = null; } closeConnection(); @@ -236,13 +238,15 @@ public void dispose() { * than the value defined by the variable motionOffDelay */ private void updateMotionSensorState() { - long now = System.currentTimeMillis(); - if (currentState != null) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager != null) { + long now = System.currentTimeMillis(); boolean update = false; - PowermaxState updateState = commManager.createNewState(); - PowermaxPanelSettings panelSettings = getPanelSettings(); + PowermaxState updateState = localCommManager.createNewState(); + PowermaxPanelSettings panelSettings = localCommManager.getPanelSettings(); for (int i = 1; i <= panelSettings.getNbZones(); i++) { - if (panelSettings.getZoneSettings(i) != null && panelSettings.getZoneSettings(i).isMotionSensor() + PowermaxZoneSettings zoneSettings = panelSettings.getZoneSettings(i); + if (zoneSettings != null && zoneSettings.isMotionSensor() && currentState.getZone(i).isLastTripBeforeTime(now - motionOffDelay)) { update = true; updateState.getZone(i).tripped.setValue(false); @@ -259,12 +263,14 @@ private void updateMotionSensorState() { * Turn off the Ringing flag when the bell time expires */ private void updateRingingState() { - if (currentState != null && Boolean.TRUE.equals(currentState.ringing.getValue())) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager != null && Boolean.TRUE.equals(currentState.ringing.getValue())) { long now = System.currentTimeMillis(); - long bellTime = getPanelSettings().getBellTime() * ONE_MINUTE; + long bellTime = localCommManager.getPanelSettings().getBellTime() * ONE_MINUTE; - if ((currentState.ringingSince.getValue() + bellTime) < now) { - PowermaxState updateState = commManager.createNewState(); + Long ringingSince = currentState.ringingSince.getValue(); + if (ringingSince != null && (ringingSince + bellTime) < now) { + PowermaxState updateState = localCommManager.createNewState(); updateState.ringing.setValue(false); updateChannelsFromAlarmState(RINGING, updateState); currentState.merge(updateState); @@ -276,25 +282,33 @@ private void updateRingingState() { * Check that we're actively communicating with the panel */ private void checkKeepAlive() { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + return; + } long now = System.currentTimeMillis(); - if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) - && (currentState.lastKeepAlive.getValue() != null) - && ((now - currentState.lastKeepAlive.getValue()) > ONE_MINUTE)) { + Long lastKeepAlive = currentState.lastKeepAlive.getValue(); + Long lastMessageTime = currentState.lastMessageTime.getValue(); + if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) && (lastKeepAlive != null) + && ((now - lastKeepAlive) > ONE_MINUTE)) { // In Powerlink mode: let Powermax know we are alive - commManager.sendRestoreMessage(); + localCommManager.sendRestoreMessage(); currentState.lastKeepAlive.setValue(now); - } else if (!Boolean.TRUE.equals(currentState.downloadMode.getValue()) - && (currentState.lastMessageTime.getValue() != null) - && ((now - currentState.lastMessageTime.getValue()) > FIVE_MINUTES)) { + } else if (!Boolean.TRUE.equals(currentState.downloadMode.getValue()) && (lastMessageTime != null) + && ((now - lastMessageTime) > FIVE_MINUTES)) { // In Standard mode: ping the panel every so often to detect disconnects - commManager.sendMessage(PowermaxSendType.STATUS); + localCommManager.sendMessage(PowermaxSendType.STATUS); } } private void tryReconnect() { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + return; + } logger.info("Trying to connect or reconnect..."); closeConnection(); - currentState = commManager.createNewState(); + currentState = localCommManager.createNewState(); try { openConnection(); logger.debug("openConnection(): connected"); @@ -305,7 +319,7 @@ private void tryReconnect() { updateChannelsFromAlarmState(MODE, currentState); processPanelSettings(); } else { - commManager.startDownload(); + localCommManager.startDownload(); } } catch (Exception e) { logger.debug("openConnection(): {}", e.getMessage(), e); @@ -320,9 +334,10 @@ private void tryReconnect() { * @return true if the connection has been opened */ private synchronized void openConnection() throws Exception { - if (commManager != null) { - commManager.addEventListener(this); - commManager.open(); + PowermaxCommManager localCommManager = commManager; + if (localCommManager != null) { + localCommManager.addEventListener(this); + localCommManager.open(); } remainingDownloadAttempts = MAX_DOWNLOAD_ATTEMPTS; } @@ -331,15 +346,24 @@ private synchronized void openConnection() throws Exception { * Close TCP or Serial connection to the Powermax Alarm Panel and remove the Event Listener */ private synchronized void closeConnection() { - if (commManager != null) { - commManager.close(); - commManager.removeEventListener(this); + PowermaxCommManager localCommManager = commManager; + if (localCommManager != null) { + localCommManager.close(); + localCommManager.removeEventListener(this); } logger.debug("closeConnection(): disconnected"); } private boolean isConnected() { - return commManager == null ? false : commManager.isConnected(); + PowermaxCommManager localCommManager = commManager; + return localCommManager == null ? false : localCommManager.isConnected(); + } + + private void retryDownloadSetup() { + PowermaxCommManager localCommManager = commManager; + if (localCommManager != null) { + localCommManager.retryDownloadSetup(remainingDownloadAttempts); + } } @Override @@ -347,7 +371,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("Received command {} from channel {}", command, channelUID.getId()); if (command instanceof RefreshType) { - updateChannelsFromAlarmState(channelUID.getId(), currentState); + updateChannelsFromAlarmState(channelUID.getId(), getCurrentState()); } else { switch (channelUID.getId()) { case ARM_MODE: @@ -384,62 +408,81 @@ public void handleCommand(ChannelUID channelUID, Command command) { } private void armCommand(PowermaxArmMode armMode) { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. Arm command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. Arm command is ignored."); } else { - commManager.requestArmMode(armMode, - Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) ? getPanelSettings().getFirstPinCode() + localCommManager.requestArmMode(armMode, + Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) + ? localCommManager.getPanelSettings().getFirstPinCode() : pinCode); } } private void pgmCommand(Command command) { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. PGM command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. PGM command is ignored."); } else { - commManager.sendPGMX10(command, null); + localCommManager.sendPGMX10(command, null); } } public void x10Command(Byte deviceNr, Command command) { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. X10 command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. X10 command is ignored."); } else { - commManager.sendPGMX10(command, deviceNr); + localCommManager.sendPGMX10(command, deviceNr); } } public void zoneBypassed(byte zoneNr, boolean bypassed) { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. Zone bypass command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. Zone bypass command is ignored."); } else if (!Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) { logger.debug("Powermax alarm binding: Bypass option only supported in Powerlink mode"); - } else if (!getPanelSettings().isBypassEnabled()) { + } else if (!localCommManager.getPanelSettings().isBypassEnabled()) { logger.debug("Powermax alarm binding: Bypass option not enabled in panel settings"); } else { - commManager.sendZoneBypass(bypassed, zoneNr, getPanelSettings().getFirstPinCode()); + localCommManager.sendZoneBypass(bypassed, zoneNr, localCommManager.getPanelSettings().getFirstPinCode()); } } private void downloadEventLog() { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. Event logs command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. Event logs command is ignored."); } else { - commManager.requestEventLog( - Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) ? getPanelSettings().getFirstPinCode() - : pinCode); + localCommManager.requestEventLog(Boolean.TRUE.equals(currentState.powerlinkMode.getValue()) + ? localCommManager.getPanelSettings().getFirstPinCode() + : pinCode); } } public void downloadSetup() { - if (!isConnected()) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + logger.debug("Powermax alarm binding not correctly initialized. Download setup command is ignored."); + } else if (!isConnected()) { logger.debug("Powermax alarm binding not connected. Download setup command is ignored."); } else if (!Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) { logger.debug("Powermax alarm binding: download setup only supported in Powerlink mode"); - } else if (commManager.isDownloadRunning()) { + } else if (localCommManager.isDownloadRunning()) { logger.debug("Powermax alarm binding: download setup not started as one is in progress"); } else { - commManager.startDownload(); + localCommManager.startDownload(); if (currentState.lastKeepAlive.getValue() != null) { currentState.lastKeepAlive.setValue(System.currentTimeMillis()); } @@ -447,11 +490,17 @@ public void downloadSetup() { } public String getInfoSetup() { - return (getPanelSettings() == null) ? "" : getPanelSettings().getInfo(); + PowermaxPanelSettings panelSettings = getPanelSettings(); + return (panelSettings == null) ? "" : panelSettings.getInfo(); } @Override public void onNewStateEvent(EventObject event) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + return; + } + PowermaxStateEvent stateEvent = (PowermaxStateEvent) event; PowermaxState updateState = stateEvent.getState(); @@ -459,7 +508,7 @@ public void onNewStateEvent(EventObject event) { && Boolean.TRUE.equals(updateState.downloadSetupRequired.getValue())) { // After Enrolling Powerlink or if a reset is required logger.debug("Powermax alarm binding: Reset"); - commManager.startDownload(); + localCommManager.startDownload(); updateState.downloadSetupRequired.setValue(false); if (currentState.lastKeepAlive.getValue() != null) { currentState.lastKeepAlive.setValue(System.currentTimeMillis()); @@ -469,12 +518,13 @@ public void onNewStateEvent(EventObject event) { // Were are in standard mode but received a keep alive message // so we switch in PowerLink mode logger.debug("Powermax alarm binding: Switching to Powerlink mode"); - commManager.startDownload(); + localCommManager.startDownload(); } boolean doProcessSettings = (updateState.powerlinkMode.getValue() != null); - getPanelSettings().getZoneRange().forEach(i -> { + PowermaxPanelSettings panelSettings = localCommManager.getPanelSettings(); + panelSettings.getZoneRange().forEach(i -> { if (Boolean.TRUE.equals(updateState.getZone(i).armed.getValue()) && Boolean.TRUE.equals(currentState.getZone(i).bypassed.getValue())) { updateState.getZone(i).armed.setValue(false); @@ -485,7 +535,6 @@ public void onNewStateEvent(EventObject event) { updateChannelsFromAlarmState(updateState); currentState.merge(updateState); - PowermaxPanelSettings panelSettings = getPanelSettings(); if (!updateState.getUpdatedZoneNames().isEmpty()) { for (Integer zoneIdx : updateState.getUpdatedZoneNames().keySet()) { if (panelSettings.getZoneSettings(zoneIdx) != null) { @@ -499,7 +548,7 @@ public void onNewStateEvent(EventObject event) { if (doProcessSettings) { // There is a change of mode (standard or Powerlink) processPanelSettings(); - commManager.exitDownload(); + localCommManager.exitDownload(); } } @@ -510,9 +559,14 @@ public void onCommunicationFailure(String message) { } private void processPanelSettings() { - if (commManager.processPanelSettings(Boolean.TRUE.equals(currentState.powerlinkMode.getValue()))) { + PowermaxCommManager localCommManager = commManager; + if (localCommManager == null) { + return; + } + + if (localCommManager.processPanelSettings(Boolean.TRUE.equals(currentState.powerlinkMode.getValue()))) { for (PowermaxPanelSettingsListener listener : listeners) { - listener.onPanelSettingsUpdated(getPanelSettings()); + listener.onPanelSettingsUpdated(localCommManager.getPanelSettings()); } remainingDownloadAttempts = 0; } else { @@ -525,10 +579,10 @@ private void processPanelSettings() { updatePropertiesFromPanelSettings(); if (Boolean.TRUE.equals(currentState.powerlinkMode.getValue())) { logger.info("Powermax alarm binding: running in Powerlink mode"); - commManager.sendRestoreMessage(); + localCommManager.sendRestoreMessage(); } else { logger.info("Powermax alarm binding: running in Standard mode"); - commManager.getInfosWhenInStandardMode(); + localCommManager.getInfosWhenInStandardMode(); } } @@ -537,7 +591,7 @@ private void processPanelSettings() { * * @param state: the alarm system state */ - private void updateChannelsFromAlarmState(PowermaxState state) { + private void updateChannelsFromAlarmState(@Nullable PowermaxState state) { updateChannelsFromAlarmState(null, state); } @@ -547,7 +601,7 @@ private void updateChannelsFromAlarmState(PowermaxState state) { * @param channel: filter on a particular channel; if null, consider all channels * @param state: the alarm system state */ - private synchronized void updateChannelsFromAlarmState(String channel, PowermaxState state) { + private synchronized void updateChannelsFromAlarmState(@Nullable String channel, @Nullable PowermaxState state) { if (state == null || !isConnected()) { return; } @@ -555,17 +609,16 @@ private synchronized void updateChannelsFromAlarmState(String channel, PowermaxS for (Value value : state.getValues()) { String vChannel = value.getChannel(); - if (((channel == null) || channel.equals(vChannel)) && (vChannel != null) && isLinked(vChannel) - && (value.getValue() != null)) { + if (((channel == null) || channel.equals(vChannel)) && isLinked(vChannel) && (value.getValue() != null)) { updateState(vChannel, value.getState()); } } for (int i = 1; i <= NB_EVENT_LOG; i++) { String channel2 = String.format(EVENT_LOG, i); - if (((channel == null) || channel.equals(channel2)) && isLinked(channel2) - && (state.getEventLog(i) != null)) { - updateState(channel2, new StringType(state.getEventLog(i))); + String log = state.getEventLog(i); + if (((channel == null) || channel.equals(channel2)) && isLinked(channel2) && (log != null)) { + updateState(channel2, new StringType(log)); } } @@ -574,14 +627,13 @@ private synchronized void updateChannelsFromAlarmState(String channel, PowermaxS PowermaxThingHandler handler = (PowermaxThingHandler) thing.getHandler(); if (handler != null) { if (thing.getThingTypeUID().equals(THING_TYPE_ZONE)) { - // All of the zone state objects will have the same list of values. // The use of getZone(1) here is just to get any PowermaxZoneState // and use it to get the list of zone channels. for (Value value : state.getZone(1).getValues()) { String channelId = value.getChannel(); - if ((channelId != null) && ((channel == null) || channel.equals(channelId))) { + if ((channel == null) || channel.equals(channelId)) { handler.updateChannelFromAlarmState(channelId, state); } } @@ -606,11 +658,14 @@ private synchronized void setAllChannelsOffline() { * Update properties to match the alarm panel settings */ private void updatePropertiesFromPanelSettings() { + PowermaxPanelSettings panelSettings = getPanelSettings(); + if (panelSettings == null) { + return; + } String value; Map properties = editProperties(); - PowermaxPanelSettings panelSettings = getPanelSettings(); - value = (panelSettings.getPanelType() != null) ? panelSettings.getPanelType().getLabel() : null; - if (value != null && !value.isEmpty()) { + value = panelSettings.getPanelType().getLabel(); + if (!value.isEmpty()) { properties.put(Thing.PROPERTY_MODEL_ID, value); } value = panelSettings.getPanelSerial(); @@ -640,25 +695,13 @@ public boolean unregisterPanelSettingsListener(PowermaxPanelSettingsListener lis return listeners.remove(listener); } - private boolean getBooleanSetting(Boolean value, boolean defaultValue) { - return value != null ? value.booleanValue() : defaultValue; - } - - private long getMotionOffDelaySetting(Integer value, long defaultValue) { - return value != null ? value.intValue() * ONE_MINUTE : defaultValue; - } - private PowermaxPanelType getPanelTypeSetting(String value, PowermaxPanelType defaultValue) { PowermaxPanelType result; - if (value != null) { - try { - result = PowermaxPanelType.fromLabel(value); - } catch (IllegalArgumentException e) { - result = defaultValue; - logger.debug("Powermax alarm binding: panel type not configured correctly"); - } - } else { + try { + result = PowermaxPanelType.fromLabel(value); + } catch (IllegalArgumentException e) { result = defaultValue; + logger.debug("Powermax alarm binding: panel type not configured correctly"); } return result; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxThingHandler.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxThingHandler.java index 1b2f7f179ad82..ad0959782118d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxThingHandler.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxThingHandler.java @@ -14,6 +14,7 @@ import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.config.PowermaxX10Configuration; import org.openhab.binding.powermax.internal.config.PowermaxZoneConfiguration; @@ -44,6 +45,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPanelSettingsListener { private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class); @@ -53,7 +55,7 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa private static final int X10_NR_MIN = 1; private static final int X10_NR_MAX = 16; - private PowermaxBridgeHandler bridgeHandler; + private @Nullable PowermaxBridgeHandler bridgeHandler; public PowermaxThingHandler(Thing thing) { super(thing); @@ -77,7 +79,7 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { initializeThingState((bridge == null) ? null : bridge.getHandler(), bridgeStatusInfo.getStatus()); } - private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridgeStatus) { + private void initializeThingState(@Nullable ThingHandler bridgeHandler, @Nullable ThingStatus bridgeStatus) { if (bridgeHandler != null && bridgeStatus != null) { if (bridgeStatus == ThingStatus.ONLINE) { boolean validConfig = false; @@ -85,8 +87,7 @@ private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridge if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) { PowermaxZoneConfiguration config = getConfigAs(PowermaxZoneConfiguration.class); - if (config.zoneNumber != null && config.zoneNumber >= ZONE_NR_MIN - && config.zoneNumber <= ZONE_NR_MAX) { + if (config.zoneNumber >= ZONE_NR_MIN && config.zoneNumber <= ZONE_NR_MAX) { validConfig = true; } else { errorMsg = "zoneNumber setting must be defined in thing configuration and set between " @@ -94,8 +95,7 @@ private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridge } } else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) { PowermaxX10Configuration config = getConfigAs(PowermaxX10Configuration.class); - if (config.deviceNumber != null && config.deviceNumber >= X10_NR_MIN - && config.deviceNumber <= X10_NR_MAX) { + if (config.deviceNumber >= X10_NR_MIN && config.deviceNumber <= X10_NR_MAX) { validConfig = true; } else { errorMsg = "deviceNumber setting must be defined in thing configuration and set between " @@ -106,9 +106,10 @@ private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridge if (validConfig) { updateStatus(ThingStatus.UNKNOWN); logger.debug("Set handler status to UNKNOWN for thing {} (bridge ONLINE)", getThing().getUID()); - this.bridgeHandler = (PowermaxBridgeHandler) bridgeHandler; - this.bridgeHandler.registerPanelSettingsListener(this); - onPanelSettingsUpdated(this.bridgeHandler.getPanelSettings()); + PowermaxBridgeHandler powermaxBridgeHandler = (PowermaxBridgeHandler) bridgeHandler; + this.bridgeHandler = powermaxBridgeHandler; + powermaxBridgeHandler.registerPanelSettingsListener(this); + onPanelSettingsUpdated(powermaxBridgeHandler.getPanelSettings()); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg); } @@ -133,8 +134,9 @@ private synchronized void setAllChannelsOffline() { @Override public void dispose() { logger.debug("Handler disposed for thing {}", getThing().getUID()); - if (bridgeHandler != null) { - bridgeHandler.unregisterPanelSettingsListener(this); + PowermaxBridgeHandler powermaxBridgeHandler = bridgeHandler; + if (powermaxBridgeHandler != null) { + powermaxBridgeHandler.unregisterPanelSettingsListener(this); } super.dispose(); } @@ -143,15 +145,18 @@ public void dispose() { public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("Received command {} from channel {}", command, channelUID.getId()); - if (bridgeHandler == null) { + PowermaxBridgeHandler powermaxBridgeHandler = bridgeHandler; + if (powermaxBridgeHandler == null) { return; } else if (command instanceof RefreshType) { - updateChannelFromAlarmState(channelUID.getId(), bridgeHandler.getCurrentState()); + updateChannelFromAlarmState(channelUID.getId(), powermaxBridgeHandler.getCurrentState()); } else { switch (channelUID.getId()) { case BYPASSED: if (command instanceof OnOffType) { - bridgeHandler.zoneBypassed(getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.byteValue(), + powermaxBridgeHandler.zoneBypassed( + Byte.valueOf( + (byte) (getConfigAs(PowermaxZoneConfiguration.class).zoneNumber & 0x000000FF)), command.equals(OnOffType.ON)); } else { logger.debug("Command of type {} while OnOffType is expected. Command is ignored.", @@ -159,7 +164,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { } break; case X10_STATUS: - bridgeHandler.x10Command(getConfigAs(PowermaxX10Configuration.class).deviceNumber.byteValue(), + powermaxBridgeHandler.x10Command( + Byte.valueOf( + (byte) (getConfigAs(PowermaxX10Configuration.class).deviceNumber & 0x000000FF)), command); break; default: @@ -175,13 +182,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { * @param channel: the channel * @param state: the alarm system state */ - public void updateChannelFromAlarmState(String channel, PowermaxState state) { - if (state == null || channel == null || !isLinked(channel)) { + public void updateChannelFromAlarmState(String channel, @Nullable PowermaxState state) { + if (state == null || !isLinked(channel)) { return; } if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) { - int num = getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.intValue(); + int num = getConfigAs(PowermaxZoneConfiguration.class).zoneNumber; for (Value value : state.getZone(num).getValues()) { String vChannel = value.getChannel(); @@ -191,9 +198,10 @@ public void updateChannelFromAlarmState(String channel, PowermaxState state) { } } } else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) { - int num = getConfigAs(PowermaxX10Configuration.class).deviceNumber.intValue(); - if (channel.equals(X10_STATUS) && (state.getPGMX10DeviceStatus(num) != null)) { - updateState(X10_STATUS, state.getPGMX10DeviceStatus(num) ? OnOffType.ON : OnOffType.OFF); + int num = getConfigAs(PowermaxX10Configuration.class).deviceNumber; + Boolean status = state.getPGMX10DeviceStatus(num); + if (channel.equals(X10_STATUS) && (status != null)) { + updateState(X10_STATUS, status ? OnOffType.ON : OnOffType.OFF); } } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java index c17598bd1ccad..33c088be5ab2f 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxAckMessage extends PowermaxBaseMessage { /** @@ -32,14 +35,15 @@ public PowermaxAckMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } PowermaxState updatedState = null; - if (commManager.getLastSendMsg().getSendType() == PowermaxSendType.EXIT) { + PowermaxBaseMessage lastSendMsg = commManager.getLastSendMsg(); + if (lastSendMsg != null && lastSendMsg.getSendType() == PowermaxSendType.EXIT) { updatedState = commManager.createNewState(); updatedState.powerlinkMode.setValue(true); updatedState.downloadMode.setValue(false); diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java index 334b3a39acfa5..21e5ee98ce849 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.openhab.core.util.HexUtils; @@ -23,14 +24,15 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxBaseMessage { private final Logger logger = LoggerFactory.getLogger(PowermaxBaseMessage.class); private byte[] rawData; private int code; - private PowermaxSendType sendType; - private PowermaxReceiveType receiveType; + private @Nullable PowermaxSendType sendType; + private @Nullable PowermaxReceiveType receiveType; private Object messageType; /** @@ -39,9 +41,9 @@ public class PowermaxBaseMessage { * @param message the message as a buffer of bytes */ public PowermaxBaseMessage(byte[] message) { - this.sendType = null; + this.rawData = message; this.messageType = "UNKNOWN"; - decodeMessage(message); + decodeMessage(); } /** @@ -59,40 +61,42 @@ public PowermaxBaseMessage(PowermaxSendType sendType) { * @param sendType the type of a message to be sent * @param param the dynamic part of a message to be sent; null if no dynamic part */ - public PowermaxBaseMessage(PowermaxSendType sendType, byte[] param) { + public PowermaxBaseMessage(PowermaxSendType sendType, byte @Nullable [] param) { this.sendType = sendType; this.messageType = "UNKNOWN"; byte[] message = new byte[sendType.getMessage().length + 3]; int index = 0; message[index++] = 0x0D; for (int i = 0; i < sendType.getMessage().length; i++) { - if ((param != null) && (sendType.getParamPosition() != null) && (i >= sendType.getParamPosition()) - && (i < (sendType.getParamPosition() + param.length))) { - message[index++] = param[i - sendType.getParamPosition()]; + Integer paramPosition = sendType.getParamPosition(); + if ((param != null) && (paramPosition != null) && (i >= paramPosition) + && (i < (paramPosition + param.length))) { + message[index++] = param[i - paramPosition]; } else { message[index++] = sendType.getMessage()[i]; } } message[index++] = 0x00; message[index++] = 0x0A; - decodeMessage(message); + this.rawData = message; + decodeMessage(); } /** * Extract information from the buffer of bytes and set class attributes - * - * @param data the message as a buffer of bytes */ - private void decodeMessage(byte[] data) { - rawData = data; + private void decodeMessage() { code = rawData[1] & 0x000000FF; + PowermaxReceiveType localReceiveType; try { - receiveType = PowermaxReceiveType.fromCode((byte) code); + localReceiveType = PowermaxReceiveType.fromCode((byte) code); } catch (IllegalArgumentException e) { - receiveType = null; + localReceiveType = null; } + receiveType = localReceiveType; - messageType = sendType != null ? sendType : receiveType != null ? receiveType : "UNKNOWN"; + PowermaxSendType localSendType = sendType; + messageType = localSendType != null ? localSendType : localReceiveType != null ? localReceiveType : "UNKNOWN"; } /** @@ -100,7 +104,7 @@ private void decodeMessage(byte[] data) { * * @return a new state containing all changes driven by the message */ - public final PowermaxState handleMessage(PowermaxCommManager commManager) { + public final @Nullable PowermaxState handleMessage(@Nullable PowermaxCommManager commManager) { // Send an ACK if needed if (isAckRequired() && commManager != null) { commManager.sendAck(this, (byte) 0x02); @@ -119,7 +123,7 @@ public final PowermaxState handleMessage(PowermaxCommManager commManager) { return newState; } - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { return null; } @@ -140,18 +144,18 @@ public int getCode() { /** * @return the type of the message to be sent */ - public PowermaxSendType getSendType() { + public @Nullable PowermaxSendType getSendType() { return sendType; } - public void setSendType(PowermaxSendType sendType) { + public void setSendType(@Nullable PowermaxSendType sendType) { this.sendType = sendType; } /** * @return the type of the received message */ - public PowermaxReceiveType getReceiveType() { + public @Nullable PowermaxReceiveType getReceiveType() { return receiveType; } @@ -159,7 +163,8 @@ public PowermaxReceiveType getReceiveType() { * @return true if the received message requires the sending of an ACK */ public boolean isAckRequired() { - return receiveType == null || receiveType.isAckRequired(); + PowermaxReceiveType localReceiveType = receiveType; + return localReceiveType == null || localReceiveType.isAckRequired(); } // Debugging helpers diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java index 175f6879d1c53..4b39c24ccff5b 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java @@ -23,6 +23,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.connector.PowermaxConnector; import org.openhab.binding.powermax.internal.connector.PowermaxSerialConnector; import org.openhab.binding.powermax.internal.connector.PowermaxTcpConnector; @@ -49,6 +51,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxCommManager implements PowermaxMessageEventListener { private final Logger logger = LoggerFactory.getLogger(PowermaxCommManager.class); @@ -77,19 +80,19 @@ public class PowermaxCommManager implements PowermaxMessageEventListener { private PowermaxConnector connector; /** The last message sent to the the Powermax alarm system */ - private PowermaxBaseMessage lastSendMsg; + private @Nullable PowermaxBaseMessage lastSendMsg; /** The message queue of messages to be sent to the the Powermax alarm system */ private ConcurrentLinkedQueue msgQueue = new ConcurrentLinkedQueue<>(); /** The time in milliseconds the last download of the panel setup was requested */ - private Long lastTimeDownloadRequested; + private long lastTimeDownloadRequested; /** The boolean indicating if the download of the panel setup is in progress or not */ private boolean downloadRunning; /** The time in milliseconds used to set time and date */ - private Long syncTimeCheck; + private long syncTimeCheck; /** * Constructor for Serial Connection @@ -110,13 +113,8 @@ public PowermaxCommManager(String sPort, PowermaxPanelType panelType, boolean fo this.timeZoneProvider = timeZoneProvider; this.panelSettings = new PowermaxPanelSettings(panelType); this.scheduler = ThreadPoolManager.getScheduledPool(threadName + "-sender"); - String serialPort = (sPort != null && !sPort.trim().isEmpty()) ? sPort.trim() : null; - if (serialPort != null) { - connector = new PowermaxSerialConnector(serialPortManager, serialPort, DEFAULT_BAUD_RATE, - threadName + "-reader"); - } else { - connector = null; - } + this.connector = new PowermaxSerialConnector(serialPortManager, sPort.trim(), DEFAULT_BAUD_RATE, + threadName + "-reader"); } /** @@ -138,13 +136,8 @@ public PowermaxCommManager(String ip, int port, PowermaxPanelType panelType, boo this.timeZoneProvider = timeZoneProvider; this.panelSettings = new PowermaxPanelSettings(panelType); this.scheduler = ThreadPoolManager.getScheduledPool(threadName + "-sender"); - String ipAddress = (ip != null && !ip.trim().isEmpty()) ? ip.trim() : null; - int tcpPort = (port > 0) ? port : DEFAULT_TCP_PORT; - if (ipAddress != null) { - connector = new PowermaxTcpConnector(ipAddress, tcpPort, TCP_CONNECTION_TIMEOUT, threadName + "-reader"); - } else { - connector = null; - } + this.connector = new PowermaxTcpConnector(ip.trim(), port > 0 ? port : DEFAULT_TCP_PORT, TCP_CONNECTION_TIMEOUT, + threadName + "-reader"); } /** @@ -154,9 +147,7 @@ public PowermaxCommManager(String ip, int port, PowermaxPanelType panelType, boo */ public synchronized void addEventListener(PowermaxStateEventListener listener) { listeners.add(listener); - if (connector != null) { - connector.addEventListener(this); - } + connector.addEventListener(this); } /** @@ -165,9 +156,7 @@ public synchronized void addEventListener(PowermaxStateEventListener listener) { * @param listener the listener to be removed */ public synchronized void removeEventListener(PowermaxStateEventListener listener) { - if (connector != null) { - connector.removeEventListener(this); - } + connector.removeEventListener(this); listeners.remove(listener); } @@ -177,9 +166,7 @@ public synchronized void removeEventListener(PowermaxStateEventListener listener * @return true if connected or false if not */ public void open() throws Exception { - if (connector != null) { - connector.open(); - } + connector.open(); lastSendMsg = null; msgQueue = new ConcurrentLinkedQueue<>(); } @@ -190,10 +177,8 @@ public void open() throws Exception { * @return true if connected or false if not */ public boolean close() { - if (connector != null) { - connector.close(); - } - lastTimeDownloadRequested = null; + connector.close(); + lastTimeDownloadRequested = 0; downloadRunning = false; return isConnected(); } @@ -202,7 +187,7 @@ public boolean close() { * @return true if connected to the Powermax alarm system or false if not */ public boolean isConnected() { - return (connector != null) && connector.isConnected(); + return connector.isConnected(); } /** @@ -220,7 +205,7 @@ public PowermaxPanelSettings getPanelSettings() { * @return true if no problem encountered to get all the settings; false if not */ public boolean processPanelSettings(boolean powerlinkMode) { - return panelSettings.process(powerlinkMode, panelType, powerlinkMode ? syncTimeCheck : null); + return panelSettings.process(powerlinkMode, panelType, powerlinkMode ? syncTimeCheck : 0); } /** @@ -233,7 +218,7 @@ public PowermaxState createNewState() { /** * @return the last message sent to the Powermax alarm system */ - public synchronized PowermaxBaseMessage getLastSendMsg() { + public synchronized @Nullable PowermaxBaseMessage getLastSendMsg() { return lastSendMsg; } @@ -261,8 +246,9 @@ public void onNewMessageEvent(EventObject event) { updateState.lastMessageTime.setValue(System.currentTimeMillis()); - if (updateState.getUpdateSettings() != null) { - panelSettings.updateRawSettings(updateState.getUpdateSettings()); + byte[] buffer = updateState.getUpdateSettings(); + if (buffer != null) { + panelSettings.updateRawSettings(buffer); } if (!updateState.getUpdatedZoneNames().isEmpty()) { for (Integer zoneIdx : updateState.getUpdatedZoneNames().keySet()) { @@ -349,7 +335,7 @@ public boolean requestArmMode(PowermaxArmMode armMode, String pinCode) { boolean done = false; if (!armMode.isAllowedCommand()) { logger.debug("Powermax alarm binding: requested arm mode {} rejected", armMode.getShortName()); - } else if ((pinCode == null) || (pinCode.length() != 4)) { + } else if (pinCode.length() != 4) { logger.debug("Powermax alarm binding: requested arm mode {} rejected due to invalid PIN code", armMode.getShortName()); } else { @@ -376,7 +362,7 @@ public boolean requestArmMode(PowermaxArmMode armMode, String pinCode) { * * @return true if the message was sent or false if not */ - public boolean sendPGMX10(Command action, Byte device) { + public boolean sendPGMX10(Command action, @Nullable Byte device) { logger.debug("sendPGMX10(): action = {}, device = {}", action, device); boolean done = false; @@ -418,7 +404,7 @@ public boolean sendZoneBypass(boolean bypass, byte zone, String pinCode) { boolean done = false; - if ((pinCode == null) || (pinCode.length() != 4)) { + if (pinCode.length() != 4) { logger.debug("Powermax alarm binding: zone bypass rejected due to invalid PIN code"); } else if ((zone < 1) || (zone > panelSettings.getNbZones())) { logger.debug("Powermax alarm binding: invalid zone number: {}", zone); @@ -483,10 +469,10 @@ public boolean sendSetTime() { } else { logger.info( "Powermax alarm binding: time not synchronized; please correct the date/time of your openHAB server"); - syncTimeCheck = null; + syncTimeCheck = 0; } } else { - syncTimeCheck = null; + syncTimeCheck = 0; } return done; } @@ -503,7 +489,7 @@ public boolean requestEventLog(String pinCode) { boolean done = false; - if ((pinCode == null) || (pinCode.length() != 4)) { + if (pinCode.length() != 4) { logger.debug("Powermax alarm binding: requested event log rejected due to invalid PIN code"); } else { try { @@ -543,7 +529,7 @@ public synchronized void exitDownload() { public void retryDownloadSetup(int remainingAttempts) { long now = System.currentTimeMillis(); - if ((remainingAttempts > 0) && !isDownloadRunning() && ((lastTimeDownloadRequested == null) + if ((remainingAttempts > 0) && !isDownloadRunning() && ((lastTimeDownloadRequested == 0) || ((now - lastTimeDownloadRequested) >= DELAY_BETWEEN_SETUP_DOWNLOADS))) { // We wait at least 45 seconds before each retry to download the panel setup logger.debug("Powermax alarm binding: try again downloading setup"); @@ -569,9 +555,9 @@ public boolean isDownloadRunning() { } /** - * @return the time in milliseconds the last download of the panel setup was requested or null if not yet requested + * @return the time in milliseconds the last download of the panel setup was requested or 0 if not yet requested */ - public Long getLastTimeDownloadRequested() { + public long getLastTimeDownloadRequested() { return lastTimeDownloadRequested; } @@ -607,7 +593,7 @@ public boolean sendMessageLater(PowermaxSendType msgType, int waitTime) { return sendMessage(new PowermaxBaseMessage(msgType), false, waitTime); } - private synchronized boolean sendMessage(PowermaxBaseMessage msg, boolean immediate, int waitTime) { + private synchronized boolean sendMessage(@Nullable PowermaxBaseMessage msg, boolean immediate, int waitTime) { return sendMessage(msg, immediate, waitTime, false); } @@ -622,7 +608,7 @@ private synchronized boolean sendMessage(PowermaxBaseMessage msg, boolean immedi * @return true if the message was sent or the sending is delayed; false in other cases */ @SuppressWarnings("PMD.CompareObjectsWithEquals") - private synchronized boolean sendMessage(PowermaxBaseMessage msg, boolean immediate, int waitTime, + private synchronized boolean sendMessage(@Nullable PowermaxBaseMessage msg, boolean immediate, int waitTime, boolean doNotLog) { if ((waitTime > 0) && (msg != null)) { logger.debug("sendMessage(): delay ({} s) sending message (type {})", waitTime, msg.getSendType()); diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java index 52593acc572b4..743e51c776d3e 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +23,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxDeniedMessage extends PowermaxBaseMessage { private final Logger logger = LoggerFactory.getLogger(PowermaxDeniedMessage.class); @@ -36,14 +39,15 @@ public PowermaxDeniedMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } PowermaxState updatedState = null; - PowermaxSendType lastSendType = commManager.getLastSendMsg().getSendType(); + PowermaxBaseMessage lastSendMsg = commManager.getLastSendMsg(); + PowermaxSendType lastSendType = lastSendMsg == null ? null : lastSendMsg.getSendType(); if (lastSendType == PowermaxSendType.EVENTLOG || lastSendType == PowermaxSendType.ARM || lastSendType == PowermaxSendType.BYPASS) { logger.debug("Powermax alarm binding: invalid PIN code"); diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java index a63ae123ed0bf..26d92cfce82fe 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage { /** @@ -32,7 +35,7 @@ public PowermaxDownloadRetryMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java index 05180eeacb62b..8d30ff1b05efb 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings; import org.openhab.binding.powermax.internal.state.PowermaxState; @@ -20,6 +22,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxEventLogMessage extends PowermaxBaseMessage { /** @@ -33,7 +36,7 @@ public PowermaxEventLogMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java index 7d6bb8c819640..8bda7f452c1fc 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxPanelType; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.slf4j.Logger; @@ -22,6 +24,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxInfoMessage extends PowermaxBaseMessage { private final Logger logger = LoggerFactory.getLogger(PowermaxInfoMessage.class); @@ -37,7 +40,7 @@ public PowermaxInfoMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java index 25592e57ff024..f1bec2160f109 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java @@ -16,11 +16,14 @@ import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Constants used in Powermax messages * * @author Ron Isaacson - Initial contribution */ +@NonNullByDefault public class PowermaxMessageConstants { private PowermaxMessageConstants() { diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEvent.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEvent.java index 77e282f5382ae..831e8f690b3f8 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEvent.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEvent.java @@ -14,11 +14,14 @@ import java.util.EventObject; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Event for messages received from the Visonic alarm panel * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxMessageEvent extends EventObject { private static final long serialVersionUID = 1L; diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEventListener.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEventListener.java index ce13ad2293ad8..23e35c3df44b1 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEventListener.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageEventListener.java @@ -15,11 +15,14 @@ import java.util.EventListener; import java.util.EventObject; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Powermax Alarm Event Listener interface. Handles incoming Powermax Alarm message events * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public interface PowermaxMessageEventListener extends EventListener { /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java index 711570374c052..e031443e96b6e 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants.PowermaxSysEvent; import org.openhab.binding.powermax.internal.state.PowermaxState; @@ -20,6 +22,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxPanelMessage extends PowermaxBaseMessage { /** @@ -33,7 +36,7 @@ public PowermaxPanelMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java index 5eb286a455f82..265ffbea6b09c 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxPowerMasterMessage extends PowermaxBaseMessage { /** @@ -32,7 +35,7 @@ public PowermaxPowerMasterMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java index 795b22ae8b9d4..7da22fbce02d1 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +23,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxPowerlinkMessage extends PowermaxBaseMessage { private final Logger logger = LoggerFactory.getLogger(PowermaxPowerlinkMessage.class); @@ -36,7 +39,7 @@ public PowermaxPowerlinkMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxReceiveType.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxReceiveType.java index da7c6072f5604..ee5d38a0acbec 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxReceiveType.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxReceiveType.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Used to map received messages from the Visonic alarm panel to a ENUM value * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxReceiveType { ACK((byte) 0x02, 0, false), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSendType.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSendType.java index 27dbc2d780e01..a8fe7cf79f82f 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSendType.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSendType.java @@ -12,11 +12,15 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Used to map messages to be sent to the Visonic alarm panel to a ENUM value * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxSendType { INIT(new byte[] { (byte) 0xAB, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, null, null), @@ -108,10 +112,11 @@ public enum PowermaxSendType { PowermaxReceiveType.POWERMASTER); private byte[] message; - private Integer paramPosition; - private PowermaxReceiveType expectedResponseType; + private @Nullable Integer paramPosition; + private @Nullable PowermaxReceiveType expectedResponseType; - private PowermaxSendType(byte[] message, Integer paramPosition, PowermaxReceiveType expectedResponseType) { + private PowermaxSendType(byte[] message, @Nullable Integer paramPosition, + @Nullable PowermaxReceiveType expectedResponseType) { this.message = message; this.paramPosition = paramPosition; this.expectedResponseType = expectedResponseType; @@ -127,14 +132,14 @@ public byte[] getMessage() { /** * @return the position of the parameter in the message buffer */ - public Integer getParamPosition() { + public @Nullable Integer getParamPosition() { return paramPosition; } /** * @return the ENUM value of the expected message as response */ - public PowermaxReceiveType getExpectedResponseType() { + public @Nullable PowermaxReceiveType getExpectedResponseType() { return expectedResponseType; } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java index 2ec2f26a5591c..7135e61b82be2 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java @@ -14,6 +14,8 @@ import java.util.Arrays; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +25,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxSettingsMessage extends PowermaxBaseMessage { private final Logger logger = LoggerFactory.getLogger(PowermaxSettingsMessage.class); @@ -38,7 +41,7 @@ public PowermaxSettingsMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java index 24c5e65eabe89..3a966ccdea5d4 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java @@ -16,6 +16,8 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxArmMode; import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings; import org.openhab.binding.powermax.internal.state.PowermaxSensorType; @@ -27,6 +29,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxStatusMessage extends PowermaxBaseMessage { private static byte[] zoneBytes(byte zones1, byte zones9, byte zones17, byte zones25) { @@ -68,7 +71,7 @@ public PowermaxStatusMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java index 9fd572bc807c0..55f39bc0b7b03 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxTimeoutMessage extends PowermaxBaseMessage { /** @@ -32,7 +35,7 @@ public PowermaxTimeoutMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager != null) { commManager.sendMessage(PowermaxSendType.EXIT); } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java index dfede05dc2829..5999611b0f971 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxZonesNameMessage extends PowermaxBaseMessage { /** @@ -32,7 +35,7 @@ public PowermaxZonesNameMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java index 39067405078be..21115c288153d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; /** @@ -19,6 +21,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxZonesTypeMessage extends PowermaxBaseMessage { /** @@ -32,7 +35,7 @@ public PowermaxZonesTypeMessage(byte[] message) { } @Override - protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { + protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermasterSensorType.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermasterSensorType.java index 7ca7347a44388..378028be741b9 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermasterSensorType.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermasterSensorType.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * All defined sensor types for Master panels * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermasterSensorType { SENSOR_TYPE_1((byte) 0x01, "Motion"), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxArmMode.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxArmMode.java index 751ec5c773288..3b9631656374e 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxArmMode.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxArmMode.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * All defined arm modes * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxArmMode { DISARMED(0, "Disarmed", "Disarmed", false, (byte) 0x00, false), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelSettings.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelSettings.java index 8fed886270c88..ba4ef1f5394bd 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelSettings.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelSettings.java @@ -18,6 +18,8 @@ import java.util.GregorianCalendar; import java.util.stream.IntStream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants; import org.openhab.binding.powermax.internal.message.PowermaxSendType; import org.slf4j.Logger; @@ -28,13 +30,14 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxPanelSettings { - private final Logger logger = LoggerFactory.getLogger(PowermaxPanelSettings.class); - /** Number of PGM and X10 devices managed by the system */ private static final int NB_PGM_X10_DEVICES = 16; + private final Logger logger = LoggerFactory.getLogger(PowermaxPanelSettings.class); + /** Raw buffers for settings */ private Byte[][] rawSettings; @@ -45,15 +48,15 @@ public class PowermaxPanelSettings { private boolean quickArm; private boolean bypassEnabled; private boolean partitionsEnabled; - private String[] pinCodes; - private String panelEprom; - private String panelSoftware; - private String panelSerial; + private String @Nullable [] pinCodes; + private @Nullable String panelEprom; + private @Nullable String panelSoftware; + private @Nullable String panelSerial; private PowermaxZoneSettings[] zoneSettings; private PowermaxX10Settings[] x10Settings; - private boolean[] keypad1wEnrolled; - private boolean[] keypad2wEnrolled; - private boolean[] sirensEnrolled; + private boolean @Nullable [] keypad1wEnrolled; + private boolean @Nullable [] keypad2wEnrolled; + private boolean @Nullable [] sirensEnrolled; /** * Constructor @@ -108,21 +111,21 @@ public boolean isPartitionsEnabled() { /** * @return the panel EEPROM version */ - public String getPanelEprom() { + public @Nullable String getPanelEprom() { return panelEprom; } /** * @return the panel software version */ - public String getPanelSoftware() { + public @Nullable String getPanelSoftware() { return panelSoftware; } /** * @return the panel serial ID */ - public String getPanelSerial() { + public @Nullable String getPanelSerial() { return panelSerial; } @@ -147,7 +150,7 @@ public IntStream getZoneRange() { * * @return the settings of the zone */ - public PowermaxZoneSettings getZoneSettings(int zone) { + public @Nullable PowermaxZoneSettings getZoneSettings(int zone) { return ((zone < 1) || (zone > zoneSettings.length)) ? null : zoneSettings[zone - 1]; } @@ -158,7 +161,7 @@ public PowermaxZoneSettings getZoneSettings(int zone) { * * @return the name of the zone */ - public String getZoneName(int zone) { + public @Nullable String getZoneName(int zone) { PowermaxZoneSettings zoneSettings = getZoneSettings(zone); return (zoneSettings == null) ? null : zoneSettings.getName(); } @@ -204,7 +207,7 @@ public PowermaxX10Settings getPGMSettings() { * * @return the settings of the X10 device */ - public PowermaxX10Settings getX10Settings(int idx) { + public @Nullable PowermaxX10Settings getX10Settings(int idx) { return ((idx < 1) || (idx >= x10Settings.length)) ? null : x10Settings[idx]; } @@ -214,8 +217,9 @@ public PowermaxX10Settings getX10Settings(int idx) { * @return true if the 1 way keypad is enrolled; false if not */ public boolean isKeypad1wEnrolled(int idx) { - return ((keypad1wEnrolled == null) || (idx < 1) || (idx >= keypad1wEnrolled.length)) ? false - : keypad1wEnrolled[idx - 1]; + boolean @Nullable [] localKeypad1wEnrolled = keypad1wEnrolled; + return ((localKeypad1wEnrolled == null) || (idx < 1) || (idx >= localKeypad1wEnrolled.length)) ? false + : localKeypad1wEnrolled[idx - 1]; } /** @@ -224,8 +228,9 @@ public boolean isKeypad1wEnrolled(int idx) { * @return true if the 2 way keypad is enrolled; false if not */ public boolean isKeypad2wEnrolled(int idx) { - return ((keypad2wEnrolled == null) || (idx < 1) || (idx >= keypad2wEnrolled.length)) ? false - : keypad2wEnrolled[idx - 1]; + boolean @Nullable [] localKeypad2wEnrolled = keypad2wEnrolled; + return ((localKeypad2wEnrolled == null) || (idx < 1) || (idx >= localKeypad2wEnrolled.length)) ? false + : localKeypad2wEnrolled[idx - 1]; } /** @@ -234,19 +239,21 @@ public boolean isKeypad2wEnrolled(int idx) { * @return true if the siren is enrolled; false if not */ public boolean isSirenEnrolled(int idx) { - return ((sirensEnrolled == null) || (idx < 1) || (idx >= sirensEnrolled.length)) ? false - : sirensEnrolled[idx - 1]; + boolean @Nullable [] localSirensEnrolled = sirensEnrolled; + return ((localSirensEnrolled == null) || (idx < 1) || (idx >= localSirensEnrolled.length)) ? false + : localSirensEnrolled[idx - 1]; } /** - * @return the PIN code of the first user of null if unknown (standard mode) + * @return the PIN code of the first user of an empty string if unknown (standard mode) */ public String getFirstPinCode() { - return (pinCodes == null) ? null : pinCodes[0]; + String @Nullable [] localPinCodes = pinCodes; + return (localPinCodes == null || localPinCodes.length == 0) ? "" : localPinCodes[0]; } public void updateRawSettings(byte[] data) { - if ((data == null) || (data.length < 3)) { + if (data.length < 3) { return; } int start = 0; @@ -276,14 +283,14 @@ public void updateRawSettings(byte[] data) { } } - private byte[] readSettings(PowermaxSendType msgType, int start, int end) { + private byte @Nullable [] readSettings(PowermaxSendType msgType, int start, int end) { byte[] message = msgType.getMessage(); int page = message[2] & 0x000000FF; int index = message[1] & 0x000000FF; return readSettings(page, index + start, index + end); } - private byte[] readSettings(int page, int start, int end) { + private byte @Nullable [] readSettings(int page, int start, int end) { int pageMin = page + start / 0x100; int indexPageMin = start % 0x100; int pageMax = page + end / 0x100; @@ -332,7 +339,7 @@ private byte[] readSettings(int page, int start, int end) { return result; } - private String readSettingsAsString(PowermaxSendType msgType, int start, int end) { + private @Nullable String readSettingsAsString(PowermaxSendType msgType, int start, int end) { byte[] message = msgType.getMessage(); int page = message[2] & 0x000000FF; int index = message[1] & 0x000000FF; @@ -381,12 +388,11 @@ private String readSettingsAsString(PowermaxSendType msgType, int start, int end * * @param PowerlinkMode true if in Powerlink mode or false if in standard mode * @param defaultPanelType the default panel type to consider if not found in the raw buffers - * @param timeSet the time in milliseconds used to set time and date; null if no sync time requested + * @param timeSet the time in milliseconds used to set time and date; 0 if no sync time requested * * @return true if no problem encountered to get all the settings; false if not */ - @SuppressWarnings("null") - public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType, Long timeSet) { + public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType, long timeSet) { logger.debug("Process settings Powerlink {}", PowerlinkMode); boolean result = true; @@ -424,15 +430,15 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType quickArm = false; bypassEnabled = false; partitionsEnabled = false; - pinCodes = new String[userCnt]; + String[] localPinCodes = new String[userCnt]; panelEprom = null; panelSoftware = null; panelSerial = null; zoneSettings = new PowermaxZoneSettings[zoneCnt]; x10Settings = new PowermaxX10Settings[NB_PGM_X10_DEVICES]; - keypad1wEnrolled = new boolean[keypad1wCnt]; - keypad2wEnrolled = new boolean[keypad2wCnt]; - sirensEnrolled = new boolean[sirenCnt]; + boolean[] localKeypad1wEnrolled = new boolean[keypad1wCnt]; + boolean[] localKeypad2wEnrolled = new boolean[keypad2wCnt]; + boolean[] localSirensEnrolled = new boolean[sirenCnt]; if (PowerlinkMode) { // Check time and date @@ -453,7 +459,7 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND))); // Check if time sync was OK - if (timeSet != null) { + if (timeSet > 0) { long delta = (timeRead - timeSet) / 1000; if (delta <= 5) { logger.debug("Powermax alarm binding: time sync OK (delta {} s)", delta); @@ -528,7 +534,8 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType 2 * userCnt - 1); if (data != null) { for (int i = 0; i < userCnt; i++) { - pinCodes[i] = String.format("%02X%02X", data[i * 2] & 0x000000FF, data[i * 2 + 1] & 0x000000FF); + localPinCodes[i] = String.format("%02X%02X", data[i * 2] & 0x000000FF, + data[i * 2 + 1] & 0x000000FF); } } else { logger.debug("Cannot get PIN codes"); @@ -606,22 +613,26 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType boolean zoneEnrolled; byte zoneInfo; - byte sensorTypeCode; String sensorTypeStr; if (panelType.isPowerMaster()) { - zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(dataMr, i * 10 + 4, i * 10 + 9), zero5); zoneInfo = data[i]; - sensorTypeCode = dataMr[i * 10 + 5]; - try { - PowermasterSensorType sensorType = PowermasterSensorType.fromCode(sensorTypeCode); - sensorTypeStr = sensorType.getLabel(); - } catch (IllegalArgumentException e) { + if (dataMr != null) { + zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(dataMr, i * 10 + 4, i * 10 + 9), zero5); + byte sensorTypeCode = dataMr[i * 10 + 5]; + try { + PowermasterSensorType sensorType = PowermasterSensorType.fromCode(sensorTypeCode); + sensorTypeStr = sensorType.getLabel(); + } catch (IllegalArgumentException e) { + sensorTypeStr = null; + } + } else { + zoneEnrolled = false; sensorTypeStr = null; } } else { zoneEnrolled = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); zoneInfo = data[i * 4 + 3]; - sensorTypeCode = data[i * 4 + 2]; + byte sensorTypeCode = data[i * 4 + 2]; try { PowermaxSensorType sensorType = PowermaxSensorType .fromCode((byte) (sensorTypeCode & 0x0000000F)); @@ -686,7 +697,8 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType byte[] zero5 = new byte[] { 0, 0, 0, 0, 0 }; for (int i = 0; i < keypad2wCnt; i++) { - keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5); + localKeypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), + zero5); } } else { logger.debug("Cannot get 2 way keypad settings"); @@ -698,7 +710,8 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType byte[] zero5 = new byte[] { 0, 0, 0, 0, 0 }; for (int i = 0; i < sirenCnt; i++) { - sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), zero5); + localSirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 10 + 4, i * 10 + 9), + zero5); } } else { logger.debug("Cannot get siren settings"); @@ -711,7 +724,7 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType byte[] zero2 = new byte[] { 0, 0 }; for (int i = 0; i < keypad1wCnt; i++) { - keypad1wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 2), zero2); + localKeypad1wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 2), zero2); } } else { logger.debug("Cannot get 1 way keypad settings"); @@ -723,7 +736,7 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType byte[] zero3 = new byte[] { 0, 0, 0 }; for (int i = 0; i < keypad2wCnt; i++) { - keypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); + localKeypad2wEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); } } else { logger.debug("Cannot get 2 way keypad settings"); @@ -735,7 +748,7 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType byte[] zero3 = new byte[] { 0, 0, 0 }; for (int i = 0; i < sirenCnt; i++) { - sirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); + localSirensEnrolled[i] = !Arrays.equals(Arrays.copyOfRange(data, i * 4, i * 4 + 3), zero3); } } else { logger.debug("Cannot get siren settings"); @@ -758,6 +771,11 @@ public boolean process(boolean PowerlinkMode, PowermaxPanelType defaultPanelType } } + pinCodes = localPinCodes; + keypad1wEnrolled = localKeypad1wEnrolled; + keypad2wEnrolled = localKeypad2wEnrolled; + sirensEnrolled = localSirensEnrolled; + return result; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelType.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelType.java index 61f1d550682b3..a3c0010c3f938 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelType.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxPanelType.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Used to store main characteristics of each Visonic alarm panel type in an ENUM * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxPanelType { POWERMAX((byte) 0, "PowerMax", 1, 250, 8, 8, 2, 2, 8, 0, 28, 2, 0), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxSensorType.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxSensorType.java index e873b41063786..18bde0100db29 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxSensorType.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxSensorType.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * All defined sensor types for all panels except Master panels * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxSensorType { MOTION_SENSOR_1((byte) 0x03, "Motion"), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxState.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxState.java index b1273073d0a5a..c27c26c0e322c 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxState.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxState.java @@ -19,11 +19,13 @@ import java.util.List; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.message.PowermaxMessageConstants; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; +import org.openhab.core.types.UnDefType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +34,7 @@ * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxState extends PowermaxStateContainer { private final Logger logger = LoggerFactory.getLogger(PowermaxState.class); @@ -58,19 +61,31 @@ public class PowermaxState extends PowermaxStateContainer { public DynamicValue isArmed = new DynamicValue<>(this, SYSTEM_ARMED, () -> { return isArmed(); }, () -> { - return isArmed() ? OnOffType.ON : OnOffType.OFF; + Boolean isArmed = isArmed(); + if (isArmed == null) { + return UnDefType.NULL; + } + return isArmed ? OnOffType.ON : OnOffType.OFF; }); public DynamicValue panelMode = new DynamicValue<>(this, MODE, () -> { return getPanelMode(); }, () -> { - return new StringType(getPanelMode()); + String mode = getPanelMode(); + if (mode == null) { + return UnDefType.NULL; + } + return new StringType(mode); }); public DynamicValue shortArmMode = new DynamicValue<>(this, ARM_MODE, () -> { return getShortArmMode(); }, () -> { - return new StringType(getShortArmMode()); + String mode = getShortArmMode(); + if (mode == null) { + return UnDefType.NULL; + } + return new StringType(mode); }); public DynamicValue activeAlerts = new DynamicValue<>(this, ACTIVE_ALERTS, () -> { @@ -82,14 +97,18 @@ public class PowermaxState extends PowermaxStateContainer { public DynamicValue pgmStatus = new DynamicValue<>(this, PGM_STATUS, () -> { return getPGMX10DeviceStatus(0); }, () -> { - return getPGMX10DeviceStatus(0) ? OnOffType.ON : OnOffType.OFF; + Boolean status = getPGMX10DeviceStatus(0); + if (status == null) { + return UnDefType.NULL; + } + return status ? OnOffType.ON : OnOffType.OFF; }); private PowermaxPanelSettings panelSettings; private PowermaxZoneState[] zones; private Boolean[] pgmX10DevicesStatus; - private byte[] updateSettings; - private String[] eventLog; + private byte @Nullable [] updateSettings; + private String @Nullable [] eventLog; private Map updatedZoneNames; private Map updatedZoneInfos; private List activeAlertList; @@ -163,7 +182,7 @@ public PowermaxZoneState getZone(int zone) { * * @return the status (true or false) */ - public Boolean getPGMX10DeviceStatus(int device) { + public @Nullable Boolean getPGMX10DeviceStatus(int device) { return ((device < 0) || (device >= pgmX10DevicesStatus.length)) ? null : pgmX10DevicesStatus[device]; } @@ -173,7 +192,7 @@ public Boolean getPGMX10DeviceStatus(int device) { * @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1) * @param status true or false */ - public void setPGMX10DeviceStatus(int device, Boolean status) { + public void setPGMX10DeviceStatus(int device, @Nullable Boolean status) { if ((device >= 0) && (device < pgmX10DevicesStatus.length)) { this.pgmX10DevicesStatus[device] = status; } @@ -184,7 +203,7 @@ public void setPGMX10DeviceStatus(int device, Boolean status) { * * @return the raw buffer as a table of bytes */ - public byte[] getUpdateSettings() { + public byte @Nullable [] getUpdateSettings() { return updateSettings; } @@ -203,7 +222,8 @@ public void setUpdateSettings(byte[] updateSettings) { * @return the number of entries */ public int getEventLogSize() { - return (eventLog == null) ? 0 : eventLog.length; + String @Nullable [] localEventLog = eventLog; + return (localEventLog == null) ? 0 : localEventLog.length; } /** @@ -222,8 +242,10 @@ public void setEventLogSize(int size) { * * @return the entry value (event) */ - public String getEventLog(int index) { - return ((index < 1) || (index > getEventLogSize())) ? null : eventLog[index - 1]; + public @Nullable String getEventLog(int index) { + String @Nullable [] localEventLog = eventLog; + return ((localEventLog == null) || (index < 1) || (index > getEventLogSize())) ? null + : localEventLog[index - 1]; } /** @@ -233,8 +255,9 @@ public String getEventLog(int index) { * @param event the entry value (event) */ public void setEventLog(int index, String event) { - if ((index >= 1) && (index <= getEventLogSize())) { - this.eventLog[index - 1] = event; + String @Nullable [] localEventLog = eventLog; + if ((localEventLog != null) && (index >= 1) && (index <= getEventLogSize())) { + localEventLog[index - 1] = event; } } @@ -329,7 +352,7 @@ private void copyActiveAlertsFrom(@Nullable PowermaxState state) { * * @return either Download or Powerlink or Standard */ - public String getPanelMode() { + public @Nullable String getPanelMode() { String mode = null; if (Boolean.TRUE.equals(downloadMode.getValue())) { mode = "Download"; @@ -346,7 +369,7 @@ public String getPanelMode() { * * @return true or false */ - public Boolean isArmed() { + public @Nullable Boolean isArmed() { return isArmed(armMode.getValue()); } @@ -357,7 +380,7 @@ public Boolean isArmed() { * * @return true or false; null if mode is unexpected */ - private static Boolean isArmed(String armMode) { + private static @Nullable Boolean isArmed(@Nullable String armMode) { Boolean result = null; if (armMode != null) { try { @@ -375,7 +398,7 @@ private static Boolean isArmed(String armMode) { * * @return the short description */ - public String getShortArmMode() { + public @Nullable String getShortArmMode() { return getShortArmMode(armMode.getValue()); } @@ -386,7 +409,7 @@ public String getShortArmMode() { * * @return the short name or null if mode is unexpected */ - private static String getShortArmMode(String armMode) { + private static @Nullable String getShortArmMode(@Nullable String armMode) { String result = null; if (armMode != null) { try { @@ -420,8 +443,8 @@ public void keepOnlyDifferencesWith(PowermaxState otherState) { } for (int i = 0; i < pgmX10DevicesStatus.length; i++) { - if ((getPGMX10DeviceStatus(i) != null) - && getPGMX10DeviceStatus(i).equals(otherState.getPGMX10DeviceStatus(i))) { + Boolean status = getPGMX10DeviceStatus(i); + if ((status != null) && status.equals(otherState.getPGMX10DeviceStatus(i))) { setPGMX10DeviceStatus(i, null); } } @@ -462,8 +485,9 @@ public void merge(PowermaxState update) { } for (int i = 0; i < pgmX10DevicesStatus.length; i++) { - if (update.getPGMX10DeviceStatus(i) != null) { - setPGMX10DeviceStatus(i, update.getPGMX10DeviceStatus(i)); + Boolean status = update.getPGMX10DeviceStatus(i); + if (status != null) { + setPGMX10DeviceStatus(i, status); } } @@ -480,8 +504,9 @@ public void merge(PowermaxState update) { setEventLogSize(update.getEventLogSize()); } for (int i = 1; i <= getEventLogSize(); i++) { - if (update.getEventLog(i) != null) { - setEventLog(i, update.getEventLog(i)); + String log = update.getEventLog(i); + if (log != null) { + setEventLog(i, log); } } @@ -495,7 +520,7 @@ public String toString() { String str = "Bridge state:"; for (Value value : getValues()) { - if ((value.getChannel() != null) && (value.getValue() != null)) { + if (value.getValue() != null) { String channel = value.getChannel(); String vStr = value.getValue().toString(); String state = value.getState().toString(); @@ -508,15 +533,16 @@ public String toString() { } for (int i = 0; i < pgmX10DevicesStatus.length; i++) { - if (getPGMX10DeviceStatus(i) != null) { + Boolean status = getPGMX10DeviceStatus(i); + if (status != null) { str += String.format("\n - %s status = %s", (i == 0) ? "PGM device" : String.format("X10 device %d", i), - getPGMX10DeviceStatus(i) ? "ON" : "OFF"); + status ? "ON" : "OFF"); } } for (int i = 1; i <= zones.length; i++) { for (Value value : zones[i - 1].getValues()) { - if ((value.getChannel() != null) && (value.getValue() != null)) { + if (value.getValue() != null) { String channel = value.getChannel(); String vStr = value.getValue().toString(); String state = value.getState().toString(); @@ -530,13 +556,13 @@ public String toString() { } for (int i = 1; i <= getEventLogSize(); i++) { - if (getEventLog(i) != null) { - str += "\n - event log " + i + " = " + getEventLog(i); + String log = getEventLog(i); + if (log != null) { + str += "\n - event log " + i + " = " + log; } } - String alarms = getActiveAlerts(); - str += "\n - active alarms/alerts = " + (alarms == null ? "null" : alarms); + str += "\n - active alarms/alerts = " + getActiveAlerts(); return str; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateContainer.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateContainer.java index f5cb70b918a45..da69de859ac36 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateContainer.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateContainer.java @@ -18,18 +18,21 @@ import java.util.List; import java.util.function.Supplier; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; /** * Base class for extensible state objects * * @author Ron Isaacson - Initial contribution */ +@NonNullByDefault public abstract class PowermaxStateContainer { protected final TimeZoneProvider timeZoneProvider; @@ -46,7 +49,7 @@ public Value(PowermaxStateContainer parent, String channel) { parent.getValues().add(this); } - public T getValue() { + public @Nullable T getValue() { return value; } @@ -67,10 +70,10 @@ public String getChannel() { } public class DynamicValue extends Value { - Supplier valueFunction; + Supplier<@Nullable T> valueFunction; Supplier stateFunction; - public DynamicValue(PowermaxStateContainer parent, String channel, Supplier valueFunction, + public DynamicValue(PowermaxStateContainer parent, String channel, Supplier<@Nullable T> valueFunction, Supplier stateFunction) { super(parent, channel); this.valueFunction = valueFunction; @@ -80,7 +83,7 @@ public DynamicValue(PowermaxStateContainer parent, String channel, Supplier v // Note: setValue() is still valid, but the saved value will be ignored @Override - public T getValue() { + public @Nullable T getValue() { return valueFunction.get(); } @@ -106,7 +109,8 @@ public BooleanValue(PowermaxStateContainer parent, String channel) { @Override public State getState() { - return value ? trueState : falseState; + Boolean val = value; + return val == null ? UnDefType.NULL : (val ? trueState : falseState); } } @@ -117,7 +121,8 @@ public StringValue(PowermaxStateContainer parent, String channel) { @Override public State getState() { - return new StringType(value); + String val = value; + return val == null ? UnDefType.NULL : new StringType(val); } } @@ -128,7 +133,11 @@ public DateTimeValue(PowermaxStateContainer parent, String channel) { @Override public State getState() { - ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(value), timeZoneProvider.getTimeZone()); + Long val = value; + if (val == null) { + return UnDefType.NULL; + } + ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(val), timeZoneProvider.getTimeZone()); return new DateTimeType(zoned); } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEvent.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEvent.java index 3c4a209cf04f6..3b65ec8d02e2d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEvent.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEvent.java @@ -14,11 +14,14 @@ import java.util.EventObject; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Event for state received from the Visonic alarm panel * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxStateEvent extends EventObject { private static final long serialVersionUID = 1L; diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEventListener.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEventListener.java index f4e24abc49947..436a4d932f7f4 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEventListener.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxStateEventListener.java @@ -15,11 +15,14 @@ import java.util.EventListener; import java.util.EventObject; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Powermax Alarm state Listener interface. Handles Powermax Alarm state events * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public interface PowermaxStateEventListener extends EventListener { /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxX10Settings.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxX10Settings.java index 6029f2f0985e5..8c34b224b60a8 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxX10Settings.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxX10Settings.java @@ -12,17 +12,21 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * A class to store the settings of an X10 device * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxX10Settings { - private String name; + private @Nullable String name; private boolean enabled; - public PowermaxX10Settings(String name, boolean enabled) { + public PowermaxX10Settings(@Nullable String name, boolean enabled) { this.name = name; this.enabled = enabled; } @@ -30,7 +34,7 @@ public PowermaxX10Settings(String name, boolean enabled) { /** * @return the name of the X10 device */ - public String getName() { + public @Nullable String getName() { return name; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneName.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneName.java index 68e00cd2c1182..fda120caa7e51 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneName.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneName.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * All panel zone names * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public enum PowermaxZoneName { ZONE_0(0, "Attic"), diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneSettings.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneSettings.java index d5802e5394c61..6c59cd20fc52e 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneSettings.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneSettings.java @@ -12,11 +12,15 @@ */ package org.openhab.binding.powermax.internal.state; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * A class to store the settings of a zone * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxZoneSettings { // Note: PowermaxStatusMessage contains hardcoded references to some of these strings @@ -27,14 +31,15 @@ public class PowermaxZoneSettings { private static final String[] ZONE_CHIMES = { "Off", "Melody", "Zone" }; - private String name; - private String type; - private String chime; - private String sensorType; + private @Nullable String name; + private @Nullable String type; + private @Nullable String chime; + private @Nullable String sensorType; private boolean[] partitions; private boolean alwaysInAlarm; - public PowermaxZoneSettings(String name, byte type, byte chime, String sensorType, boolean[] partitions) { + public PowermaxZoneSettings(@Nullable String name, byte type, byte chime, @Nullable String sensorType, + boolean[] partitions) { this.name = name; this.type = ((type & 0x000000FF) < ZONE_TYPES.length) ? ZONE_TYPES[type & 0x000000FF] : null; this.chime = ((chime & 0x000000FF) < ZONE_CHIMES.length) ? ZONE_CHIMES[chime & 0x000000FF] : null; @@ -48,7 +53,8 @@ public PowermaxZoneSettings(String name, byte type, byte chime, String sensorTyp * @return the zone name */ public String getName() { - return (name == null) ? "Unknown" : name; + String localName = name; + return (localName == null) ? "Unknown" : localName; } /** @@ -56,7 +62,7 @@ public String getName() { * * @param name the zone name */ - public void setName(String name) { + public void setName(@Nullable String name) { this.name = name; } @@ -64,7 +70,8 @@ public void setName(String name) { * @return the zone type */ public String getType() { - return (type == null) ? "Unknown" : type; + String localType = type; + return (localType == null) ? "Unknown" : localType; } /** @@ -79,14 +86,16 @@ public void setType(byte type) { } public String getChime() { - return (chime == null) ? "Unknown" : chime; + String localChime = chime; + return (localChime == null) ? "Unknown" : localChime; } /** * @return the sensor type of this zone */ public String getSensorType() { - return (sensorType == null) ? "Unknown" : sensorType; + String localSensorType = sensorType; + return (localSensorType == null) ? "Unknown" : localSensorType; } /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneState.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneState.java index b49fb0e0c641e..598c952cdea53 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneState.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/state/PowermaxZoneState.java @@ -14,14 +14,17 @@ import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.OpenClosedType; +import org.openhab.core.types.UnDefType; /** * A class to store the state of a zone * * @author Laurent Garnier - Initial contribution */ +@NonNullByDefault public class PowermaxZoneState extends PowermaxStateContainer { public BooleanValue tripped = new BooleanValue(this, TRIPPED, OpenClosedType.OPEN, OpenClosedType.CLOSED); @@ -41,7 +44,7 @@ public class PowermaxZoneState extends PowermaxStateContainer { }, () -> { Boolean isArmed = armed.getValue(); if (isArmed == null) { - return null; + return UnDefType.NULL; } return isArmed ? OpenClosedType.CLOSED : OpenClosedType.OPEN; }); @@ -51,7 +54,7 @@ public PowermaxZoneState(TimeZoneProvider timeZoneProvider) { } public boolean isLastTripBeforeTime(long refTime) { - return Boolean.TRUE.equals(tripped.getValue()) && (lastTripped.getValue() != null) - && (lastTripped.getValue() < refTime); + Long lastTrippedValue = lastTripped.getValue(); + return Boolean.TRUE.equals(tripped.getValue()) && (lastTrippedValue != null) && (lastTrippedValue < refTime); } }