Java tutorial
/** * Cerevo BlueNinja BLE Sample for Android * @auther Cerevo Inc. * @since 2015/08/04 */ /* Copyright 2015 Cerevo Inc. 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.cerevo.blueninja.blueninja_ble_example; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.os.Bundle; import android.os.Message; import android.util.Log; 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.os.Handler; import android.view.View; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { // BLE(ms) private static final int SCAN_TIMEOUT = 10000; //??? private static final String DEVICE_NAME = "CDP-TZ01B"; /* UUIDs */ //BlueNinja Example Service private static final String UUID_SERVICE_BNEXAM = "d43a0200-0e5f-4a80-9182-5f82ff67e8f8"; // private static final String UUID_CHARACTERISTIC_GYRO = "d43a0201-0e5f-4a80-9182-5f82ff67e8f8"; // private static final String UUID_CHARACTERISTIC_ACCEL = "d43a0202-0e5f-4a80-9182-5f82ff67e8f8"; //? private static final String UUID_CHARACTERISTIC_MAGM = "d43a0203-0e5f-4a80-9182-5f82ff67e8f8"; // private static final String UUID_CHARACTERISTIC_AIRP = "d43a0212-0e5f-4a80-9182-5f82ff67e8f8"; //UUID private static final String[] UUIDS_CHARACTERISTIC = { UUID_CHARACTERISTIC_ACCEL, UUID_CHARACTERISTIC_GYRO, UUID_CHARACTERISTIC_MAGM, UUID_CHARACTERISTIC_AIRP }; //UUID private static final String UUID_CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; //?TAG private static final String TAG = "BNBLE"; private AppState mAppStat = AppState.INIT; private Handler mHandler; private BluetoothAdapter mBtAdapter; private BluetoothManager mBtManager; private BluetoothGatt mBtGatt; private BluetoothGatt mGatt; private BluetoothGattCharacteristic[] mCharacteristics = new BluetoothGattCharacteristic[UUIDS_CHARACTERISTIC.length]; private TextView mTextStatus; private Button mBtnConn; private Button mBtnDiscon; private Button mBtnDisable; private Button mBtnEnable; private TextView mTextAccelX; private TextView mTextAccelY; private TextView mTextAccelZ; private TextView mTextGyroX; private TextView mTextGyroY; private TextView mTextGyroZ; private TextView mTextMagnetoX; private TextView mTextMagnetoY; private TextView mTextMagnetoZ; private TextView mTextAirpressure; private TextView mTextAxisAngle; private ProgressBar mProgressAccelX; private ProgressBar mProgressAccelY; private ProgressBar mProgressAccelZ; private ProgressBar mProgressGyroX; private ProgressBar mProgressGyroY; private ProgressBar mProgressGyroZ; private ProgressBar mProgressMagnetoX; private ProgressBar mProgressMagnetoY; private ProgressBar mProgressMagnetoZ; private double mAccel[]; private double mGyro[]; private double mMagm[]; private String mAxisAngle; private double mAirp; /** * ?? */ public View.OnClickListener buttonClickListener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnConn: /* */ connectBle(); break; case R.id.btnDisConn: /* */ disconnectBle(); break; case R.id.btnDisable: /* Disable Notification */ disableBleNotification(); break; case R.id.btnEnable: /* Enable Notification */ enableBleNotification(); break; } } }; @Override /** * */ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* Bluetooth?? */ mBtManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); mBtAdapter = mBtManager.getAdapter(); if ((mBtAdapter == null) || !mBtAdapter.isEnabled()) { Toast.makeText(getApplicationContext(), "Bluetooth??????", Toast.LENGTH_SHORT) .show(); finish(); } /* ?? */ // mTextStatus = (TextView) findViewById(R.id.textView1); // mBtnConn = (Button) findViewById(R.id.btnConn); mBtnConn.setOnClickListener(buttonClickListener); mBtnConn.setEnabled(true); // mBtnDiscon = (Button) findViewById(R.id.btnDisConn); mBtnDiscon.setOnClickListener(buttonClickListener); mBtnDiscon.setEnabled(false); //Notification mBtnDisable = (Button) findViewById(R.id.btnDisable); mBtnDisable.setOnClickListener(buttonClickListener); mBtnDisable.setEnabled(false); //Notification mBtnEnable = (Button) findViewById(R.id.btnEnable); mBtnEnable.setOnClickListener(buttonClickListener); mBtnEnable.setEnabled(false); /* */ mTextAccelX = (TextView) findViewById(R.id.textAccelX); mTextAccelY = (TextView) findViewById(R.id.textAccelY); mTextAccelZ = (TextView) findViewById(R.id.textAccelZ); mProgressAccelX = (ProgressBar) findViewById(R.id.progressAccelX); mProgressAccelY = (ProgressBar) findViewById(R.id.progressAccelY); mProgressAccelZ = (ProgressBar) findViewById(R.id.progressAccelZ); /* */ mTextGyroX = (TextView) findViewById(R.id.textGyroX); mTextGyroY = (TextView) findViewById(R.id.textGyroY); mTextGyroZ = (TextView) findViewById(R.id.textGyroZ); mProgressGyroX = (ProgressBar) findViewById(R.id.progressGyroX); mProgressGyroY = (ProgressBar) findViewById(R.id.progressGyroY); mProgressGyroZ = (ProgressBar) findViewById(R.id.progressGyroZ); /* ? */ mTextMagnetoX = (TextView) findViewById(R.id.textMagnetoX); mTextMagnetoY = (TextView) findViewById(R.id.textMagnetoY); mTextMagnetoZ = (TextView) findViewById(R.id.textMagnetoZ); mProgressMagnetoX = (ProgressBar) findViewById(R.id.progressMagnetoX); mProgressMagnetoY = (ProgressBar) findViewById(R.id.progressMagnetoY); mProgressMagnetoZ = (ProgressBar) findViewById(R.id.progressMagnetoZ); /* */ mTextAirpressure = (TextView) findViewById(R.id.textAirpressure); /* UI? */ mHandler = new Handler() { @Override public void handleMessage(Message msg) { mTextStatus.setText((String) msg.obj); AppState state = AppState.values()[msg.what]; switch (state) { case BLE_READY: mBtnConn.setEnabled(false); mBtnDiscon.setEnabled(true); mBtnDisable.setEnabled(true); mBtnEnable.setEnabled(true); break; case BLE_BUSY: mBtnDisable.setEnabled(false); mBtnEnable.setEnabled(false); break; case BLE_CLOSED: mBtnConn.setEnabled(true); mBtnDiscon.setEnabled(false); mBtnDisable.setEnabled(false); mBtnEnable.setEnabled(false); break; case BLE_DISCONNECTED: mBtnConn.setEnabled(true); mBtnDiscon.setEnabled(false); mBtnDisable.setEnabled(false); mBtnEnable.setEnabled(false); break; case BLE_DATA_UPDATE: ValueType vt = ValueType.values()[msg.arg1]; switch (vt) { case VT_ACCEL: /* */ mTextAccelX.setText(String.format("X:%5.1fG", mAccel[0])); mProgressAccelX.setProgress((int) (mAccel[0] * 80) + 160); mTextAccelY.setText(String.format("Y:%5.1fG", mAccel[1])); mProgressAccelY.setProgress((int) (mAccel[1] * 80) + 160); mTextAccelZ.setText(String.format("Z:%5.1fG", mAccel[2])); mProgressAccelZ.setProgress((int) (mAccel[2] * 80) + 160); break; case VT_GYRO: /* */ mTextGyroX.setText(String.format("X:%7.1fdig/s", mGyro[0])); mProgressGyroX.setProgress((int) (mGyro[0] * 3) + 2000); mTextGyroY.setText(String.format("Y:%7.1fdig/s", mGyro[1])); mProgressGyroY.setProgress((int) (mGyro[1] * 3) + 2000); mTextGyroZ.setText(String.format("Z:%7.1fdig/s", mGyro[2])); mProgressGyroZ.setProgress((int) (mGyro[2] * 3) + 2000); break; case VT_MAGM: /* ? */ mTextMagnetoX.setText(String.format("X:%7.1fuH", mMagm[0])); mProgressMagnetoX.setProgress((int) (mMagm[0] * 5) + 4000); mTextMagnetoY.setText(String.format("Y:%7.1fuH", mMagm[1])); mProgressMagnetoY.setProgress((int) (mMagm[1] * 5) + 4000); mTextMagnetoZ.setText(String.format("Z:%7.1fuH", mMagm[2])); mProgressMagnetoZ.setProgress((int) (mMagm[2] * 5) + 4000); break; case VT_AIRP: /* */ mTextAirpressure.setText(String.format("%7.1fPa", mAirp)); break; case VT_ANGL: /* */ mTextAxisAngle.setText(mAxisAngle); break; } break; default: break; } } }; //?? mGyro = new double[3]; mAccel = new double[3]; mMagm = new double[3]; } /** * Characteristic?Notification? */ private void enableBleNotification() { for (int i = 0; i < UUIDS_CHARACTERISTIC.length; i++) { boolean reg = mGatt.setCharacteristicNotification(mCharacteristics[i], true); BluetoothGattDescriptor desc = mCharacteristics[i] .getDescriptor(UUID.fromString(UUID_CLIENT_CHARACTERISTIC_CONFIG)); desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mGatt.writeDescriptor(desc); if (!reg) { setStatus(AppState.BLE_NOTIF_REGISTER_FAILED); return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } setStatus(AppState.BLE_NOTIF_REGISTERD); } /** * Characteristic?Notification? */ private void disableBleNotification() { for (int i = 0; i < UUIDS_CHARACTERISTIC.length; i++) { BluetoothGattDescriptor desc = mCharacteristics[i] .getDescriptor(UUID.fromString(UUID_CLIENT_CHARACTERISTIC_CONFIG)); desc.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); mGatt.writeDescriptor(desc); if (!mGatt.setCharacteristicNotification(mCharacteristics[i], false)) { setStatus(AppState.BLE_NOTIF_REGISTER_FAILED); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } setStatus(AppState.BLE_NOTIF_REGISTERD); } /** * BLE?? */ private void connectBle() { mHandler.postDelayed(new Runnable() { @Override public void run() { mBtAdapter.stopLeScan(mLeScanCallBack); if (AppState.BLE_SCANNING.equals(getStatus())) { setStatus(AppState.BLE_SCAN_FAILED); } } }, SCAN_TIMEOUT); mBtAdapter.stopLeScan(mLeScanCallBack); mBtAdapter.startLeScan(mLeScanCallBack); setStatus(AppState.BLE_SCANNING); } /** * BLE */ private void disconnectBle() { if (mBtGatt != null) { mBtGatt.close(); mBtGatt = null; for (int i = 0; i < UUIDS_CHARACTERISTIC.length; i++) { mCharacteristics[i] = null; } setStatus(AppState.BLE_CLOSED); } } /** * BLECallback */ private BluetoothAdapter.LeScanCallback mLeScanCallBack = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { Log.d(TAG, String.format("Device found: %s[%s]", device.getName(), device.getUuids())); if (DEVICE_NAME.equals(device.getName())) { //BlueNinja setStatus(AppState.BLE_DEV_FOUND); mBtAdapter.stopLeScan(this); mBtGatt = device.connectGatt(getApplicationContext(), false, mBluetoothGattCallback); } } }; private final BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); switch (newState) { case BluetoothProfile.STATE_CONNECTED: gatt.discoverServices(); break; case BluetoothProfile.STATE_DISCONNECTED: setStatus(AppState.BLE_DISCONNECTED); mBtGatt = null; break; } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { BluetoothGattService service = gatt.getService(UUID.fromString(UUID_SERVICE_BNEXAM)); if (service == null) { /* ????? */ setStatus(AppState.BLE_SRV_NOT_FOUND); } else { /* */ setStatus(AppState.BLE_SRV_FOUND); for (int i = 0; i < UUIDS_CHARACTERISTIC.length; i++) { mCharacteristics[i] = service.getCharacteristic(UUID.fromString(UUIDS_CHARACTERISTIC[i])); if (mCharacteristics[i] == null) { /* Characteristic????? */ setStatus(AppState.BLE_CHARACTERISTIC_NOT_FOUND); return; } } mGatt = gatt; setStatus(AppState.BLE_READY); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.d(TAG, String.format("onCharacteristicWrite: %d", status)); setStatus(AppState.BLE_READY); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.d(TAG, "onCharacteristicChanged"); /* */ if (UUID_CHARACTERISTIC_ACCEL.equals(characteristic.getUuid().toString())) { byte[] read_data = characteristic.getValue(); try { JSONObject json = new JSONObject(new String(read_data)); mAccel[0] = json.getDouble("ax"); mAccel[1] = json.getDouble("ay"); mAccel[2] = json.getDouble("az"); setStatus(AppState.BLE_DATA_UPDATE, ValueType.VT_ACCEL); } catch (JSONException e) { e.printStackTrace(); } } /* */ if (UUID_CHARACTERISTIC_GYRO.equals(characteristic.getUuid().toString())) { byte[] read_data = characteristic.getValue(); try { JSONObject json = new JSONObject(new String(read_data)); mGyro[0] = json.getDouble("gx"); mGyro[1] = json.getDouble("gy"); mGyro[2] = json.getDouble("gz"); setStatus(AppState.BLE_DATA_UPDATE, ValueType.VT_GYRO); } catch (JSONException e) { e.printStackTrace(); } } /* ? */ if (UUID_CHARACTERISTIC_MAGM.equals(characteristic.getUuid().toString())) { byte[] read_data = characteristic.getValue(); try { JSONObject json = new JSONObject(new String(read_data)); mMagm[0] = json.getDouble("mx"); mMagm[1] = json.getDouble("my"); mMagm[2] = json.getDouble("mz"); setStatus(AppState.BLE_DATA_UPDATE, ValueType.VT_MAGM); } catch (JSONException e) { e.printStackTrace(); } } /* */ if (UUID_CHARACTERISTIC_AIRP.equals(characteristic.getUuid().toString())) { byte[] read_data = characteristic.getValue(); try { JSONObject json = new JSONObject(new String(read_data)); mAirp = json.getDouble("ap"); setStatus(AppState.BLE_DATA_UPDATE, ValueType.VT_AIRP); } catch (JSONException e) { e.printStackTrace(); } } } }; private enum ValueType { VT_ACCEL, VT_GYRO, VT_MAGM, VT_AIRP, VT_ANGL, } /** * ? */ private enum AppState { INIT, BLE_SCANNING, BLE_SCAN_FAILED, BLE_DEV_FOUND, BLE_SRV_NOT_FOUND, BLE_SRV_FOUND, BLE_CHARACTERISTIC_NOT_FOUND, BLE_NOTIF_REGISTERD, BLE_NOTIF_REGISTER_FAILED, BLE_DATA_UPDATE, BLE_READY, BLE_BUSY, BLE_DISCONNECTED, BLE_CLOSED } /** * Set application status * @param stat Application state. */ private void setStatus(AppState stat) { Message msg = new Message(); msg.what = stat.ordinal(); msg.obj = stat.name(); mAppStat = stat; mHandler.sendMessage(msg); } private void setStatus(AppState stat, ValueType vt) { Message msg = new Message(); msg.what = stat.ordinal(); msg.obj = stat.name(); msg.arg1 = vt.ordinal(); mAppStat = stat; mHandler.sendMessage(msg); } /** * Get application status * @return Application state. */ private AppState getStatus() { return mAppStat; } }