]> git.basschouten.com Git - openhab-addons.git/blob
c2ca70e7f4a94fcbecd15170048b183534eaf067
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.paradoxalarm.internal.model;
14
15 import java.time.DateTimeException;
16 import java.time.LocalDateTime;
17 import java.time.ZonedDateTime;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.TimeZone;
22
23 import org.openhab.binding.paradoxalarm.internal.communication.IDataUpdateListener;
24 import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator;
25 import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException;
26 import org.openhab.binding.paradoxalarm.internal.parsers.EvoParser;
27 import org.openhab.binding.paradoxalarm.internal.parsers.IParadoxParser;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * The {@link ParadoxPanel} Composition class which contains all Paradox entities.
33  *
34  * @author Konstantin Polihronov - Initial contribution
35  */
36 public class ParadoxPanel implements IDataUpdateListener {
37
38     private final Logger logger = LoggerFactory.getLogger(ParadoxPanel.class);
39
40     private ParadoxInformation panelInformation;
41     private List<Partition> partitions;
42     private List<Zone> zones;
43     private IParadoxParser parser;
44     private IParadoxCommunicator communicator;
45     private double vdcLevel;
46     private double batteryLevel;
47     private double dcLevel;
48     private ZonedDateTime panelTime;
49
50     public ParadoxPanel() {
51         this.parser = new EvoParser();
52     }
53
54     public void createModelEntities() {
55         byte[] panelInfoBytes = communicator.getPanelInfoBytes();
56         panelInformation = new ParadoxInformation(panelInfoBytes, parser);
57
58         if (isPanelSupported()) {
59             logger.info("Paradox system is supported. Panel data retrieved={} ", panelInformation);
60             createPartitions();
61             createZones();
62         } else {
63             throw new ParadoxRuntimeException(
64                     "Unsupported panel type. Type: " + panelInformation.getPanelType().name());
65         }
66     }
67
68     public boolean isPanelSupported() {
69         PanelType panelType = panelInformation.getPanelType();
70         return panelType == PanelType.EVO48 || panelType == PanelType.EVO192 || panelType == PanelType.EVOHD;
71     }
72
73     public void updateEntitiesStates() {
74         if (!isOnline()) {
75             logger.debug("Not online. Unable to update entities states. ");
76             return;
77         }
78
79         List<byte[]> currentPartitionFlags = communicator.getPartitionFlags();
80         for (int i = 0; i < partitions.size(); i++) {
81             Partition partition = partitions.get(i);
82             if (i < currentPartitionFlags.size()) {
83                 partition.setState(parser.calculatePartitionState(currentPartitionFlags.get(i)));
84             } else {
85                 logger.debug("Partition flags collection is smaller than the number of partitions.");
86             }
87         }
88
89         ZoneStateFlags zoneStateFlags = communicator.getZoneStateFlags();
90         for (int i = 0; i < zones.size(); i++) {
91             Zone zone = zones.get(i);
92             zone.setZoneState(parser.calculateZoneState(zone.getId(), zoneStateFlags));
93         }
94
95         byte[] firstRamPage = communicator.getMemoryMap().getElement(0);
96         panelTime = constructPanelTime(firstRamPage);
97         vdcLevel = Math.max(0, (firstRamPage[25] & 0xFF) * (20.3 - 1.4) / 255.0 + 1.4);
98         dcLevel = Math.max(0, (firstRamPage[27] & 0xFF) * 22.8 / 255);
99         batteryLevel = Math.max(0, (firstRamPage[26] & 0xFF) * 22.8 / 255);
100     }
101
102     protected ZonedDateTime constructPanelTime(byte[] firstPage) {
103         try {
104             int year = firstPage[18] * 100 + firstPage[19];
105             return ZonedDateTime.of(
106                     LocalDateTime.of(year, firstPage[20], firstPage[21], firstPage[22], firstPage[23], firstPage[24]),
107                     TimeZone.getDefault().toZoneId());
108         } catch (DateTimeException e) {
109             logger.debug("Received exception during parsing panel time. Falling back to old time.", e);
110             return panelTime;
111         }
112     }
113
114     private List<Zone> createZones() {
115         zones = new ArrayList<>();
116         Map<Integer, String> zoneLabels = communicator.getZoneLabels();
117         for (int i = 0; i < zoneLabels.size(); i++) {
118             Zone zone = new Zone(this, i + 1, zoneLabels.get(i));
119             zones.add(zone);
120         }
121         return zones;
122     }
123
124     private List<Partition> createPartitions() {
125         partitions = new ArrayList<>();
126         Map<Integer, String> partitionLabels = communicator.getPartitionLabels();
127         for (int i = 0; i < partitionLabels.size(); i++) {
128             Partition partition = new Partition(this, i + 1, partitionLabels.get(i));
129             partitions.add(partition);
130             logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState());
131         }
132         return partitions;
133     }
134
135     @Override
136     public void update() {
137         if (panelInformation == null || partitions == null || zones == null) {
138             createModelEntities();
139         }
140         updateEntitiesStates();
141     }
142
143     public void dispose() {
144         this.panelInformation = null;
145         this.partitions = null;
146         this.zones = null;
147     }
148
149     public ParadoxInformation getPanelInformation() {
150         return panelInformation;
151     }
152
153     public List<Partition> getPartitions() {
154         return partitions;
155     }
156
157     public void setPartitions(List<Partition> partitions) {
158         this.partitions = partitions;
159     }
160
161     public List<Zone> getZones() {
162         return zones;
163     }
164
165     public void setZones(List<Zone> zones) {
166         this.zones = zones;
167     }
168
169     public boolean isOnline() {
170         return communicator != null && communicator.isOnline();
171     }
172
173     public double getVdcLevel() {
174         return vdcLevel;
175     }
176
177     public double getBatteryLevel() {
178         return batteryLevel;
179     }
180
181     public double getDcLevel() {
182         return dcLevel;
183     }
184
185     public ZonedDateTime getPanelTime() {
186         return panelTime;
187     }
188
189     public void setCommunicator(IParadoxCommunicator communicator) {
190         this.communicator = communicator;
191     }
192
193     public IParadoxCommunicator getCommunicator() {
194         return communicator;
195     }
196
197     @Override
198     public String toString() {
199         return "ParadoxPanel [panelInformation=" + panelInformation + "]";
200     }
201 }