]> git.basschouten.com Git - openhab-addons.git/blob
d64927f4fe02ac66679748f70b7b1821471ffac8
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.bluetooth.bluegiga.internal;
14
15 import java.util.HashSet;
16 import java.util.Set;
17 import java.util.UUID;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.AttributeChangeReason;
21 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.AttributeValueType;
22 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.BgApiResponse;
23 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.BluetoothAddressType;
24 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.ConnectionStatusFlag;
25 import org.openhab.binding.bluetooth.bluegiga.internal.enumeration.ScanResponseType;
26
27 /**
28  * Abstract class for response and event packets. This provides the deserialization methods to convert wire data to Java
29  * classes.
30  *
31  * @author Chris Jackson - Initial contribution and API
32  *
33  */
34 @NonNullByDefault
35 public abstract class BlueGigaResponse extends BlueGigaPacket {
36     private int[] buffer = new int[131];
37     private int position = 0;
38     protected boolean event = false;
39
40     protected BlueGigaResponse(int[] inputBuffer) {
41         // TODO Auto-generated constructor stub
42         buffer = inputBuffer;
43         position = 4;
44     }
45
46     /**
47      * Returns true if this response is an event, or false if it is a response to a command
48      *
49      * @return true if this is an event
50      */
51     public boolean isEvent() {
52         return event;
53     }
54
55     /**
56      * Reads an int8 from the output stream
57      *
58      * @return value read from input
59      */
60     protected int deserializeInt8() {
61         if (buffer[position] >= 128) {
62             return buffer[position++] - 256;
63         } else {
64             return buffer[position++];
65         }
66     }
67
68     /**
69      * Reads a uint8 from the output stream
70      *
71      * @return value read from input
72      */
73     protected int deserializeUInt8() {
74         return buffer[position++];
75     }
76
77     protected boolean deserializeBoolean() {
78         return buffer[position++] != 0;
79     }
80
81     /**
82      * Reads a uint16 from the output stream
83      *
84      * @return value read from input
85      */
86     protected int deserializeUInt16() {
87         return buffer[position++] + (buffer[position++] << 8);
88     }
89
90     protected UUID deserializeUuid() {
91         long low;
92         long high;
93
94         // This is a uint8array type so first byte is the length
95         int length = buffer[position++];
96         switch (length) {
97             case 2:
98                 // 0000xxxx-0000-1000-8000-00805F9B34FB
99                 low = 0x800000805f9b34fbL;
100                 high = ((long) buffer[position++] << 32) + ((long) buffer[position++] << 40) + 0x00001000L;
101                 break;
102             case 4:
103                 // xxxxxxxx-0000-1000-8000-00805F9B34FB
104                 low = 0x800000805f9b34fbL;
105                 high = ((long) buffer[position++] << 32) + ((long) buffer[position++] << 40)
106                         + ((long) buffer[position++] << 48) + ((long) buffer[position++] << 56) + 0x00001000L;
107                 break;
108             case 16:
109                 low = (buffer[position++]) + ((long) buffer[position++] << 8) + ((long) buffer[position++] << 16)
110                         + ((long) buffer[position++] << 24) + ((long) buffer[position++] << 32)
111                         + ((long) buffer[position++] << 40) + ((long) buffer[position++] << 48)
112                         + ((long) buffer[position++] << 56);
113                 high = (buffer[position++]) + ((long) buffer[position++] << 8) + ((long) buffer[position++] << 16)
114                         + ((long) buffer[position++] << 24) + ((long) buffer[position++] << 32)
115                         + ((long) buffer[position++] << 40) + ((long) buffer[position++] << 48)
116                         + ((long) buffer[position++] << 56);
117                 break;
118             default:
119                 low = 0;
120                 high = 0;
121                 position += length;
122                 break;
123         }
124         return new UUID(high, low);
125     }
126
127     protected BgApiResponse deserializeBgApiResponse() {
128         return BgApiResponse.getBgApiResponse(deserializeUInt16());
129     }
130
131     public Set<ConnectionStatusFlag> deserializeConnectionStatusFlag() {
132         int val = deserializeUInt8();
133         Set<ConnectionStatusFlag> options = new HashSet<>();
134         for (ConnectionStatusFlag option : ConnectionStatusFlag.values()) {
135             if (option == ConnectionStatusFlag.UNKNOWN) {
136                 continue;
137             }
138             if ((option.getKey() & val) != 0) {
139                 options.add(option);
140             }
141         }
142         return options;
143     }
144
145     protected AttributeValueType deserializeAttributeValueType() {
146         return AttributeValueType.getAttributeValueType(deserializeUInt8());
147     }
148
149     protected BluetoothAddressType deserializeBluetoothAddressType() {
150         return BluetoothAddressType.getBluetoothAddressType(deserializeUInt8());
151     }
152
153     protected AttributeChangeReason deserializeAttributeChangeReason() {
154         return AttributeChangeReason.getAttributeChangeReason(deserializeUInt8());
155     }
156
157     protected ScanResponseType deserializeScanResponseType() {
158         return ScanResponseType.getScanResponseType(deserializeUInt8());
159     }
160
161     protected long deserializeUInt32() {
162         return buffer[position++] + (buffer[position++] << 8) + (buffer[position++] << 16) + (buffer[position++] << 24);
163     }
164
165     protected int[] deserializeUInt8Array() {
166         int length = buffer[position++];
167         int[] val = new int[length];
168
169         for (int cnt = 0; cnt < length; cnt++) {
170             val[cnt] = deserializeUInt8();
171         }
172
173         return val;
174     }
175
176     protected String deserializeAddress() {
177         StringBuilder builder = new StringBuilder();
178
179         for (int cnt = 5; cnt >= 0; cnt--) {
180             if (cnt < 5) {
181                 builder.append(':');
182             }
183             builder.append(String.format("%02X", buffer[position + cnt]));
184         }
185         position += 6;
186
187         return builder.toString();
188     }
189 }