android bleiot
Installation
android studio
- Le test du bluetooth doit se faire obligatoirement avec un smartphone.
- Sous linux, il est nécessaire de mettre à jour les règles d’utilisation d’un composant USB :
$ wget http://web.enib.fr/~kerhoas/INSTALL_/51-android.rules.zip
$ unzip 51-android.rules.zip
$ cp 51-android.rules /etc/udev/rules.d/
Application BLEIOT
Projet Source
BleIotActivity.java
package fr.enib.bleiot_android;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
//==================================================================================================
public class BleIotActivity extends Activity {
private static final String TAG = "BleIotActivity";
private static TextView ledState;
AlertDialog mSelectionDialog;
DevicesAdapter mDevicesAdapter;
BluetoothAdapter mBluetoothAdapter;
BluetoothLeScanner mBluetoothLeScanner;
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
Handler mHandler;
boolean mScanning;
BluetoothGatt mGatt;
BluetoothGatt mWriteCharac;
private static final int REQUEST_ENABLE_BT = 1;
public static BluetoothGattCharacteristic mWriteCharacteristic;
private Queue<BluetoothGattDescriptor> descriptorWriteQueue = new LinkedList<>();
private static final int SCAN_PERIOD = 10000;
//##############
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
//==================================================================================================
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
mDevicesAdapter = new DevicesAdapter(getLayoutInflater());
if (Build.VERSION.SDK_INT >= 23) {
// Marshmallow+ Permission APIs
permMarshMallow();
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.select_device);
builder.setAdapter(mDevicesAdapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finishScanning();
BluetoothDevice device = (BluetoothDevice) mDevicesAdapter.getItem(i);
if (device != null) {
Log.i(TAG, "Connecting to GATT server at: " + device.getAddress());
mGatt = device.connectGatt(BleIotActivity.this, false, mGattCallback);
}
}
});
builder.setNegativeButton(R.string.cancel, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
finishScanning();
}
});
mSelectionDialog = builder.create();
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
setContentView(R.layout.activity_bleiot);
}
//==================================================================================================
// ALLOW PERMISSIONS
//==================================================================================================
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
) {
// All Permissions Granted
// Permission Denied
Toast.makeText(BleIotActivity.this, "All Permission GRANTED !! Thank You :)", Toast.LENGTH_SHORT)
.show();
} else {
// Permission Denied
Toast.makeText(BleIotActivity.this, "One or More Permissions are DENIED Exiting App :(", Toast.LENGTH_SHORT)
.show();
finish();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@TargetApi(Build.VERSION_CODES.M)
private void permMarshMallow() {
List<String> permissionsNeeded = new ArrayList<String>();
final List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add("Show Location");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "App need access to " + permissionsNeeded.get(0);
for (int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
showMessageOKCancel(message,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
}
});
return;
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
Toast.makeText(BleIotActivity.this, "No new Permission Required- Launching App .", Toast.LENGTH_SHORT)
.show();
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(BleIotActivity.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
@TargetApi(Build.VERSION_CODES.M)
private boolean addPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
//==================================================================================================
// SWITCH LED BUTTON
//==================================================================================================
public void onSwitchLedClick(View view) {
BluetoothGattCharacteristic charac = null;
List<BluetoothGattService> gattServices = getSupportedGattServices();
if (gattServices == null) {
Log.w(TAG, "Not services found.");
return;
}
for (BluetoothGattService gattService : gattServices) {
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
if (gattCharacteristic.getUuid().equals(AssignedNumber.getBleUuid("switch led"))) {
charac = gattCharacteristic;
}
}
}
if (charac == null) {
Log.e(TAG, "char not found!");
return;
}
byte[] value = new byte[1];
value[0] = (byte) (21 & 0xFF);
charac.setValue(value);
boolean status = mGatt.writeCharacteristic(charac);
return ;
}
//==================================================================================================
public void onConnectClick(View view) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
String btnText = ((Button) view).getText().toString();
if (btnText.equals(getString(R.string.connect))) {
openSelectionDialog();
} else if (btnText.equals(getString(R.string.disconnect))) {
mGatt.disconnect();
mGatt.close();
updateConnectButton(BluetoothProfile.STATE_DISCONNECTED);
}
}
}
//==================================================================================================
void openSelectionDialog() {
beginScanning();
mSelectionDialog.show();
}
//==================================================================================================
private void beginScanning() {
if (!mScanning) {
mDevicesAdapter.clear();
mDevicesAdapter.add(null);
mDevicesAdapter.updateScanningState(mScanning = true);
mDevicesAdapter.notifyDataSetChanged();
mLEScanner.startScan(mScanCallback);
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
finishScanning();
}
}, SCAN_PERIOD);
}
}
//==================================================================================================
private void finishScanning() {
if (mScanning) {
if (mDevicesAdapter.getItem(0) == null) {
mDevicesAdapter.notifyDataSetChanged();
}
}
else { mLEScanner.stopScan(mScanCallback); }
}
//==================================================================================================
private void disconnect() {
if (mGatt != null) {
mGatt.disconnect();
mGatt.close();
mGatt = null;
}
}
//==================================================================================================
@Override
protected void onPause() {
super.onPause();
finishScanning();
}
//==================================================================================================
@Override
protected void onDestroy() {
super.onDestroy();
disconnect();
}
//==================================================================================================
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == Activity.RESULT_OK) {
openSelectionDialog();
} else if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this, "App cannot run with bluetooth off", Toast.LENGTH_LONG).show();
finish();
}
} else
super.onActivityResult(requestCode, resultCode, data);
}
//==================================================================================================
private void updateConnectButton(int state) {
Button connectBtn = (Button) BleIotActivity.this.findViewById(R.id.connect_button);
switch (state) {
case BluetoothProfile.STATE_DISCONNECTED:
connectBtn.setText(getString(R.string.connect));
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView pressionTxt = (TextView) BleIotActivity.this.findViewById(R.id.Pvalue);
pressionTxt.setText("--");
TextView temperatureTxt = (TextView)BleIotActivity.this.findViewById(R.id.Tvalue);
temperatureTxt.setText(R.string.Tvalue);
}
});
break;
case BluetoothProfile.STATE_CONNECTING:
connectBtn.setText(getString(R.string.connecting));
break;
case BluetoothProfile.STATE_CONNECTED:
connectBtn.setText(getString(R.string.disconnect));
break;
}
}
//==================================================================================================
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
BluetoothDevice bluetoothDevice = result.getDevice();
connectToDevice(bluetoothDevice);
mDevicesAdapter.add(bluetoothDevice);
mDevicesAdapter.notifyDataSetChanged();
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
//==================================================================================================
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
mGatt = device.connectGatt(this, false, mGattCallback);
finishScanning();// will stop after first device detection
}
}
//==================================================================================================
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, final int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
if (mGatt.discoverServices()) {
Log.i(TAG, "Started service discovery.");
} else {
Log.w(TAG, "Service discovery failed.");
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
}
runOnUiThread(new Runnable() {
@Override
public void run() {
updateConnectButton(newState);
}
});
}
//==================================================================================================
// Callback called when a service is discovered
// Make a list of supported GATT services and subscribe to the characteristics.
//==================================================================================================
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
List<BluetoothGattService> gattServices = getSupportedGattServices();
if (gattServices == null) {
Log.w(TAG, "No services found.");
return;
}
mDevicesAdapter.updateScanningState(mScanning = false);
finishScanning();
for (BluetoothGattService gattService : gattServices) {
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
if (gattCharacteristic.getUuid().equals(AssignedNumber.getBleUuid("Pressure"))) {
mGatt.setCharacteristicNotification(gattCharacteristic, true);// Enable notifications.
BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(AssignedNumber.getBleUuid("Client Characteristic Configuration"));
descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE );
writeGattDescriptor(descriptor);
Log.i(TAG, "Pression characteristic subscription done");
}
if (gattCharacteristic.getUuid().equals(AssignedNumber.getBleUuid("switch led"))) {
mGatt.setCharacteristicNotification(gattCharacteristic, true);// Enable notifications.
Log.i(TAG, "SWITCH LED subscription done");
}
if (gattCharacteristic.getUuid().equals(AssignedNumber.getBleUuid("led state"))) {
mGatt.setCharacteristicNotification(gattCharacteristic, true);// Enable notifications.
BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(AssignedNumber.getBleUuid("Client Characteristic Configuration"));
descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE );
writeGattDescriptor(descriptor);
Log.i(TAG, "LED STATE subscription done");
}
if (gattCharacteristic.getUuid().equals(AssignedNumber.getBleUuid("Temperature"))) {
mGatt.setCharacteristicNotification(gattCharacteristic, true);// Enable notifications.
BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(AssignedNumber.getBleUuid("Client Characteristic Configuration"));
descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE );
writeGattDescriptor(descriptor);
Log.i(TAG, "Temperature characteristic subscription done");
}
}
}
}
//==================================================================================================
// Callback called when a characteristic change
// Check which characteristic has changed and update the TextView accordingly
//==================================================================================================
@Override
public void onCharacteristicChanged (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
if (characteristic.getUuid().equals(AssignedNumber.getBleUuid("Pressure"))) {
// Log.i(TAG, "Pressure has changed");
float pressure100 = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32,0).floatValue();
final float pressure = pressure100 / 100.0f; // 2 decimals
runOnUiThread(new Runnable() {
public void run() {
TextView pressureTxt = (TextView) BleIotActivity.this.findViewById(R.id.Pvalue);
pressureTxt.setText(String.format("%.2f hPa", pressure));
}
});
Log.d(TAG, String.format("Update pressure: %.2f hPa", pressure));
}
if (characteristic.getUuid().equals(AssignedNumber.getBleUuid("led state"))) {
// Log.i(TAG, "led state has changed");
final int state = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16,0);
runOnUiThread(new Runnable() {
public void run() {
if(state == 0){
TextView textLedState = (TextView) BleIotActivity.this.findViewById(R.id.textLedState);
textLedState.setText(String.format("LED OFF"));
}
else{
TextView textLedState = (TextView) BleIotActivity.this.findViewById(R.id.textLedState);
textLedState.setText(String.format("LED ON"));
}
}
});
}
if (characteristic.getUuid().equals(AssignedNumber.getBleUuid("Temperature"))) {
// Log.i(TAG, "Temperature has changed");
float temperature100 = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT16,0).floatValue();
final float temperature = temperature100 / 10.0f; // 2 decimals
runOnUiThread(new Runnable() {
public void run() {
TextView temperatureTxt = (TextView) BleIotActivity.this.findViewById(R.id.Tvalue);
temperatureTxt.setText(String.format("%.1f°C", temperature));
}
});
Log.d(TAG, String.format("Update temperature: %.1f°C", temperature));
}
}
/******************* Callback called when descriptor is written ***************************/
/**** Indicates the result of the operation and deals with the descriptor write queue. ****/
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
Log.d(TAG, "GATT onDescriptorWrite()");
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "GATT: Descriptor wrote successfully."); //Operation ended successfully.
} else {
Log.d(TAG, "GATT: Error writing descriptor (" + status + ").");
}
descriptorWriteQueue.remove();
if (descriptorWriteQueue.size() > 0) {
mGatt.writeDescriptor(descriptorWriteQueue.element());
}
}
};
//==================================================================================================
/************************** Method to write a descriptor. *************************************/
//==================================================================================================
public void writeGattDescriptor(BluetoothGattDescriptor descriptor) {
descriptorWriteQueue.add(descriptor);
Log.d(TAG, "Subscribed to " + descriptorWriteQueue.size() + " notification/s");
try {
if (descriptorWriteQueue.size() == 1)
mGatt.writeDescriptor(descriptor);
} catch (Exception e) {
e.getLocalizedMessage();
}
}
//==================================================================================================
/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mGatt == null)
return null;
return mGatt.getServices();
}
}
//==================================================================================================
AssignedNumber.java
package fr.enib.bleiot_android;
import android.util.SparseArray;
import java.util.UUID;
/**
* Created by tomcot01 on 21/08/2014.
* ARM University Program Copyright © ARM Ltd 2014
*/
public class AssignedNumber {
private static SparseArray<String> sAssignedNumbers = new SparseArray<String>();
// private static final String FORMAT_BLE_UUID_DESCRIPTOR = "0000%04x-0000-1000-8000-00805f9b34fb";
//private static final String FORMAT_BLE_UUID = "0000%04x-0001-11e1-ac36-0002a5d5c51b";
//private static final String FORMAT_BLE_UUID = "0000%04x-0000-1000-8000-00805f9b34fb";
private static final String FORMAT_BLE_UUID = "0000%04x-0000-1000-8000-00805f9b34fb";
static {
// Services.
// Taken from https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
sAssignedNumbers.put(0x1811, "Alert Notification Service");
sAssignedNumbers.put(0x180F, "Battery Service");
sAssignedNumbers.put(0x1810, "Blood Pressure");
sAssignedNumbers.put(0x1805, "Current Time Service");
sAssignedNumbers.put(0x1818, "Cycling Power");
sAssignedNumbers.put(0x1816, "Cycling Speed and Cadence");
sAssignedNumbers.put(0x180A, "Device Information");
sAssignedNumbers.put(0x1800, "Generic Access");
sAssignedNumbers.put(0x1801, "Generic Attribute");
sAssignedNumbers.put(0x1808, "Glucose");
sAssignedNumbers.put(0x1809, "Health Thermometer");
sAssignedNumbers.put(0x180D, "Heart Rate");
sAssignedNumbers.put(0x1812, "Human Interface Device");
sAssignedNumbers.put(0x1802, "Immediate Alert");
sAssignedNumbers.put(0x1803, "Link Loss");
sAssignedNumbers.put(0x1819, "Location and Navigation");
sAssignedNumbers.put(0x1807, "Next DST Change Service");
sAssignedNumbers.put(0x180E, "Phone Alert Status Service");
sAssignedNumbers.put(0x1806, "Reference Time Update Service");
sAssignedNumbers.put(0x1814, "Running Speed and Cadence");
sAssignedNumbers.put(0x1813, "Scan Parameters");
sAssignedNumbers.put(0x1804, "Tx Power");
sAssignedNumbers.put(0x181A, "Environmental Sensing");
sAssignedNumbers.put(0x181B, "Environmental Sensing2");
sAssignedNumbers.put(0x181C, "User Data");
//+++++++++++++++++++USER DEFINED SERVICES++++++++++++++++++
sAssignedNumbers.put(0xFF10, "led service");
// Characteristics.
// Taken from https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx
sAssignedNumbers.put(0x2A7E, "Aerobic Heart Rate Lower Limit");
sAssignedNumbers.put(0x2A84, "Aerobic Heart Rate Upper Limit");
sAssignedNumbers.put(0x2A7F, "Aerobic Threshold");
sAssignedNumbers.put(0x2A80, "Age");
sAssignedNumbers.put(0x2A43, "Alert Category ID");
sAssignedNumbers.put(0x2A42, "Alert Category ID Bit Mask");
sAssignedNumbers.put(0x2A06, "Alert Level");
sAssignedNumbers.put(0x2A44, "Alert Notification Control Point");
sAssignedNumbers.put(0x2A3F, "Alert Status");
sAssignedNumbers.put(0x2A81, "Anaerobic Heart Rate Lower Limit");
sAssignedNumbers.put(0x2A82, "Anaerobic Heart Rate Upper Limit");
sAssignedNumbers.put(0x2A83, "Anaerobic Threshold");
sAssignedNumbers.put(0x2A01, "Appearance");
sAssignedNumbers.put(0x2A19, "Battery Level");
sAssignedNumbers.put(0x2A49, "Blood Pressure Feature");
sAssignedNumbers.put(0x2A35, "Blood Pressure Measurement");
sAssignedNumbers.put(0x2A38, "Body Sensor Location");
sAssignedNumbers.put(0x2A22, "Boot Keyboard Input Report");
sAssignedNumbers.put(0x2A32, "Boot Keyboard Output Report");
sAssignedNumbers.put(0x2A33, "Boot Mouse Input Report");
sAssignedNumbers.put(0x2A5C, "CSC Feature");
sAssignedNumbers.put(0x2A5B, "CSC Measurement");
sAssignedNumbers.put(0x2A2B, "Current Time");
sAssignedNumbers.put(0x2A66, "Cycling Power Control Point");
sAssignedNumbers.put(0x2A65, "Cycling Power Feature");
sAssignedNumbers.put(0x2A63, "Cycling Power Measurement");
sAssignedNumbers.put(0x2A64, "Cycling Power Vector");
sAssignedNumbers.put(0x2A99, "Database Change Increment");
sAssignedNumbers.put(0x2A85, "Date of Birth");
sAssignedNumbers.put(0x2A86, "Date of Threshold Assessment ");
sAssignedNumbers.put(0x2A08, "Date Time");
sAssignedNumbers.put(0x2A0A, "Day Date Time");
sAssignedNumbers.put(0x2A09, "Day of Week");
sAssignedNumbers.put(0x2A00, "Device Name");
sAssignedNumbers.put(0x2A0D, "DST Offset");
sAssignedNumbers.put(0x2A87, "Email Address");
sAssignedNumbers.put(0x2A0C, "Exact Time 256");
sAssignedNumbers.put(0x2A88, "Fat Burn Heart Rate Lower Limit");
sAssignedNumbers.put(0x2A89, "Fat Burn Heart Rate Upper Limit");
sAssignedNumbers.put(0x2A26, "Firmware Revision String");
sAssignedNumbers.put(0x2A8A, "First Name");
sAssignedNumbers.put(0x2A8B, "Five Zone Heart Rate Limits");
sAssignedNumbers.put(0x2A8C, "Gender");
sAssignedNumbers.put(0x2A51, "Glucose Feature");
sAssignedNumbers.put(0x2A18, "Glucose Measurement");
sAssignedNumbers.put(0x2A34, "Glucose Measurement Context");
sAssignedNumbers.put(0x2A27, "Hardware Revision String");
sAssignedNumbers.put(0x2A39, "Heart Rate Control Point");
sAssignedNumbers.put(0x2A8D, "Heart Rate Max");
sAssignedNumbers.put(0x2A37, "Heart Rate Measurement");
sAssignedNumbers.put(0x2A8E, "Height");
sAssignedNumbers.put(0x2A4C, "HID Control Point");
sAssignedNumbers.put(0x2A4A, "HID Information");
sAssignedNumbers.put(0x2A8F, "Hip Circumference");
sAssignedNumbers.put(0x2A6F, "Humidity");
sAssignedNumbers.put(0x2A2A, "IEEE 11073-20601 Regulatory Certification Data List");
sAssignedNumbers.put(0x2A36, "Intermediate Cuff Pressure");
sAssignedNumbers.put(0x2A1E, "Intermediate Temperature");
sAssignedNumbers.put(0x2AA2, "Language");
sAssignedNumbers.put(0x2A90, "Last Name");
sAssignedNumbers.put(0x2A6B, "LN Control Point");
sAssignedNumbers.put(0x2A6A, "LN Feature");
sAssignedNumbers.put(0x2A0F, "Local Time Information");
sAssignedNumbers.put(0x2A67, "Location and Speed");
sAssignedNumbers.put(0x2A29, "Manufacturer Name String");
sAssignedNumbers.put(0x2A91, "Maximum Recommended Heart Rate");
sAssignedNumbers.put(0x2A21, "Measurement Interval");
sAssignedNumbers.put(0x2A24, "Model Number String");
sAssignedNumbers.put(0x2A68, "Navigation");
sAssignedNumbers.put(0x2A46, "New Alert");
sAssignedNumbers.put(0x2A04, "Peripheral Preferred Connection Parameters");
sAssignedNumbers.put(0x2A02, "Peripheral Privacy Flag");
sAssignedNumbers.put(0x2A50, "PnP ID");
sAssignedNumbers.put(0x2A69, "Position Quality");
sAssignedNumbers.put(0x2A6D, "Pressure");
sAssignedNumbers.put(0x2A4E, "Protocol Mode");
sAssignedNumbers.put(0x2A03, "Reconnection Address");
sAssignedNumbers.put(0x2A52, "Record Access Control Point");
sAssignedNumbers.put(0x2A14, "Reference Time Information");
sAssignedNumbers.put(0x2A4D, "Report");
sAssignedNumbers.put(0x2A4B, "Report Map");
sAssignedNumbers.put(0x2A92, "Resting Heart Rate");
sAssignedNumbers.put(0x2A40, "Ringer Control Point");
sAssignedNumbers.put(0x2A41, "Ringer Setting");
sAssignedNumbers.put(0x2A54, "RSC Feature");
sAssignedNumbers.put(0x2A53, "RSC Measurement");
sAssignedNumbers.put(0x2A55, "SC Control Point");
sAssignedNumbers.put(0x2A4F, "Scan Interval Window");
sAssignedNumbers.put(0x2A31, "Scan Refresh");
sAssignedNumbers.put(0x2A5D, "Sensor Location");
sAssignedNumbers.put(0x2A25, "Serial Number String");
sAssignedNumbers.put(0x2A05, "Service Changed");
sAssignedNumbers.put(0x2A28, "Software Revision String");
sAssignedNumbers.put(0x2A93, "Sport Type for Aerobic and Anaerobic Thresholds");
sAssignedNumbers.put(0x2A47, "Supported New Alert Category");
sAssignedNumbers.put(0x2A48, "Supported Unread Alert Category");
sAssignedNumbers.put(0x2A23, "System ID");
sAssignedNumbers.put(0x2A6E, "Temperature");
sAssignedNumbers.put(0x2A1C, "Temperature Measurement");
sAssignedNumbers.put(0x2A1D, "Temperature Type");
sAssignedNumbers.put(0x2A94, "Three Zone Heart Rate Limits");
sAssignedNumbers.put(0x2A12, "Time Accuracy");
sAssignedNumbers.put(0x2A13, "Time Source");
sAssignedNumbers.put(0x2A71, "True Wind Direction");
//+++++++++++++++++++USER DEFINED CHAR++++++++++++++++++
sAssignedNumbers.put(0xFF12, "switch led");
sAssignedNumbers.put(0xFF11, "led state");
// GATT
// https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-attribute-profile
sAssignedNumbers.put(0x1800, "Generic Access Profile");
sAssignedNumbers.put(0x1801, "Generic Attribute Profile");
sAssignedNumbers.put(0x2800, "Primary Service");
sAssignedNumbers.put(0x2801, "Secondary Service");
sAssignedNumbers.put(0x2802, "Include");
sAssignedNumbers.put(0x2803, "Characteristic");
sAssignedNumbers.put(0x2900, "Characteristic Extended Properties");
sAssignedNumbers.put(0x2901, "Characteristic User Description");
sAssignedNumbers.put(0x2902, "Client Characteristic Configuration");
sAssignedNumbers.put(0x2903, "Server Characteristic Configuration");
sAssignedNumbers.put(0x2904, "Characteristic Format");
sAssignedNumbers.put(0x2905, "Characteristic Aggregate Format");
sAssignedNumbers.put(0x2A00, "Device Name");
sAssignedNumbers.put(0x2A01, "Appearance");
sAssignedNumbers.put(0x2A02, "Peripheral Privacy Flag");
sAssignedNumbers.put(0x2A03, "Reconnection Address");
sAssignedNumbers.put(0x2A04, "Peripheral Preferred Connection Parameters");
sAssignedNumbers.put(0x2A05, "Service Changed");
}
public static UUID getBleUuid(String name) {
for(int i = 0; i < sAssignedNumbers.size(); i++){
int key = sAssignedNumbers.keyAt(i);
if (sAssignedNumbers.valueAt(i).equals(name)) {
return UUID.fromString(String.format(FORMAT_BLE_UUID, key));
}
}
return null;
}
public static int get(String name) {
for(int i = 0; i < sAssignedNumbers.size(); i++){
int key = sAssignedNumbers.keyAt(i);
if (sAssignedNumbers.valueAt(i).equals(name)) {
return key;
}
}
return -1;
}
}