[paradoxalarm] Handle multiple panels (#13641)

* Fixes #13640

Working with multiple Paradox panels

Tested with:
- rename things files;
- thing disable / enable on same instance of OpenHab;
- disable on one OpenHab instance > enable on other;

Everything works as espected.
All test passed even if no Login/Logout commands were sent to IP module

Signed-off-by: Silviu Chingaru <silviuchingaru@yahoo.com>
This commit is contained in:
Silviu Chingaru 2022-11-04 20:01:39 +02:00 committed by GitHub
parent 5654b9f97a
commit 1e07d1af03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 37 additions and 31 deletions

View File

@ -22,7 +22,6 @@ import org.openhab.binding.paradoxalarm.internal.communication.messages.HeaderMe
import org.openhab.binding.paradoxalarm.internal.communication.messages.IPPacket;
import org.openhab.binding.paradoxalarm.internal.communication.messages.IpMessagesConstants;
import org.openhab.binding.paradoxalarm.internal.communication.messages.ParadoxIPPacket;
import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel;
import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -368,7 +367,6 @@ public enum CommunicationState implements IResponseReceiver {
if (communicator != null) {
communicator.close();
}
ParadoxPanel.getInstance().dispose();
}
};

View File

@ -53,7 +53,7 @@ public class ParadoxDiscoveryService extends AbstractDiscoveryService {
protected void startScan() {
IParadoxCommunicator communicator = ip150BridgeHandler.getCommunicator();
if (communicator != null && communicator.isOnline()) {
ParadoxPanel panel = ParadoxPanel.getInstance();
ParadoxPanel panel = ip150BridgeHandler.getPanel();
discoverPanel(panel.getPanelInformation());
discoverPartitions(panel.getPartitions());
discoverZones(panel.getZones());

View File

@ -59,7 +59,8 @@ public abstract class EntityBaseHandler extends BaseThingHandler {
private void initializeDelayed() {
logger.debug("Start initializeDelayed() in {}", getThing().getUID());
ParadoxPanel panel = ParadoxPanel.getInstance();
ParadoxIP150BridgeHandler bridge = (ParadoxIP150BridgeHandler) getBridge().getHandler();
ParadoxPanel panel = bridge.getPanel();
// Asynchronous update not yet done
if (panel.getPanelInformation() == null) {
// Retry until reach MAX_WAIT_TIME

View File

@ -69,6 +69,7 @@ public class ParadoxIP150BridgeHandler extends BaseBridgeHandler
private final Logger logger = LoggerFactory.getLogger(ParadoxIP150BridgeHandler.class);
private IParadoxCommunicator communicator;
private ParadoxPanel panel = new ParadoxPanel();
private ParadoxIP150BridgeConfiguration config;
private @Nullable ScheduledFuture<?> refreshCacheUpdateSchedule;
@ -169,7 +170,6 @@ public class ParadoxIP150BridgeHandler extends BaseBridgeHandler
.withMaxPartitions(config.getMaxPartitions()).withMaxZones(config.getMaxZones())
.withScheduler(scheduler).withEncryption(config.isEncrypt()).build();
ParadoxPanel panel = ParadoxPanel.getInstance();
panel.setCommunicator(communicator);
Collection<IDataUpdateListener> listeners = Arrays.asList(panel, this);
@ -208,6 +208,7 @@ public class ParadoxIP150BridgeHandler extends BaseBridgeHandler
public void dispose() {
cancelSchedule(refreshCacheUpdateSchedule);
CommunicationState.logout(communicator);
panel.dispose();
super.dispose();
}
@ -323,6 +324,10 @@ public class ParadoxIP150BridgeHandler extends BaseBridgeHandler
return communicator;
}
public ParadoxPanel getPanel() {
return panel;
}
@Override
public void onSocketTimeOutOccurred(IOException exception) {
logger.warn("TIMEOUT! {} received message for socket timeout. ", this, exception);

View File

@ -49,7 +49,8 @@ public class ParadoxPanelHandler extends EntityBaseHandler {
@Override
protected void updateEntity() {
ParadoxPanel panel = ParadoxPanel.getInstance();
ParadoxIP150BridgeHandler bridge = (ParadoxIP150BridgeHandler) getBridge().getHandler();
ParadoxPanel panel = bridge.getPanel();
StringType panelState = panel.isOnline() ? STATE_ONLINE : STATE_OFFLINE;
updateState(PANEL_STATE_CHANNEL_UID, panelState);
ParadoxInformation panelInformation = panel.getPanelInformation();

View File

@ -80,7 +80,9 @@ public class ParadoxPartitionHandler extends EntityBaseHandler {
protected Partition getPartition() {
int index = calculateEntityIndex();
List<Partition> partitions = ParadoxPanel.getInstance().getPartitions();
ParadoxIP150BridgeHandler bridge = (ParadoxIP150BridgeHandler) getBridge().getHandler();
ParadoxPanel panel = bridge.getPanel();
List<Partition> partitions = panel.getPartitions();
if (partitions == null) {
logger.debug(
"Partitions collection of Paradox Panel object is null. Probably not yet initialized. Skipping update.");

View File

@ -42,7 +42,9 @@ public class ParadoxZoneHandler extends EntityBaseHandler {
@Override
protected void updateEntity() {
int index = calculateEntityIndex();
List<Zone> zones = ParadoxPanel.getInstance().getZones();
ParadoxIP150BridgeHandler bridge = (ParadoxIP150BridgeHandler) getBridge().getHandler();
ParadoxPanel panel = bridge.getPanel();
List<Zone> zones = panel.getZones();
if (zones == null) {
logger.debug(
"Zones collection of Paradox Panel object is null. Probably not yet initialized. Skipping update.");

View File

@ -24,10 +24,12 @@ import org.slf4j.LoggerFactory;
public abstract class Entity {
private final Logger logger = LoggerFactory.getLogger(Entity.class);
private ParadoxPanel panel;
private int id;
private String label;
public Entity(int id, String label) {
public Entity(ParadoxPanel panel, int id, String label) {
this.panel = panel;
this.id = id;
this.label = label.trim();
logger.debug("Creating entity with label: {} and ID: {}", label, id);
@ -49,6 +51,10 @@ public abstract class Entity {
this.label = label;
}
public ParadoxPanel getPanel() {
return panel;
}
@Override
public String toString() {
return "Entity [id=" + id + ", label=" + label + "]";

View File

@ -20,7 +20,6 @@ import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.paradoxalarm.internal.communication.IDataUpdateListener;
import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator;
import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException;
@ -38,9 +37,6 @@ public class ParadoxPanel implements IDataUpdateListener {
private final Logger logger = LoggerFactory.getLogger(ParadoxPanel.class);
@NonNull
private static ParadoxPanel paradoxPanel = new ParadoxPanel();
private ParadoxInformation panelInformation;
private List<Partition> partitions;
private List<Zone> zones;
@ -51,7 +47,7 @@ public class ParadoxPanel implements IDataUpdateListener {
private double dcLevel;
private ZonedDateTime panelTime;
private ParadoxPanel() {
public ParadoxPanel() {
this.parser = new EvoParser();
}
@ -69,10 +65,6 @@ public class ParadoxPanel implements IDataUpdateListener {
}
}
public static ParadoxPanel getInstance() {
return paradoxPanel;
}
public boolean isPanelSupported() {
PanelType panelType = panelInformation.getPanelType();
return panelType == PanelType.EVO48 || panelType == PanelType.EVO192 || panelType == PanelType.EVOHD;
@ -123,7 +115,7 @@ public class ParadoxPanel implements IDataUpdateListener {
zones = new ArrayList<>();
Map<Integer, String> zoneLabels = communicator.getZoneLabels();
for (int i = 0; i < zoneLabels.size(); i++) {
Zone zone = new Zone(i + 1, zoneLabels.get(i));
Zone zone = new Zone(this, i + 1, zoneLabels.get(i));
zones.add(zone);
}
return zones;
@ -133,7 +125,7 @@ public class ParadoxPanel implements IDataUpdateListener {
partitions = new ArrayList<>();
Map<Integer, String> partitionLabels = communicator.getPartitionLabels();
for (int i = 0; i < partitionLabels.size(); i++) {
Partition partition = new Partition(i + 1, partitionLabels.get(i));
Partition partition = new Partition(this, i + 1, partitionLabels.get(i));
partitions.add(partition);
logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState());
}

View File

@ -12,7 +12,6 @@
*/
package org.openhab.binding.paradoxalarm.internal.model;
import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator;
import org.openhab.binding.paradoxalarm.internal.communication.PartitionCommandRequest;
import org.openhab.binding.paradoxalarm.internal.communication.RequestType;
import org.openhab.binding.paradoxalarm.internal.communication.messages.CommandPayload;
@ -35,8 +34,8 @@ public class Partition extends Entity implements Commandable {
private PartitionState state = new PartitionState();
public Partition(int id, String label) {
super(id, label);
public Partition(ParadoxPanel panel, int id, String label) {
super(panel, id, label);
}
public PartitionState getState() {
@ -62,7 +61,6 @@ public class Partition extends Entity implements Commandable {
ParadoxIPPacket packet = new ParadoxIPPacket(payload.getBytes())
.setMessageType(HeaderMessageType.SERIAL_PASSTHRU_REQUEST);
PartitionCommandRequest request = new PartitionCommandRequest(RequestType.PARTITION_COMMAND, packet, null);
IParadoxCommunicator communicator = ParadoxPanel.getInstance().getCommunicator();
communicator.submitRequest(request);
getPanel().getCommunicator().submitRequest(request);
}
}

View File

@ -28,8 +28,8 @@ public class Zone extends Entity {
private ZoneState zoneState;
public Zone(int id, String label) {
super(id, label);
public Zone(ParadoxPanel panel, int id, String label) {
super(panel, id, label);
}
public ZoneState getZoneState() {

View File

@ -46,6 +46,7 @@ public class Main {
private static ScheduledExecutorService scheduler;
private static IParadoxCommunicator communicator;
private static ParadoxPanel panel;
public static void main(String[] args) {
readArguments(args);
@ -59,14 +60,14 @@ public class Main {
.withTcpPort(port).withMaxPartitions(4).withMaxZones(20).withScheduler(scheduler)
.withEncryption(true).build();
ParadoxPanel panel = ParadoxPanel.getInstance();
panel = new ParadoxPanel();
panel.setCommunicator(communicator);
communicator.setListeners(Arrays.asList(panel));
communicator.startLoginSequence();
scheduler.scheduleWithFixedDelay(() -> {
refreshMemoryMap(communicator, false);
refreshMemoryMap(panel, false);
}, 7, 5, TimeUnit.SECONDS);
} catch (Exception e) {
logger.error("Exception: ", e);
@ -74,10 +75,10 @@ public class Main {
}
}
private static void refreshMemoryMap(IParadoxCommunicator communicator, boolean withEpromValues) {
private static void refreshMemoryMap(ParadoxPanel panel, boolean withEpromValues) {
logger.debug("Refreshing memory map");
IParadoxCommunicator communicator = panel.getCommunicator();
communicator.refreshMemoryMap();
ParadoxPanel panel = ParadoxPanel.getInstance();
panel.getPartitions().stream().forEach(partition -> logger.debug("Partition={}", partition));
panel.getZones().stream().filter(zone -> zone.getId() == 19).forEach(zone -> logger.debug("Zone={}", zone));
logger.debug("PanelTime={}, ACLevel={}, DCLevel={}, BatteryLevel={}", panel.getPanelTime(), panel.getVdcLevel(),