| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.googlecode.android_scripting.facade.bluetooth; |
| |
| import android.app.Service; |
| import android.bluetooth.BluetoothAdapter; |
| import android.bluetooth.BluetoothDevice; |
| import android.bluetooth.BluetoothGattCharacteristic; |
| import android.bluetooth.BluetoothGattDescriptor; |
| import android.bluetooth.BluetoothGattServer; |
| import android.bluetooth.BluetoothGattServerCallback; |
| import android.bluetooth.BluetoothGattService; |
| import android.bluetooth.BluetoothManager; |
| import android.bluetooth.BluetoothProfile; |
| import android.content.Context; |
| import android.os.Bundle; |
| |
| import com.googlecode.android_scripting.Log; |
| import com.googlecode.android_scripting.MainThread; |
| import com.googlecode.android_scripting.facade.EventFacade; |
| import com.googlecode.android_scripting.facade.FacadeManager; |
| import com.googlecode.android_scripting.jsonrpc.RpcReceiver; |
| import com.googlecode.android_scripting.rpc.Rpc; |
| import com.googlecode.android_scripting.rpc.RpcParameter; |
| |
| import java.lang.reflect.*; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.UUID; |
| import java.util.concurrent.Callable; |
| |
| public class GattServerFacade extends RpcReceiver { |
| private final EventFacade mEventFacade; |
| private BluetoothAdapter mBluetoothAdapter; |
| private BluetoothManager mBluetoothManager; |
| private final Service mService; |
| private final Context mContext; |
| private final HashMap<Integer, BluetoothGattCharacteristic> mCharacteristicList; |
| private final HashMap<Integer, BluetoothGattDescriptor> mDescriptorList; |
| private final HashMap<Integer, BluetoothGattServer> mBluetoothGattServerList; |
| private final HashMap<Integer, BtGattServerCallback> mBluetoothGattServerCallbackList; |
| private final HashMap<Integer, BluetoothGattService> mGattServiceList; |
| private final HashMap<Integer, List<BluetoothGattService>> mBluetoothGattDiscoveredServicesList; |
| private final HashMap<Integer, List<BluetoothDevice>> mGattServerDiscoveredDevicesList; |
| private static int sCharacteristicCount; |
| private static int sDescriptorCount; |
| private static int sGattServerCallbackCount; |
| private static int sGattServerCount; |
| private static int sGattServiceCount; |
| |
| public GattServerFacade(FacadeManager manager) { |
| super(manager); |
| mService = manager.getService(); |
| mContext = mService.getApplicationContext(); |
| mBluetoothAdapter = MainThread.run(mService, new Callable<BluetoothAdapter>() { |
| @Override |
| public BluetoothAdapter call() throws Exception { |
| return BluetoothAdapter.getDefaultAdapter(); |
| } |
| }); |
| mBluetoothManager = (BluetoothManager) mContext.getSystemService(Service.BLUETOOTH_SERVICE); |
| mEventFacade = manager.getReceiver(EventFacade.class); |
| mCharacteristicList = new HashMap<Integer, BluetoothGattCharacteristic>(); |
| mDescriptorList = new HashMap<Integer, BluetoothGattDescriptor>(); |
| mBluetoothGattServerList = new HashMap<Integer, BluetoothGattServer>(); |
| mBluetoothGattServerCallbackList = new HashMap<Integer, BtGattServerCallback>(); |
| mGattServiceList = new HashMap<Integer, BluetoothGattService>(); |
| mBluetoothGattDiscoveredServicesList = new HashMap<Integer, List<BluetoothGattService>>(); |
| mGattServerDiscoveredDevicesList = new HashMap<Integer, List<BluetoothDevice>>(); |
| } |
| |
| /** |
| * Open a new Gatt server. |
| * |
| * @param index the bluetooth gatt server callback to open on |
| * @return the index of the newly opened gatt server |
| * @throws Exception |
| */ |
| @Rpc(description = "Open new gatt server") |
| public int gattServerOpenGattServer(@RpcParameter(name = "index") Integer index) |
| throws Exception { |
| if (mBluetoothGattServerCallbackList.get(index) != null) { |
| BluetoothGattServer mGattServer = |
| mBluetoothManager.openGattServer(mContext, mBluetoothGattServerCallbackList.get( |
| index)); |
| sGattServerCount += 1; |
| int in = sGattServerCount; |
| mBluetoothGattServerList.put(in, mGattServer); |
| return in; |
| } else { |
| throw new Exception("Invalid index input:" + Integer.toString(index)); |
| } |
| } |
| |
| /** |
| * Add a service to a bluetooth gatt server |
| * |
| * @param index the bluetooth gatt server to add a service to |
| * @param serviceIndex the service to add to the bluetooth gatt server |
| * @throws Exception |
| */ |
| @Rpc(description = "Add service to bluetooth gatt server") |
| public void gattServerAddService(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "serviceIndex") Integer serviceIndex) throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| if (mGattServiceList.get(serviceIndex) != null) { |
| mBluetoothGattServerList.get(index).addService(mGattServiceList.get(serviceIndex)); |
| } else { |
| throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex)); |
| } |
| } else { |
| throw new Exception("Invalid index input:" + Integer.toString(index)); |
| } |
| } |
| |
| /** |
| * Add a service to a bluetooth gatt server |
| * |
| * @param index the bluetooth gatt server to add a service to |
| * @throws Exception |
| */ |
| @Rpc(description = "Clear services from bluetooth gatt server") |
| public void gattServerClearServices( |
| @RpcParameter(name = "index") Integer index) throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| mBluetoothGattServerList.get(index).clearServices(); |
| } else { |
| throw new Exception("Invalid index input:" + Integer.toString(index)); |
| } |
| } |
| |
| /** |
| * Get connected devices of the gatt server |
| * |
| * @param gattServerIndex the gatt server index |
| * @throws Exception |
| */ |
| @Rpc(description = "Return a list of connected gatt devices.") |
| public List<BluetoothDevice> gattServerGetConnectedDevices( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex) throws Exception { |
| if (mBluetoothGattServerList.get(gattServerIndex) == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = |
| mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); |
| mGattServerDiscoveredDevicesList.put(gattServerIndex, connectedDevices); |
| return connectedDevices; |
| } |
| |
| /** |
| * Get connected devices of the gatt server |
| * |
| * @param gattServerIndex the gatt server index |
| * @param bluetoothDeviceIndex the remotely connected bluetooth device |
| * @param requestId the ID of the request that was received with the callback |
| * @param status the status of the request to be sent to the remote devices |
| * @param offset value offset for partial read/write response |
| * @param value the value of the attribute that was read/written |
| * @throws Exception |
| */ |
| @Rpc(description = "Send a response after a write.") |
| public void gattServerSendResponse( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex, |
| @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex, |
| @RpcParameter(name = "requestId") Integer requestId, |
| @RpcParameter(name = "status") Integer status, |
| @RpcParameter(name = "offset") Integer offset, |
| @RpcParameter(name = "value") byte[] value) throws Exception { |
| |
| BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex); |
| if (gattServer == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = |
| mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); |
| BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex); |
| gattServer.sendResponse(bluetoothDevice, requestId, status, offset, value); |
| } |
| |
| /** |
| * Notify that characteristic was changed |
| * |
| * @deprecated Use {@link #gattServerNotifyCharacteristicChangedByInstanceId( |
| * gattServerIndex, bluetoothDeviceIndex, instanceId, confirm)} instead. |
| * @param gattServerIndex the gatt server index |
| * @param bluetoothDeviceIndex the remotely connected bluetooth device |
| * @param characteristicIndex characteristic index |
| * @param confirm shall we expect confirmation |
| * @throws Exception |
| */ |
| @Deprecated |
| @Rpc(description = "Notify that characteristic was changed.") |
| public void gattServerNotifyCharacteristicChanged( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex, |
| @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex, |
| @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, |
| @RpcParameter(name = "confirm") Boolean confirm) throws Exception { |
| |
| BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex); |
| if (gattServer == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = |
| mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); |
| if (connectedDevices == null) { |
| throw new Exception( |
| "Connected device list empty for gattServerIndex:" + Integer.toString( |
| gattServerIndex)); |
| } |
| BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex); |
| if (bluetoothDevice == null) { |
| throw new Exception( |
| "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex)); |
| } |
| |
| BluetoothGattCharacteristic bluetoothCharacteristic = mCharacteristicList.get( |
| characteristicIndex); |
| if (bluetoothCharacteristic == null) { |
| throw new Exception( |
| "Invalid characteristicIndex: " + Integer.toString(characteristicIndex)); |
| } |
| |
| gattServer.notifyCharacteristicChanged(bluetoothDevice, bluetoothCharacteristic, confirm); |
| } |
| |
| /** |
| * Notify that characteristic was changed |
| * |
| * @param gattServerIndex the gatt server index |
| * @param bluetoothDeviceIndex the remotely connected bluetooth device |
| * @param characteristicIndex characteristic index |
| * @param confirm shall we expect confirmation |
| * @throws Exception |
| */ |
| @Rpc(description = "Notify that characteristic was changed by Instance Id.") |
| public void gattServerNotifyCharacteristicChangedByInstanceId( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex, |
| @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex, |
| @RpcParameter(name = "instanceId") Integer instanceId, |
| @RpcParameter(name = "confirm") Boolean confirm) throws Exception { |
| |
| BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex); |
| if (gattServer == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = |
| mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER); |
| if (connectedDevices == null) { |
| throw new Exception( |
| "Connected device list empty for gattServerIndex:" + Integer.toString( |
| gattServerIndex)); |
| } |
| BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex); |
| if (bluetoothDevice == null) { |
| throw new Exception( |
| "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex)); |
| } |
| |
| for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) { |
| if (mGattChar.getInstanceId() == instanceId) { |
| Log.i("Found Characteristic to get value. instanceId: " |
| + Integer.toString(instanceId) |
| + " UUID: " + mGattChar.getUuid().toString()); |
| gattServer.notifyCharacteristicChanged(bluetoothDevice, mGattChar, confirm); |
| } |
| } |
| } |
| |
| /** |
| * Create a new bluetooth gatt service |
| * |
| * @param uuid the UUID that characterises the service |
| * @param serviceType the service type |
| * @return The index of the new bluetooth gatt service |
| */ |
| @Rpc(description = "Create new bluetooth gatt service") |
| public int gattServerCreateService(@RpcParameter(name = "uuid") String uuid, |
| @RpcParameter(name = "serviceType") Integer serviceType) { |
| sGattServiceCount += 1; |
| int index = sGattServiceCount; |
| mGattServiceList.put(index, new BluetoothGattService(UUID.fromString(uuid), serviceType)); |
| return index; |
| } |
| |
| /** |
| * Add a characteristic to a bluetooth gatt service |
| * |
| * @param index the bluetooth gatt service index |
| * @param serviceUuid the service Uuid to get |
| * @param characteristicIndex the character index to use |
| * @throws Exception |
| */ |
| @Rpc(description = "Add a characteristic to a bluetooth gatt service") |
| public void gattServiceAddCharacteristic( |
| @RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "serviceUuid") String serviceUuid, |
| @RpcParameter(name = "characteristicIndex") Integer characteristicIndex) |
| throws Exception { |
| if (mBluetoothGattServerList.get(index) != null |
| && mBluetoothGattServerList.get(index).getService( |
| UUID.fromString(serviceUuid)) != null |
| && mCharacteristicList.get(characteristicIndex) != null) { |
| mBluetoothGattServerList.get(index).getService(UUID.fromString(serviceUuid)) |
| .addCharacteristic(mCharacteristicList.get(characteristicIndex)); |
| } else { |
| if (mBluetoothGattServerList.get(index) == null) { |
| throw new Exception("Invalid index input:" + index); |
| } else if (mCharacteristicList.get(characteristicIndex) == null) { |
| throw new Exception("Invalid characteristicIndex input:" + characteristicIndex); |
| } else { |
| throw new Exception("Invalid serviceUuid input:" + serviceUuid); |
| } |
| } |
| } |
| |
| /** |
| * Add a characteristic to a bluetooth gatt service |
| * |
| * @param index the bluetooth gatt service to add a characteristic to |
| * @param characteristicIndex the characteristic to add |
| * @throws Exception |
| */ |
| @Rpc(description = "Add a characteristic to a bluetooth gatt service") |
| public void gattServerAddCharacteristicToService(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "characteristicIndex") Integer characteristicIndex |
| |
| ) throws Exception { |
| if (mGattServiceList.get(index) != null) { |
| if (mCharacteristicList.get(characteristicIndex) != null) { |
| mGattServiceList.get(index).addCharacteristic(mCharacteristicList.get( |
| characteristicIndex)); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Close a bluetooth gatt |
| * |
| * @param index the bluetooth gatt index to close |
| * @throws Exception |
| */ |
| @Rpc(description = "Close a bluetooth gatt") |
| public void gattServerClose(@RpcParameter(name = "index") Integer index) throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| mBluetoothGattServerList.get(index).close(); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Get a list of Bluetooth Devices connnected to the bluetooth gatt |
| * |
| * @param index the bluetooth gatt index |
| * @return List of BluetoothDevice Objects |
| * @throws Exception |
| */ |
| @Rpc(description = "Get a list of Bluetooth Devices connnected to the bluetooth gatt") |
| public List<BluetoothDevice> gattGetConnectedDevices( |
| @RpcParameter(name = "index") Integer index) |
| throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| return mBluetoothGattServerList.get(index).getConnectedDevices(); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Read the current transmitter PHY and receiver PHY of the connection. |
| * |
| * @param gattServerIndex the bluetooth gatt index |
| * @throws Exception |
| */ |
| @Rpc(description = "Read PHY") |
| public void gattServerReadPhy( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex, |
| @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex) |
| throws Exception { |
| BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex); |
| if (gattServer == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get( |
| gattServerIndex); |
| if (connectedDevices == null) { |
| throw new Exception( |
| "Connected device list empty for gattServerIndex:" + Integer.toString( |
| gattServerIndex)); |
| } |
| BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex); |
| if (bluetoothDevice == null) { |
| throw new Exception( |
| "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex)); |
| } |
| |
| if (mBluetoothGattServerList.get(gattServerIndex) != null) { |
| mBluetoothGattServerList.get(gattServerIndex).readPhy(bluetoothDevice); |
| } else { |
| throw new Exception("Invalid index input:" + gattServerIndex); |
| } |
| } |
| |
| /** |
| * Set the preferred connection PHY. |
| * |
| * @param gattServerIndex the bluetooth gatt index |
| * @throws Exception |
| */ |
| @Rpc(description = "Set the preferred connection PHY") |
| public void gattServerSetPreferredPhy( |
| @RpcParameter(name = "gattServerIndex") Integer gattServerIndex, |
| @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex, |
| @RpcParameter(name = "txPhy") Integer txPhy, |
| @RpcParameter(name = "rxPhy") Integer rxPhy, |
| @RpcParameter(name = "txPhy") Integer phyOptions) throws Exception { |
| BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex); |
| if (gattServer == null) { |
| throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex)); |
| } |
| List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get( |
| gattServerIndex); |
| if (connectedDevices == null) { |
| throw new Exception( |
| "Connected device list empty for gattServerIndex:" + Integer.toString( |
| gattServerIndex)); |
| } |
| BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex); |
| if (bluetoothDevice == null) { |
| throw new Exception( |
| "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex)); |
| } |
| |
| if (mBluetoothGattServerList.get(gattServerIndex) != null) { |
| mBluetoothGattServerList.get(gattServerIndex) |
| .setPreferredPhy(bluetoothDevice, txPhy, rxPhy, phyOptions); |
| } else { |
| throw new Exception("Invalid index input:" + gattServerIndex); |
| } |
| } |
| |
| /** |
| * Get GATT Server UUID by characteristic index |
| * |
| * @param charIndex of the characteristic |
| * @return String Uuid |
| * @throws Exception |
| */ |
| @Rpc(description = "Get UUID of the input characteristic") |
| public String gattServerGetCharacteristicUuid( |
| @RpcParameter(name = "charIndex") Integer charIndex) |
| throws Exception { |
| BluetoothGattCharacteristic gattChar = mCharacteristicList.get(charIndex); |
| if (gattChar == null) { |
| throw new Exception("Invalid index input: " + charIndex); |
| } |
| return gattChar.getUuid().toString(); |
| } |
| |
| /** |
| * Get GATT Server UUID by characteristic index |
| * |
| * @param charIndex of the characteristic |
| * @return Integer instanceId |
| * @throws Exception |
| */ |
| @Rpc(description = "Get instanceId of the input characteristic") |
| public Integer gattServerGetCharacteristicInstanceId( |
| @RpcParameter(name = "charIndex") Integer charIndex) |
| throws Exception { |
| BluetoothGattCharacteristic gattChar = mCharacteristicList.get(charIndex); |
| if (gattChar == null) { |
| throw new Exception("Invalid index input: " + charIndex); |
| } |
| return gattChar.getInstanceId(); |
| } |
| |
| /** |
| * Get the service from an input UUID |
| * |
| * @param index the bluetooth gatt index |
| * @return BluetoothGattService related to the bluetooth gatt |
| * @throws Exception |
| */ |
| @Rpc(description = "Get the service from an input UUID") |
| public ArrayList<String> gattGetServiceUuidList(@RpcParameter(name = "index") Integer index) |
| throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| ArrayList<String> serviceUuidList = new ArrayList<String>(); |
| for (BluetoothGattService service : mBluetoothGattServerList.get(index).getServices()) { |
| serviceUuidList.add(service.getUuid().toString()); |
| } |
| return serviceUuidList; |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Get the service from an input UUID |
| * |
| * @param index the bluetooth gatt index |
| * @param uuid the String uuid that matches the service |
| * @return BluetoothGattService related to the bluetooth gatt |
| * @throws Exception |
| */ |
| @Rpc(description = "Get the service from an input UUID") |
| public BluetoothGattService gattGetService(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "uuid") String uuid) throws Exception { |
| if (mBluetoothGattServerList.get(index) != null) { |
| return mBluetoothGattServerList.get(index).getService(UUID.fromString(uuid)); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Add a descriptor to a bluetooth gatt characteristic |
| * |
| * @param index the bluetooth gatt characteristic to add a descriptor to |
| * @param descriptorIndex the descritor index to add to the characteristic |
| * @throws Exception |
| */ |
| @Rpc(description = "add descriptor to blutooth gatt characteristic") |
| public void gattServerCharacteristicAddDescriptor(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "descriptorIndex") Integer descriptorIndex) throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| if (mDescriptorList.get(descriptorIndex) != null) { |
| mCharacteristicList.get(index).addDescriptor(mDescriptorList.get(descriptorIndex)); |
| } else { |
| throw new Exception("Invalid descriptorIndex input:" + descriptorIndex); |
| } |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Create a new Characteristic object |
| * |
| * @param characteristicUuid uuid The UUID for this characteristic |
| * @param property Properties of this characteristic |
| * @param permission permissions Permissions for this characteristic |
| * @return |
| */ |
| @Rpc(description = "Create a new Characteristic object") |
| public int gattServerCreateBluetoothGattCharacteristic( |
| @RpcParameter(name = "characteristicUuid") String characteristicUuid, |
| @RpcParameter(name = "property") Integer property, |
| @RpcParameter(name = "permission") Integer permission) { |
| sCharacteristicCount += 1; |
| int index = sCharacteristicCount; |
| BluetoothGattCharacteristic characteristic = |
| new BluetoothGattCharacteristic( |
| UUID.fromString(characteristicUuid), property, permission); |
| mCharacteristicList.put(index, characteristic); |
| return index; |
| } |
| |
| /** |
| * Set value to a bluetooth gatt characteristic |
| * |
| * @deprecated Use {@link #gattServerCharacteristicSetValueByInstanceId( |
| * instanceId, value)} instead. |
| * @param index the bluetooth gatt characteristic |
| * @param value value |
| * @throws Exception |
| */ |
| @Deprecated |
| @Rpc(description = "Set byte value to a Characteristic") |
| public void gattServerCharacteristicSetValue(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "value") byte[] value) throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| mCharacteristicList.get(index).setValue(value); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Set value to a bluetooth gatt characteristic by instance id |
| * |
| * @param index the bluetooth gatt characteristic by instance id |
| * @param value value |
| * @throws Exception |
| */ |
| @Rpc(description = "Set byte value to a Characteristic by instance id") |
| public boolean gattServerCharacteristicSetValueByInstanceId( |
| @RpcParameter(name = "instanceId") Integer instanceId, |
| @RpcParameter(name = "value") byte[] value) throws Exception { |
| for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) { |
| //test this to be sure |
| if (mGattChar.getInstanceId() == instanceId) { |
| return mGattChar.setValue(value); |
| } |
| } |
| throw new Exception("Cannot find instance ID:" + instanceId); |
| } |
| |
| /** |
| * Set value to a bluetooth gatt characteristic |
| * |
| * @param index the bluetooth gatt characteristic |
| * @param value value |
| * @throws Exception |
| */ |
| @Rpc(description = "Set Characteristic Byte Value") |
| public boolean gattServerCharacteristicSetByteValue(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "value") byte[] value) throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| return mCharacteristicList.get(index).setValue(value); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Set value to a bluetooth gatt descriptor |
| * |
| * @param index the bluetooth gatt descriptor |
| * @param value byte[] value to set |
| * @throws Exception |
| */ |
| @Rpc(description = "Set Characteristic Byte Value") |
| public boolean gattServerDescriptorSetByteValue( |
| @RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "value") byte[] value) throws Exception { |
| if (mDescriptorList.get(index) != null) { |
| return mDescriptorList.get(index).setValue(value); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Get Read value by instance ID |
| * |
| * @param instanceId of the Characteristic of the Descriptor to get the value of |
| * @throws Exception |
| */ |
| @Rpc(description = "Returns the read value of a matching instanceId") |
| public byte[] gattServerGetReadValueByInstanceId( |
| @RpcParameter(name = "instanceId") Integer instanceId) |
| throws Exception { |
| for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) { |
| if (mGattChar.getInstanceId() == instanceId) { |
| Log.i("Found Characteristic to get value. instanceId: " |
| + Integer.toString(instanceId) |
| + " UUID: " + mGattChar.getUuid().toString()); |
| return mGattChar.getValue(); |
| } |
| List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors(); |
| for (BluetoothGattDescriptor mGattDesc : descList) { |
| if (mGattDesc.getInstanceId() == instanceId) { |
| Log.i("Found Descriptor to get value. instanceId: " |
| + Integer.toString(instanceId) |
| + " UUID: " + mGattDesc.getUuid().toString()); |
| return mGattDesc.getValue(); |
| } |
| } |
| } |
| throw new Exception("Cannot find instance ID:" + instanceId); |
| } |
| |
| /** |
| * Set value by instance ID |
| * |
| * @param instanceId of the Characteristic of the Descriptor to get the value of |
| * @value value set bytearray value |
| * @throws Exception |
| */ |
| @Rpc(description = "Sets the value of a Characteristic or Descriptor by instance id") |
| public boolean gattServerSetByteArrayValueByInstanceId( |
| @RpcParameter(name = "instanceId") Integer instanceId, |
| @RpcParameter(name = "value") byte[] value) |
| throws Exception { |
| for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) { |
| if (mGattChar.getInstanceId() == instanceId) { |
| Log.i("Found Characteristic to get value. instanceId: " |
| + Integer.toString(instanceId) |
| + " UUID: " + mGattChar.getUuid().toString()); |
| return mGattChar.setValue(value); |
| } |
| List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors(); |
| for (BluetoothGattDescriptor mGattDesc : descList) { |
| if (mGattDesc.getInstanceId() == instanceId) { |
| Log.i("Found Descriptor to set value. instanceId: " |
| + Integer.toString(instanceId) |
| + " UUID: " + mGattDesc.getUuid().toString()); |
| return mGattDesc.setValue(value); |
| } |
| } |
| } |
| throw new Exception("Cannot find instance ID:" + instanceId); |
| } |
| |
| /** |
| * Set BluetoothGattService instance ID to input value |
| * |
| * @param index the bluetooth gatt service |
| * @param instanceId instanceId |
| * @throws Exception |
| */ |
| @Rpc(description = "GATT Server Set Instance ID of Service") |
| public void gattServerServiceSetInstanceId( |
| @RpcParameter(name = "serviceIndex") Integer serviceIndex, |
| @RpcParameter(name = "instanceId") Integer instanceId) throws Exception { |
| if (mGattServiceList.get(serviceIndex) == null) { |
| throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex)); |
| } |
| Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService"); |
| Method setInstanceIdMethod = bluetoothGattServiceClass.getMethod( |
| "setInstanceId", int.class); |
| setInstanceIdMethod.invoke(mGattServiceList.get(serviceIndex), instanceId); |
| } |
| |
| /** |
| * GATT Server set the number of handles to reserve for this service |
| * |
| * @param index the bluetooth gatt service |
| * @param numHandles number of handles to reserve |
| * @throws Exception |
| */ |
| @Rpc(description = "GATT Server Set the number of handles to reserve for this service") |
| public void gattServerServiceSetHandlesToReserve( |
| @RpcParameter(name = "serviceIndex") Integer serviceIndex, |
| @RpcParameter(name = "numHandles") Integer numHandles) throws Exception { |
| if (mGattServiceList.get(serviceIndex) == null) { |
| throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex)); |
| } |
| Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService"); |
| Method setHandlesMethod = bluetoothGattServiceClass.getMethod( |
| "setHandles", int.class); |
| setHandlesMethod.invoke(mGattServiceList.get(serviceIndex), numHandles); |
| } |
| |
| /** |
| * GATT Server set service advertise perferred value |
| * |
| * @param index the bluetooth gatt service |
| * @param isPreferred if advertisement is preferred or not |
| * @throws Exception |
| */ |
| @Rpc(description = "GATT Server Set the number of handles to reserve for this service") |
| public void gattServerServiceIsAdvertisePreferred( |
| @RpcParameter(name = "serviceIndex") Integer serviceIndex, |
| @RpcParameter(name = "isPreferred") Boolean isPreferred) throws Exception { |
| if (mGattServiceList.get(serviceIndex) == null) { |
| throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex)); |
| } |
| Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService"); |
| Method setAdvertisePreferredMethod = bluetoothGattServiceClass.getMethod( |
| "setAdvertisePrefereed", boolean.class); |
| setAdvertisePreferredMethod.invoke(mGattServiceList.get(serviceIndex), isPreferred); |
| } |
| |
| /** |
| * GATT Service add included service. |
| * |
| * @param index the bluetooth gatt service |
| * @param serviceIncludedIndex index of the service to be included |
| * @throws Exception |
| */ |
| @Rpc(description = "Gatt Server add included service") |
| public void gattServerServiceaddIncludedService( |
| @RpcParameter(name = "serviceIndex") Integer serviceIndex, |
| @RpcParameter(name = "serviceIncludedIndex") Integer serviceIncludedIndex) |
| throws Exception { |
| if (mGattServiceList.get(serviceIndex) == null) { |
| throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex)); |
| } |
| if (mGattServiceList.get(serviceIncludedIndex) == null) { |
| throw new Exception("Invalid serviceIncludedIndex input:" + Integer.toString( |
| serviceIncludedIndex)); |
| } |
| Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService"); |
| Method addIncludedServiceMethod = bluetoothGattServiceClass.getMethod( |
| "addIncludedService", BluetoothGattService.class); |
| addIncludedServiceMethod.invoke( |
| mGattServiceList.get(serviceIndex), mGattServiceList.get(serviceIncludedIndex)); |
| } |
| |
| /** |
| * Set value to a bluetooth gatt characteristic |
| * |
| * @param index the bluetooth gatt characteristic |
| * @param value value |
| * @throws Exception |
| */ |
| @Rpc(description = "add descriptor to blutooth gatt characteristic") |
| public boolean gattServerCharacteristicSetStringValue( |
| @RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "value") String value) throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| return mCharacteristicList.get(index).setValue(value); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Set value to a bluetooth gatt characteristic |
| * |
| * @param index the bluetooth gatt characteristic |
| * @param value value |
| * @throws Exception |
| */ |
| @Rpc(description = "add descriptor to blutooth gatt characteristic") |
| public boolean gattServerCharacteristicSetIntValue(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "value") Integer value, |
| @RpcParameter(name = "type") Integer type, |
| @RpcParameter(name = "offset") Integer offset) |
| throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| return mCharacteristicList.get(index).setValue(value, type, offset); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Set the instance id of the Bluetooth Gatt Characteristic |
| * |
| * @param index the bluetooth gatt characteristic |
| * @param instanceId the instanceId to set |
| * @throws Exception |
| */ |
| @Rpc(description = "Set Caracteristic Instance id") |
| public void gattServerCharacteristicSetInstanceId(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "instanceId") Integer instanceId) |
| throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| mCharacteristicList.get(index).setInstanceId(instanceId); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Set the instance id of the Bluetooth Gatt Descriptor |
| * |
| * @param index the bluetooth gatt descriptor |
| * @param instanceId the instanceId to set |
| * @throws Exception |
| */ |
| @Rpc(description = "Set Descriptor Instance Id") |
| public void gattServerDescriptorSetInstanceId(@RpcParameter(name = "index") Integer index, |
| @RpcParameter(name = "instanceId") Integer instanceId) |
| throws Exception { |
| if (mDescriptorList.get(index) != null) { |
| Class bluetoothGattDescriptorClass = Class.forName( |
| "android.bluetooth.BluetoothGattDescriptor"); |
| Method setInstanceIdMethod = bluetoothGattDescriptorClass.getMethod( |
| "setInstanceId", int.class); |
| setInstanceIdMethod.invoke( |
| mDescriptorList.get(index), instanceId); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Get the instance id of the Bluetooth Gatt Characteristic |
| * |
| * @param index the bluetooth gatt characteristic |
| * @throws Exception |
| * @return the instance id of the characteristic |
| */ |
| @Rpc(description = "add descriptor to blutooth gatt characteristic") |
| public int gattServerCharacteristicGetInstanceId( |
| @RpcParameter(name = "index") Integer index) |
| throws Exception { |
| if (mCharacteristicList.get(index) != null) { |
| return mCharacteristicList.get(index).getInstanceId(); |
| } else { |
| throw new Exception("Invalid index input:" + index); |
| } |
| } |
| |
| /** |
| * Create a new GattCallback object |
| * |
| * @return the index of the callback object |
| */ |
| @Rpc(description = "Create a new GattCallback object") |
| public Integer gattServerCreateGattServerCallback() { |
| sGattServerCallbackCount += 1; |
| int index = sGattServerCallbackCount; |
| mBluetoothGattServerCallbackList.put(index, new BtGattServerCallback(index)); |
| return index; |
| } |
| |
| /** |
| * Create a new Descriptor object |
| * |
| * @param descriptorUuid the UUID for this descriptor |
| * @param permissions Permissions for this descriptor |
| * @return the index of the Descriptor object |
| */ |
| @Rpc(description = "Create a new Descriptor object") |
| public int gattServerCreateBluetoothGattDescriptor( |
| @RpcParameter(name = "descriptorUuid") String descriptorUuid, |
| @RpcParameter(name = "permissions") Integer permissions) { |
| sDescriptorCount += 1; |
| int index = sDescriptorCount; |
| BluetoothGattDescriptor descriptor = |
| new BluetoothGattDescriptor(UUID.fromString(descriptorUuid), permissions); |
| mDescriptorList.put(index, descriptor); |
| return index; |
| } |
| |
| private class BtGattServerCallback extends BluetoothGattServerCallback { |
| private final Bundle mResults; |
| private final int mIndex; |
| private final String mEventType; |
| |
| BtGattServerCallback(int idx) { |
| mResults = new Bundle(); |
| mEventType = "GattServer"; |
| mIndex = idx; |
| } |
| |
| @Override |
| public void onServiceAdded(int status, BluetoothGattService service) { |
| Log.d("gatt_server change onServiceAdded " + mEventType + " " + mIndex); |
| mResults.putString("serviceUuid", service.getUuid().toString()); |
| mResults.putInt("instanceId", service.getInstanceId()); |
| mEventFacade.postEvent(mEventType + mIndex + "onServiceAdded", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, |
| BluetoothGattCharacteristic characteristic) { |
| Log.d("gatt_server change onCharacteristicReadRequest " + mEventType + " " + mIndex); |
| mResults.putInt("requestId", requestId); |
| mResults.putInt("offset", offset); |
| mResults.putInt("instanceId", characteristic.getInstanceId()); |
| mResults.putInt("properties", characteristic.getProperties()); |
| mResults.putString("uuid", characteristic.getUuid().toString()); |
| mResults.putInt("permissions", characteristic.getPermissions()); |
| mEventFacade.postEvent( |
| mEventType + mIndex + "onCharacteristicReadRequest", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, |
| BluetoothGattCharacteristic characteristic, boolean preparedWrite, |
| boolean responseNeeded, int offset, byte[] value) { |
| Log.d("gatt_server change onCharacteristicWriteRequest " + mEventType + " " + mIndex); |
| mResults.putInt("requestId", requestId); |
| mResults.putInt("offset", offset); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putBoolean("preparedWrite", preparedWrite); |
| mResults.putBoolean("responseNeeded", responseNeeded); |
| mResults.putByteArray("value", value); |
| mResults.putInt("instanceId", characteristic.getInstanceId()); |
| mResults.putInt("properties", characteristic.getProperties()); |
| mResults.putString("uuid", characteristic.getUuid().toString()); |
| mResults.putInt("permissions", characteristic.getPermissions()); |
| mEventFacade.postEvent( |
| mEventType + mIndex + "onCharacteristicWriteRequest", mResults.clone()); |
| mResults.clear(); |
| |
| } |
| |
| @Override |
| public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, |
| BluetoothGattDescriptor descriptor) { |
| Log.d("gatt_server change onDescriptorReadRequest " + mEventType + " " + mIndex); |
| mResults.putInt("requestId", requestId); |
| mResults.putInt("offset", offset); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("instanceId", descriptor.getInstanceId()); |
| mResults.putInt("permissions", descriptor.getPermissions()); |
| mResults.putString("uuid", descriptor.getUuid().toString()); |
| mEventFacade.postEvent( |
| mEventType + mIndex + "onDescriptorReadRequest", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, |
| BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, |
| int offset, byte[] value) { |
| Log.d("gatt_server change onDescriptorWriteRequest " + mEventType + " " + mIndex); |
| mResults.putInt("requestId", requestId); |
| mResults.putInt("offset", offset); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putBoolean("preparedWrite", preparedWrite); |
| mResults.putBoolean("responseNeeded", responseNeeded); |
| mResults.putByteArray("value", value); |
| mResults.putInt("instanceId", descriptor.getInstanceId()); |
| mResults.putInt("permissions", descriptor.getPermissions()); |
| mResults.putString("uuid", descriptor.getUuid().toString()); |
| mEventFacade.postEvent( |
| mEventType + mIndex + "onDescriptorWriteRequest", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { |
| Log.d("gatt_server change onExecuteWrite " + mEventType + " " + mIndex); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("requestId", requestId); |
| mResults.putBoolean("execute", execute); |
| mEventFacade.postEvent(mEventType + mIndex + "onExecuteWrite", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onNotificationSent(BluetoothDevice device, int status) { |
| Log.d("gatt_server change onNotificationSent " + mEventType + " " + mIndex); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("status", status); |
| mEventFacade.postEvent(mEventType + mIndex + "onNotificationSent", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { |
| Log.d("gatt_server change onConnectionStateChange " + mEventType + " " + mIndex); |
| if (newState == BluetoothProfile.STATE_CONNECTED) { |
| Log.d("State Connected to mac address " + device.getAddress() + " status " |
| + status); |
| } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { |
| Log.d("State Disconnected from mac address " |
| + device.getAddress() + " status " + status); |
| } |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("status", status); |
| mResults.putInt("newState", newState); |
| mEventFacade.postEvent( |
| mEventType + mIndex + "onConnectionStateChange", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onMtuChanged(BluetoothDevice device, int mtu) { |
| Log.d("gatt_server change onMtuChanged " + mEventType + " " + mIndex); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("MTU", mtu); |
| mEventFacade.postEvent(mEventType + mIndex + "onMtuChanged", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) { |
| Log.d("gatt_server change onPhyRead " + mEventType + " " + mIndex); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("TxPhy", txPhy); |
| mResults.putInt("RxPhy", rxPhy); |
| mResults.putInt("Status", status); |
| mEventFacade.postEvent(mEventType + mIndex + "onPhyRead", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| @Override |
| public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) { |
| Log.d("gatt_server change onPhyUpdate " + mEventType + " " + mIndex); |
| mResults.putParcelable("BluetoothDevice", device); |
| mResults.putInt("TxPhy", txPhy); |
| mResults.putInt("RxPhy", rxPhy); |
| mResults.putInt("Status", status); |
| mEventFacade.postEvent(mEventType + mIndex + "onPhyUpdate", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| public void onConnectionUpdated(BluetoothDevice device, int interval, int latency, |
| int timeout, int status) { |
| Log.d("gatt_server change onConnecitonUpdated " + mEventType + " " + mIndex |
| + ", interval: " + interval + ", latency: " + latency |
| + ", timeout: " + timeout + ", status: " + status); |
| |
| mResults.putInt("Status", status); |
| mResults.putInt("Interval", interval); |
| mResults.putInt("Latency", latency); |
| mResults.putInt("Timeout", timeout); |
| mEventFacade.postEvent(mEventType + mIndex + "onConnectionUpdated", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| } |
| |
| @Override |
| public void shutdown() { |
| if (!mBluetoothGattServerList.isEmpty()) { |
| if (mBluetoothGattServerList.values() != null) { |
| for (BluetoothGattServer mBluetoothGattServer : mBluetoothGattServerList.values()) { |
| mBluetoothGattServer.close(); |
| } |
| } |
| } |
| } |
| } |