mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[powermax] Add null annotations (#11275)
Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
parent
2b5431df00
commit
99f595450a
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import java.io.OutputStream;
|
||||
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,17 +32,19 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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;
|
||||
protected final String readerThreadName;
|
||||
private final List<PowermaxMessageEventListener> listeners = new ArrayList<>();
|
||||
|
||||
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<PowermaxMessageEventListener> listeners = new ArrayList<>();
|
||||
|
||||
public PowermaxConnector(String readerThreadName) {
|
||||
this.readerThreadName = readerThreadName;
|
||||
@ -58,26 +62,29 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
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 +114,20 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
/**
|
||||
* 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 +136,11 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
|
||||
@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 +156,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
/**
|
||||
* @return the input stream
|
||||
*/
|
||||
public InputStream getInput() {
|
||||
public @Nullable InputStream getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@ -150,14 +165,14 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
*
|
||||
* @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 +181,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
*
|
||||
* @param output the output stream
|
||||
*/
|
||||
public void setOutput(OutputStream output) {
|
||||
public void setOutput(@Nullable OutputStream output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@ -190,7 +205,7 @@ public abstract class PowermaxConnector implements PowermaxConnectorInterface {
|
||||
/**
|
||||
* @return the thread that handles the message reading
|
||||
*/
|
||||
public Thread getReaderThread() {
|
||||
public @Nullable Thread getReaderThread() {
|
||||
return readerThread;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.powermax.internal.connector;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListener;
|
||||
|
||||
/**
|
||||
@ -21,6 +22,7 @@ import org.openhab.binding.powermax.internal.message.PowermaxMessageEventListene
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface PowermaxConnectorInterface {
|
||||
|
||||
/**
|
||||
|
@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
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,14 +28,15 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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 PowermaxConnector connector;
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxReaderThread.class);
|
||||
|
||||
private final PowermaxConnector connector;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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 class PowermaxSerialConnector extends PowermaxConnector implements Serial
|
||||
this.serialPortManager = serialPortManager;
|
||||
this.serialPortName = serialPortName;
|
||||
this.baudRate = baudRate;
|
||||
this.serialPort = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,26 +69,31 @@ public class PowermaxSerialConnector extends PowermaxConnector implements Serial
|
||||
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 class PowermaxSerialConnector extends PowermaxConnector implements Serial
|
||||
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;
|
||||
|
@ -18,6 +18,8 @@ import java.net.Socket;
|
||||
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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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 class PowermaxTcpConnector extends PowermaxConnector {
|
||||
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 class PowermaxTcpConnector extends PowermaxConnector {
|
||||
|
||||
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());
|
||||
}
|
||||
|
@ -15,7 +15,9 @@ package org.openhab.binding.powermax.internal.console;
|
||||
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.Thing;
|
||||
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 @@ import org.osgi.service.component.annotations.Reference;
|
||||
*
|
||||
* @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 class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
|
||||
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 class PowermaxCommandExtension extends AbstractConsoleCommandExtension {
|
||||
buildCommandUsage("<bridgeUID> " + DOWNLOAD_SETUP, "download setup"),
|
||||
buildCommandUsage("<bridgeUID> " + BRIDGE_STATE, "show current state") });
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setThingRegistry(ThingRegistry thingRegistry) {
|
||||
this.thingRegistry = thingRegistry;
|
||||
}
|
||||
|
||||
protected void unsetThingRegistry(ThingRegistry thingRegistry) {
|
||||
this.thingRegistry = null;
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +48,10 @@ import org.slf4j.LoggerFactory;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
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.PowermaxState;
|
||||
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,18 +62,12 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxBridgeHandler extends BaseBridgeHandler implements PowermaxStateEventListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxBridgeHandler.class);
|
||||
private final SerialPortManager serialPortManager;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
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,9 +76,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
|
||||
private static final int MAX_DOWNLOAD_ATTEMPTS = 3;
|
||||
|
||||
private ScheduledFuture<?> globalJob;
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxBridgeHandler.class);
|
||||
|
||||
private List<PowermaxPanelSettingsListener> listeners = new CopyOnWriteArrayList<>();
|
||||
private final SerialPortManager serialPortManager;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private final List<PowermaxPanelSettingsListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> globalJob;
|
||||
|
||||
/** The delay in milliseconds to reset a motion detection */
|
||||
private long motionOffDelay;
|
||||
@ -96,7 +98,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 +106,8 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
super(thing);
|
||||
this.serialPortManager = serialPortManager;
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.pinCode = "";
|
||||
this.currentState = new PowermaxState(new PowermaxPanelSettings(DEFAULT_PANEL_TYPE), timeZoneProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -111,12 +115,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +143,8 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
}
|
||||
|
||||
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 +153,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
updateRingingState();
|
||||
if (isConnected()) {
|
||||
checkKeepAlive();
|
||||
commManager.retryDownloadSetup(remainingDownloadAttempts);
|
||||
retryDownloadSetup();
|
||||
} else {
|
||||
tryReconnect();
|
||||
}
|
||||
@ -160,30 +167,27 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
}
|
||||
}
|
||||
|
||||
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 +196,24 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +224,9 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
@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 +239,15 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* 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 +264,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* 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 +283,33 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* 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 +320,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
updateChannelsFromAlarmState(MODE, currentState);
|
||||
processPanelSettings();
|
||||
} else {
|
||||
commManager.startDownload();
|
||||
localCommManager.startDownload();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("openConnection(): {}", e.getMessage(), e);
|
||||
@ -320,9 +335,10 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* @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 +347,24 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* 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 +372,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +409,81 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
}
|
||||
|
||||
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 +491,17 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
}
|
||||
|
||||
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 +509,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
&& 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 +519,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
// 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 +536,6 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +549,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
if (doProcessSettings) {
|
||||
// There is a change of mode (standard or Powerlink)
|
||||
processPanelSettings();
|
||||
commManager.exitDownload();
|
||||
localCommManager.exitDownload();
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,9 +560,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
}
|
||||
|
||||
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 +580,10 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +592,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
*
|
||||
* @param state: the alarm system state
|
||||
*/
|
||||
private void updateChannelsFromAlarmState(PowermaxState state) {
|
||||
private void updateChannelsFromAlarmState(@Nullable PowermaxState state) {
|
||||
updateChannelsFromAlarmState(null, state);
|
||||
}
|
||||
|
||||
@ -547,7 +602,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* @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 +610,16 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +628,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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 +659,14 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
* Update properties to match the alarm panel settings
|
||||
*/
|
||||
private void updatePropertiesFromPanelSettings() {
|
||||
PowermaxPanelSettings panelSettings = getPanelSettings();
|
||||
if (panelSettings == null) {
|
||||
return;
|
||||
}
|
||||
String value;
|
||||
Map<String, String> 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 +696,13 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax
|
||||
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;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ package org.openhab.binding.powermax.internal.handler;
|
||||
|
||||
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,16 +45,17 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPanelSettingsListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class);
|
||||
|
||||
private static final int ZONE_NR_MIN = 1;
|
||||
private static final int ZONE_NR_MAX = 64;
|
||||
private static final int X10_NR_MIN = 1;
|
||||
private static final int X10_NR_MAX = 16;
|
||||
|
||||
private PowermaxBridgeHandler bridgeHandler;
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class);
|
||||
|
||||
private @Nullable PowermaxBridgeHandler bridgeHandler;
|
||||
|
||||
public PowermaxThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -77,7 +79,7 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
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 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
|
||||
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 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
}
|
||||
} 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 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
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 @@ public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
@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 class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
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 class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
}
|
||||
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 class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
* @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 class PowermaxThingHandler extends BaseThingHandler implements PowermaxPa
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxAckMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,14 +35,15 @@ public class PowermaxAckMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@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);
|
||||
|
@ -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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxBaseMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxBaseMessage.class);
|
||||
|
||||
private byte[] rawData;
|
||||
private final 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,41 @@ public class PowermaxBaseMessage {
|
||||
* @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];
|
||||
this.rawData = new byte[sendType.getMessage().length + 3];
|
||||
int index = 0;
|
||||
message[index++] = 0x0D;
|
||||
rawData[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))) {
|
||||
rawData[index++] = param[i - paramPosition];
|
||||
} else {
|
||||
message[index++] = sendType.getMessage()[i];
|
||||
rawData[index++] = sendType.getMessage()[i];
|
||||
}
|
||||
}
|
||||
message[index++] = 0x00;
|
||||
message[index++] = 0x0A;
|
||||
decodeMessage(message);
|
||||
rawData[index++] = 0x00;
|
||||
rawData[index++] = 0x0A;
|
||||
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 +103,7 @@ public class PowermaxBaseMessage {
|
||||
*
|
||||
* @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 +122,7 @@ public class PowermaxBaseMessage {
|
||||
return newState;
|
||||
}
|
||||
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -140,18 +143,18 @@ public class PowermaxBaseMessage {
|
||||
/**
|
||||
* @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 +162,8 @@ public class PowermaxBaseMessage {
|
||||
* @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
|
||||
|
@ -23,6 +23,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
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,47 +51,49 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxCommManager.class);
|
||||
|
||||
private static final int DEFAULT_TCP_PORT = 80;
|
||||
private static final int TCP_CONNECTION_TIMEOUT = 5000;
|
||||
private static final int DEFAULT_BAUD_RATE = 9600;
|
||||
private static final int WAITING_DELAY_FOR_RESPONSE = 750;
|
||||
private static final long DELAY_BETWEEN_SETUP_DOWNLOADS = TimeUnit.SECONDS.toMillis(45);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxCommManager.class);
|
||||
|
||||
private final ScheduledExecutorService scheduler;
|
||||
|
||||
/** The object to store the current settings of the Powermax alarm system */
|
||||
private PowermaxPanelSettings panelSettings;
|
||||
|
||||
/** Panel type used when in standard mode */
|
||||
private PowermaxPanelType panelType;
|
||||
|
||||
private boolean forceStandardMode;
|
||||
private boolean autoSyncTime;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private List<PowermaxStateEventListener> listeners = new ArrayList<>();
|
||||
/** The object to store the current settings of the Powermax alarm system */
|
||||
private final PowermaxPanelSettings panelSettings;
|
||||
|
||||
/** Panel type used when in standard mode */
|
||||
private final PowermaxPanelType panelType;
|
||||
|
||||
private final boolean forceStandardMode;
|
||||
private final boolean autoSyncTime;
|
||||
|
||||
private final List<PowermaxStateEventListener> listeners = new ArrayList<>();
|
||||
|
||||
/** The serial or TCP connecter used to communicate with the Powermax alarm system */
|
||||
private PowermaxConnector connector;
|
||||
private final 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<PowermaxBaseMessage> 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 +114,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
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 +137,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
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 +148,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
*/
|
||||
public synchronized void addEventListener(PowermaxStateEventListener listener) {
|
||||
listeners.add(listener);
|
||||
if (connector != null) {
|
||||
connector.addEventListener(this);
|
||||
}
|
||||
connector.addEventListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,9 +157,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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 +167,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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 +178,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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 +188,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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 +206,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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 +219,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
/**
|
||||
* @return the last message sent to the Powermax alarm system
|
||||
*/
|
||||
public synchronized PowermaxBaseMessage getLastSendMsg() {
|
||||
public synchronized @Nullable PowermaxBaseMessage getLastSendMsg() {
|
||||
return lastSendMsg;
|
||||
}
|
||||
|
||||
@ -261,8 +247,9 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
|
||||
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 +336,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
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 +363,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
*
|
||||
* @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 +405,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
|
||||
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 +470,10 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
} 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 +490,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
|
||||
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 +530,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
|
||||
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 +556,9 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 +594,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
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 +609,7 @@ public class PowermaxCommManager implements PowermaxMessageEventListener {
|
||||
* @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());
|
||||
|
@ -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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxDeniedMessage extends PowermaxBaseMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxDeniedMessage.class);
|
||||
@ -36,14 +39,15 @@ public class PowermaxDeniedMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@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");
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@ public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxEventLogMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -33,7 +36,7 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxInfoMessage extends PowermaxBaseMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxInfoMessage.class);
|
||||
@ -37,7 +40,7 @@ public class PowermaxInfoMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -16,11 +16,14 @@ import static java.util.Map.entry;
|
||||
|
||||
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() {
|
||||
|
@ -14,15 +14,18 @@ package org.openhab.binding.powermax.internal.message;
|
||||
|
||||
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;
|
||||
private PowermaxBaseMessage message;
|
||||
private final PowermaxBaseMessage message;
|
||||
|
||||
public PowermaxMessageEvent(Object source, PowermaxBaseMessage message) {
|
||||
super(source);
|
||||
|
@ -15,11 +15,14 @@ package org.openhab.binding.powermax.internal.message;
|
||||
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 {
|
||||
|
||||
/**
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxPanelMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -33,7 +36,7 @@ public class PowermaxPanelMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxPowerMasterMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@ public class PowermaxPowerMasterMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxPowerlinkMessage extends PowermaxBaseMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxPowerlinkMessage.class);
|
||||
@ -36,7 +39,7 @@ public class PowermaxPowerlinkMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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),
|
||||
@ -36,9 +39,9 @@ public enum PowermaxReceiveType {
|
||||
POWERMASTER((byte) 0xB0, 0, true),
|
||||
F1((byte) 0xF1, 9, false);
|
||||
|
||||
private byte code;
|
||||
private int length;
|
||||
private boolean ackRequired;
|
||||
private final byte code;
|
||||
private final int length;
|
||||
private final boolean ackRequired;
|
||||
|
||||
private PowermaxReceiveType(byte code, int length, boolean ackRequired) {
|
||||
this.code = code;
|
||||
|
@ -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),
|
||||
@ -107,11 +111,12 @@ public enum PowermaxSendType {
|
||||
POWERMASTER_ZONE_TYPE1(new byte[] { (byte) 0xB0, 0x01, 0x2D, 0x02, 0x05, 0x00, 0x43 }, null,
|
||||
PowermaxReceiveType.POWERMASTER);
|
||||
|
||||
private byte[] message;
|
||||
private Integer paramPosition;
|
||||
private PowermaxReceiveType expectedResponseType;
|
||||
private final byte[] message;
|
||||
private final @Nullable Integer paramPosition;
|
||||
private final @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 enum PowermaxSendType {
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ package org.openhab.binding.powermax.internal.message;
|
||||
|
||||
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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxSettingsMessage extends PowermaxBaseMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PowermaxSettingsMessage.class);
|
||||
@ -38,7 +41,7 @@ public class PowermaxSettingsMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ import java.math.BigInteger;
|
||||
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 @@ import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings;
|
||||
*
|
||||
* @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 class PowermaxStatusMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxTimeoutMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@ public class PowermaxTimeoutMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager != null) {
|
||||
commManager.sendMessage(PowermaxSendType.EXIT);
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxZonesNameMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@ public class PowermaxZonesNameMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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 @@ import org.openhab.binding.powermax.internal.state.PowermaxState;
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PowermaxZonesTypeMessage extends PowermaxBaseMessage {
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@ public class PowermaxZonesTypeMessage extends PowermaxBaseMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) {
|
||||
protected @Nullable PowermaxState handleMessageInternal(@Nullable PowermaxCommManager commManager) {
|
||||
if (commManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -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"),
|
||||
@ -26,8 +29,8 @@ public enum PowermasterSensorType {
|
||||
SENSOR_TYPE_5((byte) 0x2A, "Magnet"),
|
||||
SENSOR_TYPE_6((byte) 0xFE, "Wired");
|
||||
|
||||
private byte code;
|
||||
private String label;
|
||||
private final byte code;
|
||||
private final String label;
|
||||
|
||||
private PowermasterSensorType(byte code, String label) {
|
||||
this.code = code;
|
||||
|
@ -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),
|
||||
@ -42,11 +45,11 @@ public enum PowermaxArmMode {
|
||||
ARMED_HOME_INSTANT(20, "Armed Home Instant", "StayInstant", true, (byte) 0x14, false),
|
||||
ARMED_AWAY_INSTANT(21, "Armed Away Instant", "ArmedInstant", true, (byte) 0x15, false);
|
||||
|
||||
private int code;
|
||||
private String name;
|
||||
private String shortName;
|
||||
private boolean armed;
|
||||
private byte commandCode;
|
||||
private final int code;
|
||||
private final String name;
|
||||
private final String shortName;
|
||||
private final boolean armed;
|
||||
private final byte commandCode;
|
||||
private boolean allowedCommand;
|
||||
|
||||
private PowermaxArmMode(int code, String name, String shortName, boolean armed, byte commandCode,
|
||||
|
@ -18,6 +18,8 @@ import java.util.Calendar;
|
||||
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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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 class PowermaxPanelSettings {
|
||||
/**
|
||||
* @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 class PowermaxPanelSettings {
|
||||
*
|
||||
* @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 class PowermaxPanelSettings {
|
||||
*
|
||||
* @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 class PowermaxPanelSettings {
|
||||
*
|
||||
* @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 class PowermaxPanelSettings {
|
||||
* @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 class PowermaxPanelSettings {
|
||||
* @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 class PowermaxPanelSettings {
|
||||
* @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 class PowermaxPanelSettings {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class PowermaxPanelSettings {
|
||||
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 @@ public class PowermaxPanelSettings {
|
||||
*
|
||||
* @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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
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 class PowermaxPanelSettings {
|
||||
}
|
||||
}
|
||||
|
||||
pinCodes = localPinCodes;
|
||||
keypad1wEnrolled = localKeypad1wEnrolled;
|
||||
keypad2wEnrolled = localKeypad2wEnrolled;
|
||||
sirensEnrolled = localSirensEnrolled;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
@ -29,19 +32,19 @@ public enum PowermaxPanelType {
|
||||
POWERMASTER_10((byte) 7, "PowerMaster10", 3, 250, 8, 0, 8, 4, 8, 8, 29, 1, 5),
|
||||
POWERMASTER_30((byte) 8, "PowerMaster30", 3, 1000, 32, 0, 32, 8, 48, 32, 62, 2, 5);
|
||||
|
||||
private byte code;
|
||||
private String label;
|
||||
private int partitions;
|
||||
private int events;
|
||||
private int keyfobs;
|
||||
private int keypads1w;
|
||||
private int keypads2w;
|
||||
private int sirens;
|
||||
private int userCodes;
|
||||
private int prontags;
|
||||
private int wireless;
|
||||
private int wired;
|
||||
private int customZones;
|
||||
private final byte code;
|
||||
private final String label;
|
||||
private final int partitions;
|
||||
private final int events;
|
||||
private final int keyfobs;
|
||||
private final int keypads1w;
|
||||
private final int keypads2w;
|
||||
private final int sirens;
|
||||
private final int userCodes;
|
||||
private final int prontags;
|
||||
private final int wireless;
|
||||
private final int wired;
|
||||
private final int customZones;
|
||||
|
||||
private PowermaxPanelType(byte code, String label, int partitions, int events, int keyfobs, int keypads1w,
|
||||
int keypads2w, int sirens, int userCodes, int prontags, int wireless, int wired, int customZones) {
|
||||
|
@ -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"),
|
||||
@ -29,8 +32,8 @@ public enum PowermaxSensorType {
|
||||
MOTION_SENSOR_3((byte) 0x0C, "Motion"),
|
||||
WIRED_SENSOR((byte) 0x0F, "Wired");
|
||||
|
||||
private byte code;
|
||||
private String label;
|
||||
private final byte code;
|
||||
private final String label;
|
||||
|
||||
private PowermaxSensorType(byte code, String label) {
|
||||
this.code = code;
|
||||
|
@ -19,11 +19,13 @@ import java.util.HashMap;
|
||||
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 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @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<Boolean> 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<String> 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<String> 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<String> activeAlerts = new DynamicValue<>(this, ACTIVE_ALERTS, () -> {
|
||||
@ -82,14 +97,18 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
public DynamicValue<Boolean> 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<Integer, Byte> updatedZoneNames;
|
||||
private Map<Integer, Integer> updatedZoneInfos;
|
||||
private List<PowermaxActiveAlert> activeAlertList;
|
||||
@ -163,7 +182,7 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @return the raw buffer as a table of bytes
|
||||
*/
|
||||
public byte[] getUpdateSettings() {
|
||||
public byte @Nullable [] getUpdateSettings() {
|
||||
return updateSettings;
|
||||
}
|
||||
|
||||
@ -203,7 +222,8 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
* @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 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean isArmed() {
|
||||
public @Nullable Boolean isArmed() {
|
||||
return isArmed(armMode.getValue());
|
||||
}
|
||||
|
||||
@ -357,7 +380,7 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @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 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @return the short description
|
||||
*/
|
||||
public String getShortArmMode() {
|
||||
public @Nullable String getShortArmMode() {
|
||||
return getShortArmMode(armMode.getValue());
|
||||
}
|
||||
|
||||
@ -386,7 +409,7 @@ public class PowermaxState extends PowermaxStateContainer {
|
||||
*
|
||||
* @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 class PowermaxState extends PowermaxStateContainer {
|
||||
}
|
||||
|
||||
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 class PowermaxState extends PowermaxStateContainer {
|
||||
}
|
||||
|
||||
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 class PowermaxState extends PowermaxStateContainer {
|
||||
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 class PowermaxState extends PowermaxStateContainer {
|
||||
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 class PowermaxState extends PowermaxStateContainer {
|
||||
}
|
||||
|
||||
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 class PowermaxState extends PowermaxStateContainer {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -18,18 +18,21 @@ import java.util.ArrayList;
|
||||
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 abstract class PowermaxStateContainer {
|
||||
parent.getValues().add(this);
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
public @Nullable T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -67,10 +70,10 @@ public abstract class PowermaxStateContainer {
|
||||
}
|
||||
|
||||
public class DynamicValue<T> extends Value<T> {
|
||||
Supplier<T> valueFunction;
|
||||
Supplier<@Nullable T> valueFunction;
|
||||
Supplier<State> stateFunction;
|
||||
|
||||
public DynamicValue(PowermaxStateContainer parent, String channel, Supplier<T> valueFunction,
|
||||
public DynamicValue(PowermaxStateContainer parent, String channel, Supplier<@Nullable T> valueFunction,
|
||||
Supplier<State> stateFunction) {
|
||||
super(parent, channel);
|
||||
this.valueFunction = valueFunction;
|
||||
@ -80,7 +83,7 @@ public abstract class PowermaxStateContainer {
|
||||
// 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 abstract class PowermaxStateContainer {
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return value ? trueState : falseState;
|
||||
Boolean val = value;
|
||||
return val == null ? UnDefType.NULL : (val ? trueState : falseState);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +121,8 @@ public abstract class PowermaxStateContainer {
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return new StringType(value);
|
||||
String val = value;
|
||||
return val == null ? UnDefType.NULL : new StringType(val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +133,11 @@ public abstract class PowermaxStateContainer {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
@ -14,15 +14,18 @@ package org.openhab.binding.powermax.internal.state;
|
||||
|
||||
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;
|
||||
private PowermaxState state;
|
||||
private final PowermaxState state;
|
||||
|
||||
public PowermaxStateEvent(Object source, PowermaxState state) {
|
||||
super(source);
|
||||
|
@ -15,11 +15,14 @@ package org.openhab.binding.powermax.internal.state;
|
||||
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 {
|
||||
|
||||
/**
|
||||
|
@ -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 boolean enabled;
|
||||
private final @Nullable String name;
|
||||
private final 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 class PowermaxX10Settings {
|
||||
/**
|
||||
* @return the name of the X10 device
|
||||
*/
|
||||
public String getName() {
|
||||
public @Nullable String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -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"),
|
||||
@ -52,7 +55,7 @@ public enum PowermaxZoneName {
|
||||
ZONE_30(30, "Custom 5"),
|
||||
ZONE_31(31, "Not Installed");
|
||||
|
||||
private int id;
|
||||
private final int id;
|
||||
private String name;
|
||||
|
||||
private PowermaxZoneName(int id, String name) {
|
||||
|
@ -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,16 @@ 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 boolean[] partitions;
|
||||
private final @Nullable String chime;
|
||||
private final boolean[] partitions;
|
||||
|
||||
private @Nullable String name;
|
||||
private @Nullable String type;
|
||||
private @Nullable String sensorType;
|
||||
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 +54,8 @@ public class PowermaxZoneSettings {
|
||||
* @return the zone name
|
||||
*/
|
||||
public String getName() {
|
||||
return (name == null) ? "Unknown" : name;
|
||||
String localName = name;
|
||||
return (localName == null) ? "Unknown" : localName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,7 +63,7 @@ public class PowermaxZoneSettings {
|
||||
*
|
||||
* @param name the zone name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
public void setName(@Nullable String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ -64,7 +71,8 @@ public class PowermaxZoneSettings {
|
||||
* @return the zone type
|
||||
*/
|
||||
public String getType() {
|
||||
return (type == null) ? "Unknown" : type;
|
||||
String localType = type;
|
||||
return (localType == null) ? "Unknown" : localType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,14 +87,16 @@ public class PowermaxZoneSettings {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,14 +14,17 @@ package org.openhab.binding.powermax.internal.state;
|
||||
|
||||
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 class PowermaxZoneState extends PowermaxStateContainer {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user