2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.bluetooth;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.UUID;
20 import java.util.concurrent.ConcurrentHashMap;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
26 * The {@link BluetoothCharacteristic} class defines the BLE Service.
28 * Services are collections of characteristics and relationships to other services that encapsulate the behavior of part
31 * https://www.bluetooth.com/specifications/gatt/services
33 * @author Chris Jackson - Initial contribution
34 * @author Kai Kreuzer - Cleaned up code
37 public class BluetoothService {
40 private final UUID uuid;
43 * The start handle for this service
45 private final int handleStart;
48 * The end handle for this service
50 private final int handleEnd;
52 protected int instanceId;
55 * Indicates if this is a primary service (true) or secondary service (false)
57 protected boolean primaryService;
60 * Map of {@link BluetoothCharacteristic}s supported in this service
62 protected final Map<UUID, BluetoothCharacteristic> supportedCharacteristics = new ConcurrentHashMap<>();
67 * @param uuid the uuid of the service
69 public BluetoothService(UUID uuid) {
70 this(uuid, true, 0, 0);
76 * @param uuid the uuid of the service
77 * @param primaryService true, if this service is a primary service
79 public BluetoothService(UUID uuid, boolean primaryService) {
80 this(uuid, primaryService, 0, 0);
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
91 public BluetoothService(UUID uuid, boolean primaryService, int handleStart, int handleEnd) {
93 this.primaryService = primaryService;
94 this.handleStart = handleStart;
95 this.handleEnd = handleEnd;
99 * Get characteristic based on {@link UUID}, null if it is not known
101 * @return the {@link BluetoothCharacteristic} with the requested {@link UUID}
103 public @Nullable BluetoothCharacteristic getCharacteristic(UUID uuid) {
104 return supportedCharacteristics.get(uuid);
108 * Get list of characteristics of the service
110 * @return the list of {@link BluetoothCharacteristic}s
112 public List<BluetoothCharacteristic> getCharacteristics() {
113 return new ArrayList<>(supportedCharacteristics.values());
117 * Return the UUID of this service
119 * @return the {@link UUID} of the service
121 public UUID getUuid() {
126 * Gets the starting handle for this service
128 * @return the start handle
130 public int getHandleStart() {
135 * Gets the end handle for this service
137 * @return the end handle
139 public int getHandleEnd() {
144 * Get the type of this service (primary/secondary)
146 * @return true if this is a primary service
148 public boolean isPrimary() {
149 return primaryService;
153 * Returns the instance ID for this service
155 * @return Instance ID of this service
157 public int getInstanceId() {
162 * Checks if the service provides a specific characteristic
164 * @return true if the characteristic is provided in this service
166 public boolean providesCharacteristic(UUID uuid) {
167 return supportedCharacteristics.containsKey(uuid);
171 * Add a characteristic to this service
173 * @param characteristic The characteristics to be added
174 * @return true, if the characteristic was added to the service
176 public boolean addCharacteristic(BluetoothCharacteristic characteristic) {
177 if (supportedCharacteristics.get(characteristic.getUuid()) != null) {
181 supportedCharacteristics.put(characteristic.getUuid(), characteristic);
182 characteristic.setService(this);
187 * Gets a characteristic by the handle
189 * @param handle the handle of the characteristic to return
190 * @return return the {@link BluetoothCharacteristic} or null if not found
192 public @Nullable BluetoothCharacteristic getCharacteristicByHandle(int handle) {
193 synchronized (supportedCharacteristics) {
194 for (BluetoothCharacteristic characteristic : supportedCharacteristics.values()) {
195 if (characteristic.getHandle() == handle) {
196 return characteristic;
204 * Gets the {@link GattService} for this service. This is an enum defining the available GATT services.
206 * @return the {@link GattService} relating to this service
208 public @Nullable GattService getService() {
209 return GattService.getService(uuid);
212 public enum GattService {
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),
230 HEALTH_THERMOMETER(0x1809),
233 HUMAN_INTERFACE_DEVICE(0x1812),
234 IMMEDIATE_ALERT(0x1802),
235 INDOOR_POSITIONING(0x1821),
236 INTERNET_PROTOCOL_SUPPORT(0x1820),
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),
246 WEIGHT_SCALE(0x181D);
248 private static @Nullable Map<UUID, GattService> uuidToServiceMapping;
252 private GattService(long key) {
253 this.uuid = BluetoothBindingConstants.createBluetoothUUID(key);
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);
263 uuidToServiceMapping = localServiceMapping;
265 return localServiceMapping.get(uuid);
271 public UUID getUUID() {
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);
286 return builder.toString();