]> git.basschouten.com Git - openhab-addons.git/blob
a6722222a38ace0a626508f29eda53048bd11cbd
[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.powermax.internal.state;
14
15 import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.Map;
19
20 import org.openhab.core.i18n.TimeZoneProvider;
21 import org.openhab.core.library.types.OnOffType;
22 import org.openhab.core.library.types.StringType;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * A class to store the state of the alarm system
28  *
29  * @author Laurent Garnier - Initial contribution
30  */
31 public class PowermaxState extends PowermaxStateContainer {
32
33     private final Logger logger = LoggerFactory.getLogger(PowermaxState.class);
34
35     // For values that are mapped to channels, use a channel name constant from
36     // PowermaxBindingConstants. For values used internally but not mapped to
37     // channels, use a unique name starting with "_".
38
39     public BooleanValue powerlinkMode = new BooleanValue(this, "_powerlink_mode");
40     public BooleanValue downloadMode = new BooleanValue(this, "_download_mode");
41     public BooleanValue ready = new BooleanValue(this, READY);
42     public BooleanValue bypass = new BooleanValue(this, WITH_ZONES_BYPASSED);
43     public BooleanValue alarmActive = new BooleanValue(this, ALARM_ACTIVE);
44     public BooleanValue trouble = new BooleanValue(this, TROUBLE);
45     public BooleanValue alertInMemory = new BooleanValue(this, ALERT_IN_MEMORY);
46     public StringValue statusStr = new StringValue(this, SYSTEM_STATUS);
47     public StringValue armMode = new StringValue(this, "_arm_mode");
48     public BooleanValue downloadSetupRequired = new BooleanValue(this, "_download_setup_required");
49     public DateTimeValue lastKeepAlive = new DateTimeValue(this, "_last_keepalive");
50     public StringValue panelStatus = new StringValue(this, "_panel_status");
51     public StringValue alarmType = new StringValue(this, "_alarm_type");
52     public StringValue troubleType = new StringValue(this, "_trouble_type");
53
54     public DynamicValue<Boolean> isArmed = new DynamicValue<>(this, SYSTEM_ARMED, () -> {
55         return isArmed();
56     }, () -> {
57         return isArmed() ? OnOffType.ON : OnOffType.OFF;
58     });
59
60     public DynamicValue<String> panelMode = new DynamicValue<>(this, MODE, () -> {
61         return getPanelMode();
62     }, () -> {
63         return new StringType(getPanelMode());
64     });
65
66     public DynamicValue<String> shortArmMode = new DynamicValue<>(this, ARM_MODE, () -> {
67         return getShortArmMode();
68     }, () -> {
69         return new StringType(getShortArmMode());
70     });
71
72     public DynamicValue<Boolean> pgmStatus = new DynamicValue<>(this, PGM_STATUS, () -> {
73         return getPGMX10DeviceStatus(0);
74     }, () -> {
75         return getPGMX10DeviceStatus(0) ? OnOffType.ON : OnOffType.OFF;
76     });
77
78     private PowermaxZoneState[] zones;
79     private Boolean[] pgmX10DevicesStatus;
80     private byte[] updateSettings;
81     private String[] eventLog;
82     private Map<Integer, Byte> updatedZoneNames;
83     private Map<Integer, Integer> updatedZoneInfos;
84
85     /**
86      * Constructor (default values)
87      */
88     public PowermaxState(PowermaxPanelSettings panelSettings, TimeZoneProvider timeZoneProvider) {
89         super(timeZoneProvider);
90
91         zones = new PowermaxZoneState[panelSettings.getNbZones()];
92         for (int i = 0; i < panelSettings.getNbZones(); i++) {
93             zones[i] = new PowermaxZoneState(timeZoneProvider);
94         }
95         pgmX10DevicesStatus = new Boolean[panelSettings.getNbPGMX10Devices()];
96         updatedZoneNames = new HashMap<>();
97         updatedZoneInfos = new HashMap<>();
98     }
99
100     /**
101      * Return the PowermaxZoneState object for a given zone. If the zone number is
102      * out of range, returns a dummy PowermaxZoneState object that won't be
103      * persisted. The return value is never null, so it's safe to chain method
104      * calls.
105      *
106      * @param zone the index of the zone (first zone is index 1)
107      * @return the zone state object (or a dummy zone state)
108      */
109     public PowermaxZoneState getZone(int zone) {
110         if ((zone < 1) || (zone > zones.length)) {
111             logger.warn("Received update for invalid zone {}", zone);
112             return new PowermaxZoneState(timeZoneProvider);
113         } else {
114             return zones[zone - 1];
115         }
116     }
117
118     /**
119      * Get the status of a PGM or X10 device
120      *
121      * @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1)
122      *
123      * @return the status (true or false)
124      */
125     public Boolean getPGMX10DeviceStatus(int device) {
126         return ((device < 0) || (device >= pgmX10DevicesStatus.length)) ? null : pgmX10DevicesStatus[device];
127     }
128
129     /**
130      * Set the status of a PGM or X10 device
131      *
132      * @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1)
133      * @param status true or false
134      */
135     public void setPGMX10DeviceStatus(int device, Boolean status) {
136         if ((device >= 0) && (device < pgmX10DevicesStatus.length)) {
137             this.pgmX10DevicesStatus[device] = status;
138         }
139     }
140
141     /**
142      * Get the raw buffer containing all the settings
143      *
144      * @return the raw buffer as a table of bytes
145      */
146     public byte[] getUpdateSettings() {
147         return updateSettings;
148     }
149
150     /**
151      * Set the raw buffer containing all the settings
152      *
153      * @param updateSettings the raw buffer as a table of bytes
154      */
155     public void setUpdateSettings(byte[] updateSettings) {
156         this.updateSettings = updateSettings;
157     }
158
159     /**
160      * Get the number of entries in the event log
161      *
162      * @return the number of entries
163      */
164     public int getEventLogSize() {
165         return (eventLog == null) ? 0 : eventLog.length;
166     }
167
168     /**
169      * Set the number of entries in the event log
170      *
171      * @param size the number of entries
172      */
173     public void setEventLogSize(int size) {
174         eventLog = new String[size];
175     }
176
177     /**
178      * Get one entry from the event logs
179      *
180      * @param index the entry index (1 for the most recent entry)
181      *
182      * @return the entry value (event)
183      */
184     public String getEventLog(int index) {
185         return ((index < 1) || (index > getEventLogSize())) ? null : eventLog[index - 1];
186     }
187
188     /**
189      * Set one entry from the event logs
190      *
191      * @param index the entry index (1 for the most recent entry)
192      * @param event the entry value (event)
193      */
194     public void setEventLog(int index, String event) {
195         if ((index >= 1) && (index <= getEventLogSize())) {
196             this.eventLog[index - 1] = event;
197         }
198     }
199
200     public Map<Integer, Byte> getUpdatedZoneNames() {
201         return updatedZoneNames;
202     }
203
204     public void updateZoneName(int zoneIdx, byte zoneNameIdx) {
205         this.updatedZoneNames.put(zoneIdx, zoneNameIdx);
206     }
207
208     public Map<Integer, Integer> getUpdatedZoneInfos() {
209         return updatedZoneInfos;
210     }
211
212     public void updateZoneInfo(int zoneIdx, int zoneInfo) {
213         this.updatedZoneInfos.put(zoneIdx, zoneInfo);
214     }
215
216     /**
217      * Get the panel mode
218      *
219      * @return either Download or Powerlink or Standard
220      */
221     public String getPanelMode() {
222         String mode = null;
223         if (Boolean.TRUE.equals(downloadMode.getValue())) {
224             mode = "Download";
225         } else if (Boolean.TRUE.equals(powerlinkMode.getValue())) {
226             mode = "Powerlink";
227         } else if (Boolean.FALSE.equals(powerlinkMode.getValue())) {
228             mode = "Standard";
229         }
230         return mode;
231     }
232
233     /**
234      * Get whether or not the current arming mode is considered as armed
235      *
236      * @return true or false
237      */
238     public Boolean isArmed() {
239         return isArmed(armMode.getValue());
240     }
241
242     /**
243      * Get whether or not an arming mode is considered as armed
244      *
245      * @param armMode the arming mode
246      *
247      * @return true or false; null if mode is unexpected
248      */
249     private static Boolean isArmed(String armMode) {
250         Boolean result = null;
251         if (armMode != null) {
252             try {
253                 PowermaxArmMode mode = PowermaxArmMode.fromName(armMode);
254                 result = mode.isArmed();
255             } catch (IllegalArgumentException e) {
256                 result = Boolean.FALSE;
257             }
258         }
259         return result;
260     }
261
262     /**
263      * Get the short description associated to the current arming mode
264      *
265      * @return the short description
266      */
267     public String getShortArmMode() {
268         return getShortArmMode(armMode.getValue());
269     }
270
271     /**
272      * Get the short name associated to an arming mode
273      *
274      * @param armMode the arming mode
275      *
276      * @return the short name or null if mode is unexpected
277      */
278     private static String getShortArmMode(String armMode) {
279         String result = null;
280         if (armMode != null) {
281             try {
282                 PowermaxArmMode mode = PowermaxArmMode.fromName(armMode);
283                 result = mode.getShortName();
284             } catch (IllegalArgumentException e) {
285                 result = armMode;
286             }
287         }
288         return result;
289     }
290
291     /**
292      * Keep only data that are different from another state and reset all others data to undefined
293      *
294      * @param otherState the other state
295      */
296     public void keepOnlyDifferencesWith(PowermaxState otherState) {
297         for (int zone = 1; zone <= zones.length; zone++) {
298             PowermaxZoneState thisZone = getZone(zone);
299             PowermaxZoneState otherZone = otherState.getZone(zone);
300
301             for (int i = 0; i < thisZone.getValues().size(); i++) {
302                 Value<?> thisValue = thisZone.getValues().get(i);
303                 Value<?> otherValue = otherZone.getValues().get(i);
304
305                 if ((thisValue.getValue() != null) && thisValue.getValue().equals(otherValue.getValue())) {
306                     thisValue.setValue(null);
307                 }
308             }
309         }
310
311         for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
312             if ((getPGMX10DeviceStatus(i) != null)
313                     && getPGMX10DeviceStatus(i).equals(otherState.getPGMX10DeviceStatus(i))) {
314                 setPGMX10DeviceStatus(i, null);
315             }
316         }
317
318         for (int i = 0; i < getValues().size(); i++) {
319             Value<?> thisValue = getValues().get(i);
320             Value<?> otherValue = otherState.getValues().get(i);
321
322             if ((thisValue.getValue() != null) && thisValue.getValue().equals(otherValue.getValue())) {
323                 thisValue.setValue(null);
324             }
325         }
326     }
327
328     /**
329      * Update (override) the current state data from another state, ignoring in this other state
330      * the undefined data
331      *
332      * @param update the other state to consider for the update
333      */
334     public void merge(PowermaxState update) {
335         for (int zone = 1; zone <= zones.length; zone++) {
336             PowermaxZoneState thisZone = getZone(zone);
337             PowermaxZoneState otherZone = update.getZone(zone);
338
339             for (int i = 0; i < thisZone.getValues().size(); i++) {
340                 Value<?> thisValue = thisZone.getValues().get(i);
341                 Value<?> otherValue = otherZone.getValues().get(i);
342
343                 if (otherValue.getValue() != null) {
344                     thisValue.setValueUnsafe(otherValue.getValue());
345                 }
346             }
347         }
348
349         for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
350             if (update.getPGMX10DeviceStatus(i) != null) {
351                 setPGMX10DeviceStatus(i, update.getPGMX10DeviceStatus(i));
352             }
353         }
354
355         for (int i = 0; i < getValues().size(); i++) {
356             Value<?> thisValue = getValues().get(i);
357             Value<?> otherValue = update.getValues().get(i);
358
359             if (otherValue.getValue() != null) {
360                 thisValue.setValueUnsafe(otherValue.getValue());
361             }
362         }
363
364         if (update.getEventLogSize() > getEventLogSize()) {
365             setEventLogSize(update.getEventLogSize());
366         }
367         for (int i = 1; i <= getEventLogSize(); i++) {
368             if (update.getEventLog(i) != null) {
369                 setEventLog(i, update.getEventLog(i));
370             }
371         }
372     }
373
374     @Override
375     public String toString() {
376         String str = "Bridge state:";
377
378         for (Value<?> value : getValues()) {
379             if ((value.getChannel() != null) && (value.getValue() != null)) {
380                 String channel = value.getChannel();
381                 String v_str = value.getValue().toString();
382                 String state = value.getState().toString();
383
384                 str += "\n - " + channel + " = " + v_str;
385                 if (!v_str.equals(state)) {
386                     str += " (" + state + ")";
387                 }
388             }
389         }
390
391         for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
392             if (getPGMX10DeviceStatus(i) != null) {
393                 str += String.format("\n - %s status = %s", (i == 0) ? "PGM device" : String.format("X10 device %d", i),
394                         getPGMX10DeviceStatus(i) ? "ON" : "OFF");
395             }
396         }
397
398         for (int i = 1; i <= zones.length; i++) {
399             for (Value<?> value : zones[i - 1].getValues()) {
400                 if ((value.getChannel() != null) && (value.getValue() != null)) {
401                     String channel = value.getChannel();
402                     String v_str = value.getValue().toString();
403                     String state = value.getState().toString();
404
405                     str += String.format("\n - sensor zone %d %s = %s", i, channel, v_str);
406                     if (!v_str.equals(state)) {
407                         str += " (" + state + ")";
408                     }
409                 }
410             }
411         }
412
413         for (int i = 1; i <= getEventLogSize(); i++) {
414             if (getEventLog(i) != null) {
415                 str += "\n - event log " + i + " = " + getEventLog(i);
416             }
417         }
418
419         return str;
420     }
421 }