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