]> git.basschouten.com Git - openhab-addons.git/blob
ad417e04b9bdb67695bf0f9d48bfce230d2b1418
[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;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.UUID;
20 import java.util.concurrent.ConcurrentHashMap;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24
25 /**
26  * The {@link BluetoothCharacteristic} class defines the BLE Service.
27  * <p>
28  * Services are collections of characteristics and relationships to other services that encapsulate the behavior of part
29  * of a device.
30  * <p>
31  * https://www.bluetooth.com/specifications/gatt/services
32  *
33  * @author Chris Jackson - Initial contribution
34  * @author Kai Kreuzer - Cleaned up code
35  */
36 @NonNullByDefault
37 public class BluetoothService {
38
39     // The service UUID
40     private final UUID uuid;
41
42     /**
43      * The start handle for this service
44      */
45     private final int handleStart;
46
47     /**
48      * The end handle for this service
49      */
50     private final int handleEnd;
51
52     protected int instanceId;
53
54     /**
55      * Indicates if this is a primary service (true) or secondary service (false)
56      */
57     protected boolean primaryService;
58
59     /**
60      * Map of {@link BluetoothCharacteristic}s supported in this service
61      */
62     protected final Map<UUID, BluetoothCharacteristic> supportedCharacteristics = new ConcurrentHashMap<>();
63
64     /**
65      * Constructor
66      *
67      * @param uuid the uuid of the service
68      */
69     public BluetoothService(UUID uuid) {
70         this(uuid, true, 0, 0);
71     }
72
73     /**
74      * Constructor
75      *
76      * @param uuid the uuid of the service
77      * @param primaryService true, if this service is a primary service
78      */
79     public BluetoothService(UUID uuid, boolean primaryService) {
80         this(uuid, primaryService, 0, 0);
81     }
82
83     /**
84      * Constructor
85      *
86      * @param uuid the uuid of the service
87      * @param primaryService true, if this service is a primary service
88      * @param handleStart id of the lowest handle
89      * @param handleEnd id of the highest handle
90      */
91     public BluetoothService(UUID uuid, boolean primaryService, int handleStart, int handleEnd) {
92         this.uuid = uuid;
93         this.primaryService = primaryService;
94         this.handleStart = handleStart;
95         this.handleEnd = handleEnd;
96     }
97
98     /**
99      * Get characteristic based on {@link UUID}, null if it is not known
100      *
101      * @return the {@link BluetoothCharacteristic} with the requested {@link UUID}
102      */
103     public @Nullable BluetoothCharacteristic getCharacteristic(UUID uuid) {
104         return supportedCharacteristics.get(uuid);
105     }
106
107     /**
108      * Get list of characteristics of the service
109      *
110      * @return the list of {@link BluetoothCharacteristic}s
111      */
112     public List<BluetoothCharacteristic> getCharacteristics() {
113         return new ArrayList<>(supportedCharacteristics.values());
114     }
115
116     /**
117      * Return the UUID of this service
118      *
119      * @return the {@link UUID} of the service
120      */
121     public UUID getUuid() {
122         return uuid;
123     }
124
125     /**
126      * Gets the starting handle for this service
127      *
128      * @return the start handle
129      */
130     public int getHandleStart() {
131         return handleStart;
132     }
133
134     /**
135      * Gets the end handle for this service
136      *
137      * @return the end handle
138      */
139     public int getHandleEnd() {
140         return handleEnd;
141     }
142
143     /**
144      * Get the type of this service (primary/secondary)
145      *
146      * @return true if this is a primary service
147      */
148     public boolean isPrimary() {
149         return primaryService;
150     }
151
152     /**
153      * Returns the instance ID for this service
154      *
155      * @return Instance ID of this service
156      */
157     public int getInstanceId() {
158         return instanceId;
159     }
160
161     /**
162      * Checks if the service provides a specific characteristic
163      *
164      * @return true if the characteristic is provided in this service
165      */
166     public boolean providesCharacteristic(UUID uuid) {
167         return supportedCharacteristics.containsKey(uuid);
168     }
169
170     /**
171      * Add a characteristic to this service
172      *
173      * @param characteristic The characteristics to be added
174      * @return true, if the characteristic was added to the service
175      */
176     public boolean addCharacteristic(BluetoothCharacteristic characteristic) {
177         if (supportedCharacteristics.get(characteristic.getUuid()) != null) {
178             return false;
179         }
180
181         supportedCharacteristics.put(characteristic.getUuid(), characteristic);
182         characteristic.setService(this);
183         return true;
184     }
185
186     /**
187      * Gets a characteristic by the handle
188      *
189      * @param handle the handle of the characteristic to return
190      * @return return the {@link BluetoothCharacteristic} or null if not found
191      */
192     public @Nullable BluetoothCharacteristic getCharacteristicByHandle(int handle) {
193         synchronized (supportedCharacteristics) {
194             for (BluetoothCharacteristic characteristic : supportedCharacteristics.values()) {
195                 if (characteristic.getHandle() == handle) {
196                     return characteristic;
197                 }
198             }
199         }
200         return null;
201     }
202
203     /**
204      * Gets the {@link GattService} for this service. This is an enum defining the available GATT services.
205      *
206      * @return the {@link GattService} relating to this service
207      */
208     public @Nullable GattService getService() {
209         return GattService.getService(uuid);
210     }
211
212     public enum GattService {
213
214         // List of GATT Services
215         ALERT_NOTIFICATION_SERVICE(0x1811),
216         AUTOMATION_IO(0x1815),
217         BATTERY_SERVICE(0x180F),
218         BLOOD_PRESSURE(0x1810),
219         BODY_COMPOSITION(0x181B),
220         BOND_MANAGEMENT(0x181E),
221         CONTINUOUS_GLUCOSE_MONITORING(0x181F),
222         CURRENT_TIME_SERVICE(0x1805),
223         CYCLING_POWER(0x1818),
224         CYCLING_SPEED_AND_CADENCE(0x1816),
225         DEVICE_INFORMATION(0x180A),
226         ENVIRONMENTAL_SENSING(0x181A),
227         GENERIC_ACCESS(0x1800),
228         GENERIC_ATTRIBUTE(0x1801),
229         GLUCOSE(0x1808),
230         HEALTH_THERMOMETER(0x1809),
231         HEART_RATE(0x180D),
232         HTTP_PROXY(0x1823),
233         HUMAN_INTERFACE_DEVICE(0x1812),
234         IMMEDIATE_ALERT(0x1802),
235         INDOOR_POSITIONING(0x1821),
236         INTERNET_PROTOCOL_SUPPORT(0x1820),
237         LINK_LOSS(0x1803L),
238         LOCATION_AND_NAVIGATION(0x1819),
239         NEXT_DST_CHANGE_SERVICE(0x1807),
240         PHONE_ALERT_STATUS_SERVICE(0x180E),
241         REFERENCE_TIME_UPDATE_SERVICE(0x1806),
242         RUNNING_SPEED_AND_CADENCE(0x1814),
243         SCAN_PARAMETERS(0x1813),
244         TX_POWER(0x1804),
245         USER_DATA(0x181C),
246         WEIGHT_SCALE(0x181D);
247
248         private static @Nullable Map<UUID, GattService> uuidToServiceMapping;
249
250         private UUID uuid;
251
252         private GattService(long key) {
253             this.uuid = BluetoothBindingConstants.createBluetoothUUID(key);
254         }
255
256         public static @Nullable GattService getService(UUID uuid) {
257             Map<UUID, GattService> localServiceMapping = uuidToServiceMapping;
258             if (localServiceMapping == null) {
259                 localServiceMapping = new HashMap<>();
260                 for (GattService s : values()) {
261                     localServiceMapping.put(s.uuid, s);
262                 }
263                 uuidToServiceMapping = localServiceMapping;
264             }
265             return localServiceMapping.get(uuid);
266         }
267
268         /**
269          * @return the key
270          */
271         public UUID getUUID() {
272             return uuid;
273         }
274     }
275
276     @Override
277     public String toString() {
278         StringBuilder builder = new StringBuilder();
279         builder.append("BluetoothService [uuid=");
280         builder.append(uuid);
281         builder.append(", handleStart=");
282         builder.append(handleStart);
283         builder.append(", handleEnd=");
284         builder.append(handleEnd);
285         builder.append(']');
286         return builder.toString();
287     }
288 }