]> git.basschouten.com Git - openhab-addons.git/blob
2fbf6ee28f27d4a473541611d29082e041cf3dcb
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.transport.message;
14
15 import java.util.Arrays;
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.HexUtils;
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  * @author Jeremy Setton - Rewrite insteon binding
30  */
31 @NonNullByDefault
32 public final class Field {
33     private final String name;
34     private final int offset;
35     private final DataType type;
36
37     public String getName() {
38         return name;
39     }
40
41     public int getOffset() {
42         return offset;
43     }
44
45     public DataType getType() {
46         return type;
47     }
48
49     public Field(String name, DataType type, int offset) {
50         this.name = name;
51         this.type = type;
52         this.offset = offset;
53     }
54
55     private void check(int len, DataType t) throws FieldException {
56         if (offset + type.getSize() > len) {
57             throw new FieldException("field write beyond end of msg");
58         }
59         if (type != t) {
60             throw new FieldException("field write type mismatch!");
61         }
62     }
63
64     public void set(byte[] data, Object o) throws FieldException {
65         switch (type) {
66             case BYTE:
67                 setByte(data, (Byte) o);
68                 break;
69             case ADDRESS:
70                 setAddress(data, (InsteonAddress) o);
71                 break;
72             default:
73                 throw new FieldException("field data type unknown");
74         }
75     }
76
77     /**
78      * Sets a byte value to a byte array, at the proper offset.
79      * Use this function to set the value of a field within a message.
80      *
81      * @param data the byte array to update
82      * @param b the byte value to set
83      * @throws FieldException
84      */
85     public void setByte(byte[] data, byte b) throws FieldException {
86         check(data.length, DataType.BYTE);
87         data[offset] = b;
88     }
89
90     /**
91      * Sets the value of an InsteonAddress to a message array.
92      * Use this function to set the value of a field within a message.
93      *
94      * @param data the byte array to update
95      * @param address the insteon address value to set
96      * @throws FieldException
97      */
98     public void setAddress(byte[] data, InsteonAddress address) throws FieldException {
99         check(data.length, DataType.ADDRESS);
100         System.arraycopy(address.getBytes(), 0, data, offset, type.getSize());
101     }
102
103     /**
104      * Returns a byte from a byte array at the field position
105      *
106      * @param data the byte array to use
107      * @return the byte
108      * @throws FieldException
109      */
110     public byte getByte(byte[] data) throws FieldException {
111         check(data.length, DataType.BYTE);
112         return data[offset];
113     }
114
115     /**
116      * Returns an insteon address from the field position
117      *
118      * @param data the byte array to use
119      * @return the insteon address
120      * @throws FieldException
121      */
122     public InsteonAddress getAddress(byte[] data) throws FieldException {
123         check(data.length, DataType.ADDRESS);
124         byte[] address = Arrays.copyOfRange(data, offset, offset + type.getSize());
125         return new InsteonAddress(address);
126     }
127
128     /**
129      * Returns a string representation for a given byte array
130      *
131      * @param data the byte array to use
132      * @return the string representation
133      */
134     public String toString(byte[] data) {
135         String s = name + ":";
136         try {
137             switch (type) {
138                 case BYTE:
139                     s += HexUtils.getHexString(getByte(data));
140                     break;
141                 case ADDRESS:
142                     s += getAddress(data).toString();
143                     break;
144                 default:
145                     throw new FieldException("field data type unknown");
146             }
147         } catch (FieldException e) {
148             s += "NULL";
149         }
150         return s;
151     }
152
153     @Override
154     public String toString() {
155         return name + " Type: " + type + " Offset: " + offset;
156     }
157
158     @Override
159     public boolean equals(@Nullable Object obj) {
160         if (obj == this) {
161             return true;
162         }
163         if (obj == null) {
164             return false;
165         }
166         if (getClass() != obj.getClass()) {
167             return false;
168         }
169         Field other = (Field) obj;
170         return name.equals(other.name) && offset == other.offset;
171     }
172
173     @Override
174     public int hashCode() {
175         final int prime = 31;
176         int result = 1;
177         result = prime * result + name.hashCode();
178         result = prime * result + offset;
179         return result;
180     }
181 }