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