]> git.basschouten.com Git - openhab-addons.git/blob
3197a2163c962861cad9fae21fd8852edcdb98ed
[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.insteon.internal.message;
14
15 import java.util.Objects;
16
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.insteon.internal.device.InsteonAddress;
20 import org.openhab.binding.insteon.internal.utils.Utils;
21
22 /**
23  * An Insteon message has several fields with known type and offset
24  * within the message. This class represents a single field, and
25  * holds name, type, and offset (but not value!).
26  *
27  * @author Daniel Pfrommer - Initial contribution
28  * @author Rob Nielsen - Port to openHAB 2 insteon binding
29  */
30 @NonNullByDefault
31 @SuppressWarnings("null")
32 public final class Field {
33     private final String name;
34     private final int offset;
35     private final @Nullable DataType type;
36
37     public String getName() {
38         return name;
39     }
40
41     public int getOffset() {
42         return offset;
43     }
44
45     public @Nullable DataType getType() {
46         return type;
47     }
48
49     public Field(String name, @Nullable DataType type, int off) {
50         this.name = name;
51         this.type = type;
52         this.offset = off;
53     }
54
55     private void check(int arrayLen, DataType t) throws FieldException {
56         checkSpace(arrayLen);
57         checkType(t);
58     }
59
60     private void checkSpace(int arrayLen) throws FieldException {
61         if (offset + type.getSize() > arrayLen) {
62             throw new FieldException("field write beyond end of msg");
63         }
64     }
65
66     private void checkType(DataType t) throws FieldException {
67         if (type != t) {
68             throw new FieldException("field write type mismatch!");
69         }
70     }
71
72     @Override
73     public String toString() {
74         return getName() + " Type: " + getType() + " Offset " + getOffset();
75     }
76
77     public String toString(byte @Nullable [] array) {
78         String s = name + ":";
79         try {
80             switch (type) {
81                 case BYTE:
82                     s += Utils.getHexByte(getByte(array));
83                     break;
84                 case INT:
85                     s += Integer.toString(getInt(array));
86                     break;
87                 case ADDRESS:
88                     s += getAddress(array).toString();
89                     break;
90                 default:
91                     break;
92             }
93         } catch (FieldException e) {
94             // will just return empty string
95         }
96         return s;
97     }
98
99     public void set(byte @Nullable [] array, Object o) throws FieldException {
100         switch (getType()) {
101             case BYTE:
102                 setByte(array, (Byte) o);
103                 break;
104             case INT:
105                 setInt(array, (Integer) o);
106                 break;
107             // case FLOAT: setFloat(array, (float) o); break;
108             case ADDRESS:
109                 setAddress(array, (InsteonAddress) o);
110                 break;
111             default:
112                 throw new FieldException("Not implemented data type " + getType() + "!");
113         }
114     }
115
116     /**
117      * Writes a byte value to a byte array, at the proper offset.
118      * Use this function to set the value of a field within a message.
119      *
120      * @param array the destination array
121      * @param b the value you want to set the byte to
122      * @throws FieldException
123      */
124     public void setByte(byte @Nullable [] array, byte b) throws FieldException {
125         check(array.length, DataType.BYTE);
126         array[offset] = b;
127     }
128
129     /**
130      * Writes the value of an integer field to a byte array
131      * Use this function to set the value of a field within a message.
132      *
133      * @param array the destination array
134      * @param i the integer value to set
135      */
136     public void setInt(byte @Nullable [] array, int i) throws FieldException {
137         check(array.length, DataType.INT);
138         array[offset] = (byte) ((i >>> 24) & 0xFF);
139         array[offset + 1] = (byte) ((i >>> 16) & 0xFF);
140         array[offset + 2] = (byte) ((i >>> 8) & 0xFF);
141         array[offset + 3] = (byte) ((i >>> 0) & 0xFF);
142     }
143
144     /**
145      * Writes the value of an InsteonAddress to a message array.
146      * Use this function to set the value of a field within a message.
147      *
148      * @param array the destination array
149      * @param adr the insteon address value to set
150      */
151
152     public void setAddress(byte @Nullable [] array, InsteonAddress adr) throws FieldException {
153         check(array.length, DataType.ADDRESS);
154         adr.storeBytes(array, offset);
155     }
156
157     /**
158      * Fetch a byte from the array at the field position
159      *
160      * @param array the array to fetch from
161      * @return the byte value of the field
162      */
163     public byte getByte(byte @Nullable [] array) throws FieldException {
164         check(array.length, DataType.BYTE);
165         return array[offset];
166     }
167
168     /**
169      * Fetch an int from the array at the field position
170      *
171      * @param array the array to fetch from
172      * @return the int value of the field
173      */
174     public int getInt(byte @Nullable [] array) throws FieldException {
175         check(array.length, DataType.INT);
176         byte b1 = array[offset];
177         byte b2 = array[offset + 1];
178         byte b3 = array[offset + 2];
179         byte b4 = array[offset + 3];
180         int value = ((b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0));
181         return value;
182     }
183
184     /**
185      * Fetch an insteon address from the field position
186      *
187      * @param array the array to fetch from
188      * @return the address
189      */
190
191     public InsteonAddress getAddress(byte @Nullable [] array) throws FieldException {
192         check(array.length, DataType.ADDRESS);
193         InsteonAddress adr = new InsteonAddress();
194         adr.loadBytes(array, offset);
195         return adr;
196     }
197
198     /**
199      * Equals test
200      */
201     @Override
202     public boolean equals(@Nullable Object o) {
203         if (o instanceof Field) {
204             Field f = (Field) o;
205             return (f.getName().equals(getName())) && (f.getOffset() == getOffset());
206         } else {
207             return false;
208         }
209     }
210
211     @Override
212     public int hashCode() {
213         return Objects.hash(getName(), getOffset());
214     }
215 }