2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.powermax.internal.state;
15 import java.util.HashMap;
19 * A class to store the state of the alarm system
21 * @author Laurent Garnier - Initial contribution
23 public class PowermaxState {
25 private Boolean powerlinkMode;
26 private Boolean downloadMode;
27 private PowermaxZoneState[] zones;
28 private Boolean[] pgmX10DevicesStatus;
29 private Boolean ready;
30 private Boolean bypass;
31 private Boolean alarmActive;
32 private Boolean trouble;
33 private Boolean alertInMemory;
34 private String statusStr;
35 private String armMode;
36 private Boolean downloadSetupRequired;
37 private Long lastKeepAlive;
38 private byte[] updateSettings;
39 private String panelStatus;
40 private String alarmType;
41 private String troubleType;
42 private String[] eventLog;
43 private Map<Integer, Byte> updatedZoneNames;
44 private Map<Integer, Integer> updatedZoneInfos;
47 * Constructor (default values)
49 public PowermaxState(PowermaxPanelSettings panelSettings) {
50 zones = new PowermaxZoneState[panelSettings.getNbZones()];
51 for (int i = 0; i < panelSettings.getNbZones(); i++) {
52 zones[i] = new PowermaxZoneState();
54 pgmX10DevicesStatus = new Boolean[panelSettings.getNbPGMX10Devices()];
55 updatedZoneNames = new HashMap<>();
56 updatedZoneInfos = new HashMap<>();
60 * Get the current mode (standard or Powerlink)
62 * @return true when the current mode is Powerlink; false when standard
64 public Boolean isPowerlinkMode() {
69 * Set the current mode (standard or Powerlink)
71 * @param powerlinkMode true for Powerlink or false for standard
73 public void setPowerlinkMode(Boolean powerlinkMode) {
74 this.powerlinkMode = powerlinkMode;
78 * Get whether or not the setup is being downloaded
80 * @return true when downloading the setup
82 public Boolean isDownloadMode() {
87 * Set whether or not the setup is being downloaded
89 * @param downloadMode true when downloading the setup
91 public void setDownloadMode(Boolean downloadMode) {
92 this.downloadMode = downloadMode;
96 * Get whether or not the zone sensor is tripped
98 * @param zone the index of the zone (first zone is index 1)
100 * @return true when the zone sensor is tripped
102 public Boolean isSensorTripped(int zone) {
103 return ((zone < 1) || (zone > zones.length)) ? null : zones[zone - 1].isTripped();
107 * Set whether or not the zone sensor is tripped
109 * @param zone the index of the zone (first zone is index 1)
110 * @param tripped true if tripped
112 public void setSensorTripped(int zone, Boolean tripped) {
113 if ((zone >= 1) && (zone <= zones.length)) {
114 this.zones[zone - 1].setTripped(tripped);
119 * Get the timestamp when the zone sensor was last tripped
121 * @param zone the index of the zone (first zone is index 1)
123 * @return the timestamp
125 public Long getSensorLastTripped(int zone) {
126 return ((zone < 1) || (zone > zones.length)) ? null : zones[zone - 1].getLastTripped();
130 * Set the timestamp when the zone sensor was last tripped
132 * @param zone the index of the zone (first zone is index 1)
133 * @param lastTripped the timestamp
135 public void setSensorLastTripped(int zone, Long lastTripped) {
136 if ((zone >= 1) && (zone <= zones.length)) {
137 this.zones[zone - 1].setLastTripped(lastTripped);
142 * Compare the sensor last trip with a given time
144 * @param zone the index of the zone (first zone is index 1)
145 * @param refTime the time in ms to compare with
147 * @return true if the sensor is tripped and last trip is older than the given time
149 public boolean isLastTripBeforeTime(int zone, long refTime) {
150 return ((zone < 1) || (zone > zones.length)) ? false : zones[zone - 1].isLastTripBeforeTime(refTime);
154 * Get whether or not the battery of the zone sensor is low
156 * @param zone the index of the zone (first zone is index 1)
158 * @return true when the battery is low
160 public Boolean isSensorLowBattery(int zone) {
161 return ((zone < 1) || (zone > zones.length)) ? null : zones[zone - 1].isLowBattery();
165 * Set whether or not the battery of the zone sensor is low
167 * @param zone the index of the zone (first zone is index 1)
168 * @param lowBattery true if battery is low
170 public void setSensorLowBattery(int zone, Boolean lowBattery) {
171 if ((zone >= 1) && (zone <= zones.length)) {
172 this.zones[zone - 1].setLowBattery(lowBattery);
177 * Get whether or not the zone sensor is bypassed
179 * @param zone the index of the zone (first zone is index 1)
181 * @return true if bypassed
183 public Boolean isSensorBypassed(int zone) {
184 return ((zone < 1) || (zone > zones.length)) ? null : zones[zone - 1].isBypassed();
188 * Set whether or not the zone sensor is bypassed
190 * @param zone the index of the zone (first zone is index 1)
191 * @param bypassed true if bypassed
193 public void setSensorBypassed(int zone, Boolean bypassed) {
194 if ((zone >= 1) && (zone <= zones.length)) {
195 this.zones[zone - 1].setBypassed(bypassed);
200 * Get whether or not the zone sensor is armed
202 * @param zone the index of the zone (first zone is index 1)
204 * @return true if armed
206 public Boolean isSensorArmed(int zone) {
207 return ((zone < 1) || (zone > zones.length)) ? null : zones[zone - 1].isArmed();
211 * Set whether or not the zone sensor is armed
213 * @param zone the index of the zone (first zone is index 1)
214 * @param armed true if armed
216 public void setSensorArmed(int zone, Boolean armed) {
217 if ((zone >= 1) && (zone <= zones.length)) {
218 this.zones[zone - 1].setArmed(armed);
223 * Get the status of a PGM or X10 device
225 * @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1)
227 * @return the status (true or false)
229 public Boolean getPGMX10DeviceStatus(int device) {
230 return ((device < 0) || (device >= pgmX10DevicesStatus.length)) ? null : pgmX10DevicesStatus[device];
234 * Set the status of a PGM or X10 device
236 * @param device the index of the PGM/X10 device (0 s for PGM; for X10 device is index 1)
237 * @param status true or false
239 public void setPGMX10DeviceStatus(int device, Boolean status) {
240 if ((device >= 0) && (device < pgmX10DevicesStatus.length)) {
241 this.pgmX10DevicesStatus[device] = status;
246 * Get whether or not the panel is ready
248 * @return true if ready
250 public Boolean isReady() {
255 * Set whether or not the panel is ready
257 * @param ready true if ready
259 public void setReady(Boolean ready) {
264 * Get whether or not at least one zone is bypassed
266 * @return true if at least one zone is bypassed
268 public Boolean isBypass() {
273 * Set whether or not at least one zone is bypassed
275 * @param bypass true if at least one zone is bypassed
277 public void setBypass(Boolean bypass) {
278 this.bypass = bypass;
282 * Get whether or not the alarm is active
284 * @return true if active
286 public Boolean isAlarmActive() {
291 * Set whether or not the alarm is active
293 * @param alarmActive true if the alarm is active
295 public void setAlarmActive(Boolean alarmActive) {
296 this.alarmActive = alarmActive;
300 * Get whether or not the panel is identifying a trouble
302 * @return true if the panel is identifying a trouble
304 public Boolean isTrouble() {
309 * Set whether or not the panel is identifying a trouble
311 * @param trouble true if trouble is identified
313 public void setTrouble(Boolean trouble) {
314 this.trouble = trouble;
318 * Get whether or not the panel has saved an alert in memory
320 * @return true if the panel has saved an alert in memory
322 public Boolean isAlertInMemory() {
323 return alertInMemory;
327 * Set whether or not the panel has saved an alert in memory
329 * @param alertInMemory true if an alert is saved in memory
331 public void setAlertInMemory(Boolean alertInMemory) {
332 this.alertInMemory = alertInMemory;
336 * Get the partition status
338 * @return the status as a short string
340 public String getStatusStr() {
345 * Set the partition status
347 * @param statusStr the status as a short string
349 public void setStatusStr(String statusStr) {
350 this.statusStr = statusStr;
354 * Get the arming name
356 * @return the arming mode
358 public String getArmMode() {
363 * Set the arming name
365 * @param armMode the arming name
367 public void setArmMode(String armMode) {
368 this.armMode = armMode;
372 * Get whether or not the setup downloading is required
374 * @return true when downloading the setup is required
376 public Boolean isDownloadSetupRequired() {
377 return downloadSetupRequired;
381 * Set whether or not the setup downloading is required
383 * @param downloadSetupRequired true when downloading setup is required
385 public void setDownloadSetupRequired(Boolean downloadSetupRequired) {
386 this.downloadSetupRequired = downloadSetupRequired;
390 * Get the timestamp of the last received "keep alive" message
392 * @return the timestamp
394 public Long getLastKeepAlive() {
395 return lastKeepAlive;
399 * Set the timestamp of the last received "keep alive" message
401 * @param lastKeepAlive the timestamp
403 public void setLastKeepAlive(Long lastKeepAlive) {
404 this.lastKeepAlive = lastKeepAlive;
408 * Get the raw buffer containing all the settings
410 * @return the raw buffer as a table of bytes
412 public byte[] getUpdateSettings() {
413 return updateSettings;
417 * Set the raw buffer containing all the settings
419 * @param updateSettings the raw buffer as a table of bytes
421 public void setUpdateSettings(byte[] updateSettings) {
422 this.updateSettings = updateSettings;
426 * Get the panel status
428 * @return the panel status
430 public String getPanelStatus() {
435 * Set the panel status
437 * @param panelStatus the status as a short string
439 public void setPanelStatus(String panelStatus) {
440 this.panelStatus = panelStatus;
444 * Get the kind of the current alarm identified by the panel
446 * @return the kind of the current alarm; null if no alarm
448 public String getAlarmType() {
453 * Set the kind of the current alarm identified by the panel
455 * @param alarmType the kind of alarm (set it to null if no alarm)
457 public void setAlarmType(String alarmType) {
458 this.alarmType = alarmType;
462 * Get the kind of the current trouble identified by the panel
464 * @return the kind of the current trouble; null if no trouble
466 public String getTroubleType() {
471 * Set the kind of the current trouble identified by the panel
473 * @param troubleType the kind of trouble (set it to null if no trouble)
475 public void setTroubleType(String troubleType) {
476 this.troubleType = troubleType;
480 * Get the number of entries in the event log
482 * @return the number of entries
484 public int getEventLogSize() {
485 return (eventLog == null) ? 0 : eventLog.length;
489 * Set the number of entries in the event log
491 * @param size the number of entries
493 public void setEventLogSize(int size) {
494 eventLog = new String[size];
498 * Get one entry from the event logs
500 * @param index the entry index (1 for the most recent entry)
502 * @return the entry value (event)
504 public String getEventLog(int index) {
505 return ((index < 1) || (index > getEventLogSize())) ? null : eventLog[index - 1];
509 * Set one entry from the event logs
511 * @param index the entry index (1 for the most recent entry)
512 * @param event the entry value (event)
514 public void setEventLog(int index, String event) {
515 if ((index >= 1) && (index <= getEventLogSize())) {
516 this.eventLog[index - 1] = event;
520 public Map<Integer, Byte> getUpdatedZoneNames() {
521 return updatedZoneNames;
524 public void updateZoneName(int zoneIdx, byte zoneNameIdx) {
525 this.updatedZoneNames.put(zoneIdx, zoneNameIdx);
528 public Map<Integer, Integer> getUpdatedZoneInfos() {
529 return updatedZoneInfos;
532 public void updateZoneInfo(int zoneIdx, int zoneInfo) {
533 this.updatedZoneInfos.put(zoneIdx, zoneInfo);
539 * @return either Download or Powerlink or Standard
541 public String getPanelMode() {
543 if (Boolean.TRUE.equals(downloadMode)) {
545 } else if (Boolean.TRUE.equals(powerlinkMode)) {
547 } else if (Boolean.FALSE.equals(powerlinkMode)) {
554 * Get whether or not the current arming mode is considered as armed
556 * @return true or false
558 public Boolean isArmed() {
559 return isArmed(getArmMode());
563 * Get whether or not an arming mode is considered as armed
565 * @param armMode the arming mode
567 * @return true or false; null if mode is unexpected
569 private static Boolean isArmed(String armMode) {
570 Boolean result = null;
571 if (armMode != null) {
573 PowermaxArmMode mode = PowermaxArmMode.fromName(armMode);
574 result = mode.isArmed();
575 } catch (IllegalArgumentException e) {
576 result = Boolean.FALSE;
583 * Get the short description associated to the current arming mode
585 * @return the short description
587 public String getShortArmMode() {
588 return getShortArmMode(getArmMode());
592 * Get the short name associated to an arming mode
594 * @param armMode the arming mode
596 * @return the short name or null if mode is unexpected
598 private static String getShortArmMode(String armMode) {
599 String result = null;
600 if (armMode != null) {
602 PowermaxArmMode mode = PowermaxArmMode.fromName(armMode);
603 result = mode.getShortName();
604 } catch (IllegalArgumentException e) {
612 * Keep only data that are different from another state and reset all others data to undefined
614 * @param otherState the other state
616 public void keepOnlyDifferencesWith(PowermaxState otherState) {
617 for (int i = 1; i <= zones.length; i++) {
618 if ((isSensorTripped(i) != null) && isSensorTripped(i).equals(otherState.isSensorTripped(i))) {
619 setSensorTripped(i, null);
621 if ((getSensorLastTripped(i) != null)
622 && getSensorLastTripped(i).equals(otherState.getSensorLastTripped(i))) {
623 setSensorLastTripped(i, null);
625 if ((isSensorLowBattery(i) != null) && isSensorLowBattery(i).equals(otherState.isSensorLowBattery(i))) {
626 setSensorLowBattery(i, null);
628 if ((isSensorBypassed(i) != null) && isSensorBypassed(i).equals(otherState.isSensorBypassed(i))) {
629 setSensorBypassed(i, null);
631 if ((isSensorArmed(i) != null) && isSensorArmed(i).equals(otherState.isSensorArmed(i))) {
632 setSensorArmed(i, null);
635 for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
636 if ((getPGMX10DeviceStatus(i) != null)
637 && getPGMX10DeviceStatus(i).equals(otherState.getPGMX10DeviceStatus(i))) {
638 setPGMX10DeviceStatus(i, null);
641 if ((ready != null) && ready.equals(otherState.isReady())) {
644 if ((bypass != null) && bypass.equals(otherState.isBypass())) {
647 if ((alarmActive != null) && alarmActive.equals(otherState.isAlarmActive())) {
650 if ((trouble != null) && trouble.equals(otherState.isTrouble())) {
653 if ((alertInMemory != null) && alertInMemory.equals(otherState.isAlertInMemory())) {
654 alertInMemory = null;
656 if ((statusStr != null) && statusStr.equals(otherState.getStatusStr())) {
659 if ((armMode != null) && armMode.equals(otherState.getArmMode())) {
662 if ((lastKeepAlive != null) && lastKeepAlive.equals(otherState.getLastKeepAlive())) {
663 lastKeepAlive = null;
665 if ((panelStatus != null) && panelStatus.equals(otherState.getPanelStatus())) {
668 if ((alarmType != null) && alarmType.equals(otherState.getAlarmType())) {
671 if ((troubleType != null) && troubleType.equals(otherState.getTroubleType())) {
677 * Update (override) the current state data from another state, ignoring in this other state
680 * @param update the other state to consider for the update
682 public void merge(PowermaxState update) {
683 if (update.isPowerlinkMode() != null) {
684 powerlinkMode = update.isPowerlinkMode();
686 if (update.isDownloadMode() != null) {
687 downloadMode = update.isDownloadMode();
689 for (int i = 1; i <= zones.length; i++) {
690 if (update.isSensorTripped(i) != null) {
691 setSensorTripped(i, update.isSensorTripped(i));
693 if (update.getSensorLastTripped(i) != null) {
694 setSensorLastTripped(i, update.getSensorLastTripped(i));
696 if (update.isSensorLowBattery(i) != null) {
697 setSensorLowBattery(i, update.isSensorLowBattery(i));
699 if (update.isSensorBypassed(i) != null) {
700 setSensorBypassed(i, update.isSensorBypassed(i));
702 if (update.isSensorArmed(i) != null) {
703 setSensorArmed(i, update.isSensorArmed(i));
706 for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
707 if (update.getPGMX10DeviceStatus(i) != null) {
708 setPGMX10DeviceStatus(i, update.getPGMX10DeviceStatus(i));
711 if (update.isReady() != null) {
712 ready = update.isReady();
714 if (update.isBypass() != null) {
715 bypass = update.isBypass();
717 if (update.isAlarmActive() != null) {
718 alarmActive = update.isAlarmActive();
720 if (update.isTrouble() != null) {
721 trouble = update.isTrouble();
723 if (update.isAlertInMemory() != null) {
724 alertInMemory = update.isAlertInMemory();
726 if (update.getStatusStr() != null) {
727 statusStr = update.getStatusStr();
729 if (update.getArmMode() != null) {
730 armMode = update.getArmMode();
732 if (update.getLastKeepAlive() != null) {
733 lastKeepAlive = update.getLastKeepAlive();
735 if (update.getPanelStatus() != null) {
736 panelStatus = update.getPanelStatus();
738 if (update.getAlarmType() != null) {
739 alarmType = update.getAlarmType();
741 if (update.getTroubleType() != null) {
742 troubleType = update.getTroubleType();
744 if (update.getEventLogSize() > getEventLogSize()) {
745 setEventLogSize(update.getEventLogSize());
747 for (int i = 1; i <= getEventLogSize(); i++) {
748 if (update.getEventLog(i) != null) {
749 setEventLog(i, update.getEventLog(i));
755 public String toString() {
758 if (powerlinkMode != null) {
759 str += "\n - powerlink mode = " + (powerlinkMode ? "yes" : "no");
761 if (downloadMode != null) {
762 str += "\n - download mode = " + (downloadMode ? "yes" : "no");
764 for (int i = 1; i <= zones.length; i++) {
765 if (isSensorTripped(i) != null) {
766 str += String.format("\n - sensor zone %d %s", i, isSensorTripped(i) ? "tripped" : "untripped");
768 if (getSensorLastTripped(i) != null) {
769 str += String.format("\n - sensor zone %d last trip %d", i, getSensorLastTripped(i));
771 if (isSensorLowBattery(i) != null) {
772 str += String.format("\n - sensor zone %d %s", i, isSensorLowBattery(i) ? "low battery" : "battery ok");
774 if (isSensorBypassed(i) != null) {
775 str += String.format("\n - sensor zone %d %sbypassed", i, isSensorBypassed(i) ? "" : "not ");
777 if (isSensorArmed(i) != null) {
778 str += String.format("\n - sensor zone %d %s", i, isSensorArmed(i) ? "armed" : "disarmed");
781 for (int i = 0; i < pgmX10DevicesStatus.length; i++) {
782 if (getPGMX10DeviceStatus(i) != null) {
783 str += String.format("\n - %s status = %s", (i == 0) ? "PGM device" : String.format("X10 device %d", i),
784 getPGMX10DeviceStatus(i) ? "ON" : "OFF");
788 str += "\n - ready = " + (ready ? "yes" : "no");
790 if (bypass != null) {
791 str += "\n - bypass = " + (bypass ? "yes" : "no");
793 if (alarmActive != null) {
794 str += "\n - alarm active = " + (alarmActive ? "yes" : "no");
796 if (trouble != null) {
797 str += "\n - trouble = " + (trouble ? "yes" : "no");
799 if (alertInMemory != null) {
800 str += "\n - alert in memory = " + (alertInMemory ? "yes" : "no");
802 if (statusStr != null) {
803 str += "\n - status = " + statusStr;
805 if (armMode != null) {
806 str += "\n - arm mode = " + armMode;
808 if (lastKeepAlive != null) {
809 str += "\n - last keep alive = " + lastKeepAlive;
811 if (panelStatus != null) {
812 str += "\n - panel status = " + panelStatus;
814 if (alarmType != null) {
815 str += "\n - alarm type = " + alarmType;
817 if (troubleType != null) {
818 str += "\n - trouble type = " + troubleType;
820 for (int i = 1; i <= getEventLogSize(); i++) {
821 if (getEventLog(i) != null) {
822 str += "\n - event log " + i + " = " + getEventLog(i);