]> git.basschouten.com Git - openhab-addons.git/blob
154348e5bc5b586bc00dac7cab9fee6438857628
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.message;
14
15 import org.openhab.binding.powermax.internal.state.PowermaxState;
16 import org.openhab.core.util.HexUtils;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * A base class for handling a message with the Visonic alarm system
22  *
23  * @author Laurent Garnier - Initial contribution
24  */
25 public class PowermaxBaseMessage {
26
27     private final Logger logger = LoggerFactory.getLogger(PowermaxBaseMessage.class);
28
29     private byte[] rawData;
30     private int code;
31     private PowermaxSendType sendType;
32     private PowermaxReceiveType receiveType;
33
34     /**
35      * Constructor.
36      *
37      * @param message the message as a buffer of bytes
38      */
39     public PowermaxBaseMessage(byte[] message) {
40         this.sendType = null;
41         decodeMessage(message);
42     }
43
44     /**
45      * Constructor.
46      *
47      * @param sendType the type of a message to be sent
48      */
49     public PowermaxBaseMessage(PowermaxSendType sendType) {
50         this(sendType, null);
51     }
52
53     /**
54      * Constructor.
55      *
56      * @param sendType the type of a message to be sent
57      * @param param the dynamic part of a message to be sent; null if no dynamic part
58      */
59     public PowermaxBaseMessage(PowermaxSendType sendType, byte[] param) {
60         this.sendType = sendType;
61         byte[] message = new byte[sendType.getMessage().length + 3];
62         int index = 0;
63         message[index++] = 0x0D;
64         for (int i = 0; i < sendType.getMessage().length; i++) {
65             if ((param != null) && (sendType.getParamPosition() != null) && (i >= sendType.getParamPosition())
66                     && (i < (sendType.getParamPosition() + param.length))) {
67                 message[index++] = param[i - sendType.getParamPosition()];
68             } else {
69                 message[index++] = sendType.getMessage()[i];
70             }
71         }
72         message[index++] = 0x00;
73         message[index++] = 0x0A;
74         decodeMessage(message);
75     }
76
77     /**
78      * Extract information from the buffer of bytes and set class attributes
79      *
80      * @param data the message as a buffer of bytes
81      */
82     private void decodeMessage(byte[] data) {
83         rawData = data;
84         code = rawData[1] & 0x000000FF;
85         try {
86             receiveType = PowermaxReceiveType.fromCode((byte) code);
87         } catch (IllegalArgumentException e) {
88             receiveType = null;
89         }
90     }
91
92     /**
93      * Work to be done when receiving a message from the Visonic alarm system
94      *
95      * @return a new state containing all changes driven by the message
96      */
97     public PowermaxState handleMessage(PowermaxCommManager commManager) {
98         // Send an ACK if needed
99         if (isAckRequired() && commManager != null) {
100             commManager.sendAck(this, (byte) 0x02);
101         }
102
103         if (logger.isDebugEnabled()) {
104             logger.debug("{}message handled by class {}: {}", (receiveType == null) ? "Unsupported " : "",
105                     this.getClass().getSimpleName(), this);
106         }
107
108         return null;
109     }
110
111     /**
112      * @return the raw data of the message (buffer of bytes)
113      */
114     public byte[] getRawData() {
115         return rawData;
116     }
117
118     /**
119      * @return the identifying code of the message (second byte in the buffer)
120      */
121     public int getCode() {
122         return code;
123     }
124
125     /**
126      * @return the type of the message to be sent
127      */
128     public PowermaxSendType getSendType() {
129         return sendType;
130     }
131
132     public void setSendType(PowermaxSendType sendType) {
133         this.sendType = sendType;
134     }
135
136     /**
137      * @return the type of the received message
138      */
139     public PowermaxReceiveType getReceiveType() {
140         return receiveType;
141     }
142
143     /**
144      * @return true if the received message requires the sending of an ACK
145      */
146     public boolean isAckRequired() {
147         return receiveType == null || receiveType.isAckRequired();
148     }
149
150     @Override
151     public String toString() {
152         String str = "\n - Raw data = " + HexUtils.bytesToHex(rawData);
153         str += "\n - type = " + String.format("%02X", code);
154         if (sendType != null) {
155             str += " ( " + sendType.toString() + " )";
156         } else if (receiveType != null) {
157             str += " ( " + receiveType.toString() + " )";
158         }
159
160         return str;
161     }
162
163     /**
164      * Instantiate a class for handling a received message The class depends on the message.
165      *
166      * @param message the received message as a buffer of bytes
167      *
168      * @return a new class instance
169      */
170     public static PowermaxBaseMessage getMessageHandler(byte[] message) {
171         PowermaxBaseMessage msgHandler;
172         try {
173             PowermaxReceiveType msgType = PowermaxReceiveType.fromCode(message[1]);
174             switch (msgType) {
175                 case ACK:
176                     msgHandler = new PowermaxAckMessage(message);
177                     break;
178                 case TIMEOUT:
179                     msgHandler = new PowermaxTimeoutMessage(message);
180                     break;
181                 case DENIED:
182                     msgHandler = new PowermaxDeniedMessage(message);
183                     break;
184                 case DOWNLOAD_RETRY:
185                     msgHandler = new PowermaxDownloadRetryMessage(message);
186                     break;
187                 case SETTINGS:
188                 case SETTINGS_ITEM:
189                     msgHandler = new PowermaxSettingsMessage(message);
190                     break;
191                 case INFO:
192                     msgHandler = new PowermaxInfoMessage(message);
193                     break;
194                 case EVENT_LOG:
195                     msgHandler = new PowermaxEventLogMessage(message);
196                     break;
197                 case ZONESNAME:
198                     msgHandler = new PowermaxZonesNameMessage(message);
199                     break;
200                 case STATUS:
201                     msgHandler = new PowermaxStatusMessage(message);
202                     break;
203                 case ZONESTYPE:
204                     msgHandler = new PowermaxZonesTypeMessage(message);
205                     break;
206                 case PANEL:
207                     msgHandler = new PowermaxPanelMessage(message);
208                     break;
209                 case POWERLINK:
210                     msgHandler = new PowermaxPowerlinkMessage(message);
211                     break;
212                 case POWERMASTER:
213                     msgHandler = new PowermaxPowerMasterMessage(message);
214                     break;
215                 default:
216                     msgHandler = new PowermaxBaseMessage(message);
217                     break;
218             }
219         } catch (IllegalArgumentException e) {
220             msgHandler = new PowermaxBaseMessage(message);
221         }
222         return msgHandler;
223     }
224 }