1. 选中扫描到的 Thingy 52 蓝牙设备;
文件: ScannerFragment.java
public Dialog onCreateDialog(final Bundle savedInstanceState) {
......
builder.setTitle(R.string.scanner_title);
final AlertDialog dialog = builder.setView(dialogView).create();
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
stopScan();
dismiss();
final ScannerFragmentListener listener = (ScannerFragmentListener) getActivity();
final ExtendedBluetoothDevice device = (ExtendedBluetoothDevice) mAdapter.getItem(position);
listener.onDeviceSelected(device.device, device.name != null ? device.name : getString(R.string.not_available));
}
});
......
}
2. 联结 Thingy 52 蓝牙设备
文件: InitialConfigurationActivity.java
public void onDeviceSelected(BluetoothDevice device, String name) {
if (mThingySdkManager != null) {
mThingySdkManager.connectToThingy(this, device, ThingyService.class);
}
mDevice = device;
animateStepOne();
showConnectionProgressDialog();
}
文件: ThingySdkManager.java
注: 对于 Thingy 52 的蓝牙操作, 手机 App 是以后台服务形式实现;
启动服务
public void connectToThingy(final Context context, final BluetoothDevice device, final Class<? extends BaseThingyService> service) {
final Intent intent = new Intent(context, service);
intent.putExtra(ThingyUtils.EXTRA_DEVICE, device);
context.startService(intent);
}
绑定服务
public void bindService(final Context context, final Class<? extends BaseThingyService> service) {
mServiceConnectionListener = (ServiceConnectionListener) context;
final Intent intent = new Intent(context, service);
context.startService(intent);
context.bindService(intent, mServiceConnection, 0);
}
服务定义
private BaseThingyService.BaseThingyBinder mBinder;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (BaseThingyService.BaseThingyBinder) service;
if (mBinder != null) {
mServiceConnectionListener.onServiceConnected();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(ThingyUtils.TAG, "unbound");
mBinder = null;
}
};
服务的 ThingyConnection
public ThingyConnection getThingyConnection(final BluetoothDevice device){
return mBinder.getThingyConnection(device);
}
3. 蓝牙 gatt.discoverServices()
文件: ThingyConnection.java (public class ThingyConnection extends BluetoothGattCallback {})
public final void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.v(TAG, "Error " + status + " : " + gatt.getDevice().getAddress());
isConnected = false;
mListener.onDeviceDisconnected(mBluetoothDevice, newState);
Intent intent = new Intent(ThingyUtils.ACTION_DEVICE_DISCONNECTED);
intent.putExtra(ThingyUtils.EXTRA_DATA, newState);
intent.putExtra(ThingyUtils.EXTRA_DEVICE, mBluetoothDevice);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
gatt.close();
return;
}
if (newState == BluetoothGatt.STATE_CONNECTED) {
isConnected = true;
Log.v(TAG, "Connected " + status);
Intent intent = new Intent(ThingyUtils.ACTION_DEVICE_CONNECTED);
intent.putExtra(ThingyUtils.EXTRA_DATA, newState);
intent.putExtra(ThingyUtils.EXTRA_DEVICE, mBluetoothDevice);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
mListener.onDeviceConnected(mBluetoothDevice, newState);
Log.v(TAG, "Starting service discovery");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
gatt.discoverServices();
}
}, 200);
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
isConnected = false;
Log.v(TAG, "Disconnected " + status);
mListener.onDeviceDisconnected(mBluetoothDevice, newState);
Intent intent = new Intent(ThingyUtils.ACTION_DEVICE_DISCONNECTED);
intent.putExtra(ThingyUtils.EXTRA_DATA, newState);
intent.putExtra(ThingyUtils.EXTRA_DEVICE, mBluetoothDevice);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
gatt.close();
}
}
4. 蓝牙 onServicesDiscovered()
文件: ThingyConnection.java
public final void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.v(TAG, "Service discovery error: " + status);
return;
}
Log.v(TAG, "Service discovery completed");
mThingyConfigurationService = gatt.getService(ThingyUtils.THINGY_CONFIGURATION_SERVICE);
if (mThingyConfigurationService != null) {
mDeviceNameCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.DEVICE_NAME_CHARACTERISTIC_UUID);
mAdvertisingParamCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.ADVERTISING_PARAM_CHARACTERISTIC_UUID);
mConnectionParamCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.CONNECTION_PARAM_CHARACTERISTIC_UUID);
mEddystoneUrlCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.EDDYSTONE_URL_CHARACTERISTIC_UUID);
mCloudTokenCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.CLOUD_TOKEN_CHARACTERISTIC_UUID);
mFirmwareVersionCharacteristic = mThingyConfigurationService.getCharacteristic(ThingyUtils.FIRMWARE_VERSION_CHARACERISTIC_UUID);
Log.v(TAG, "Reading thingy config chars");
}
final BluetoothGattService mBatteryService = gatt.getService(ThingyUtils.BATTERY_SERVICE);
if(mBatteryService != null) {
mBatteryLevelCharacteristic = mBatteryService.getCharacteristic(ThingyUtils.BATTERY_SERVICE_CHARACTERISTIC);
Log.v(TAG, "Reading battery characteristic");
}
final BluetoothGattService mEnvironmentService = gatt.getService(ThingyUtils.THINGY_ENVIRONMENTAL_SERVICE);
if (mEnvironmentService != null) {
mTemperatureCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.TEMPERATURE_CHARACTERISTIC);
mPressureCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.PRESSURE_CHARACTERISTIC);
mHumidityCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.HUMIDITY_CHARACTERISTIC);
mAirQualityCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.AIR_QUALITY_CHARACTERISTIC);
mColorCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.COLOR_CHARACTERISTIC);
mEnvironmentConfigurationCharacteristic = mEnvironmentService.getCharacteristic(ThingyUtils.CONFIGURATION_CHARACTERISTIC);
Log.v(TAG, "Reading environment config chars");
}
final BluetoothGattService mUiService = gatt.getService(ThingyUtils.THINGY_UI_SERVICE);
if (mUiService != null) {
mLedCharacteristic = mUiService.getCharacteristic(ThingyUtils.LED_CHARACTERISTIC);
mButtonCharacteristic = mUiService.getCharacteristic(ThingyUtils.BUTTON_CHARACTERISTIC);
}
final BluetoothGattService mMotionService = gatt.getService(ThingyUtils.THINGY_MOTION_SERVICE);
if (mMotionService != null) {
mMotionConfigurationCharacteristic = mMotionService.getCharacteristic(ThingyUtils.THINGY_MOTION_CONFIGURATION_CHARACTERISTIC);
mTapCharacteristic = mMotionService.getCharacteristic(ThingyUtils.TAP_CHARACTERISTIC);
mOrientationCharacteristic = mMotionService.getCharacteristic(ThingyUtils.ORIENTATION_CHARACTERISTIC);
mQuaternionCharacteristic = mMotionService.getCharacteristic(ThingyUtils.QUATERNION_CHARACTERISTIC);
mPedometerCharacteristic = mMotionService.getCharacteristic(ThingyUtils.PEDOMETER_CHARACTERISTIC);
mRawDataCharacteristic = mMotionService.getCharacteristic(ThingyUtils.RAW_DATA_CHARACTERISTIC);
mEulerCharacteristic = mMotionService.getCharacteristic(ThingyUtils.EULER_CHARACTERISTIC);
mRotationMatrixCharacteristic = mMotionService.getCharacteristic(ThingyUtils.ROTATION_MATRIX_CHARACTERISTIC);
mHeadingCharacteristic = mMotionService.getCharacteristic(ThingyUtils.HEADING_CHARACTERISTIC);
mGravityVectorCharacteristic = mMotionService.getCharacteristic(ThingyUtils.GRAVITY_VECTOR_CHARACTERISTIC);
Log.v(TAG, "Reading motion config chars");
}
final BluetoothGattService mSoundService = gatt.getService(ThingyUtils.THINGY_SOUND_SERVICE);
if (mSoundService != null) {
mSoundConfigurationCharacteristic = mSoundService.getCharacteristic(ThingyUtils.THINGY_SOUND_CONFIG_CHARACTERISTIC);
mSpeakerDataCharacteristic = mSoundService.getCharacteristic(ThingyUtils.THINGY_SPEAKER_DATA_CHARACTERISTIC);
mSpeakerStatusCharacteristic = mSoundService.getCharacteristic(ThingyUtils.THINGY_SPEAKER_STATUS_CHARACTERISTIC);
mMicrophoneCharacteristic = mSoundService.getCharacteristic(ThingyUtils.THINGY_MICROPHONE_CHARACTERISTIC);
}
mButtonLessDfuService = gatt.getService(ThingyUtils.SECURE_DFU_SERVICE);
if (mButtonLessDfuService != null) {
mDfuControlPointCharacteristic = mButtonLessDfuService.getCharacteristic(ThingyUtils.DFU_DEFAULT_CONTROL_POINT_CHARACTERISTIC);
}
readThingyCharacteristics();
}
5. 读取服务数据
文件: ThingyConnection.java
private final void readThingyCharacteristics() {
if (mThingyConfigurationService != null) {
if (mDeviceNameCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mDeviceNameCharacteristic);
}
if (mAdvertisingParamCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mAdvertisingParamCharacteristic);
}
if (mConnectionParamCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mConnectionParamCharacteristic);
}
if (mEddystoneUrlCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mEddystoneUrlCharacteristic);
}
if (mCloudTokenCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mCloudTokenCharacteristic);
}
if (mFirmwareVersionCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mFirmwareVersionCharacteristic);
}
}
if(mBatteryLevelCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mBatteryLevelCharacteristic);
add(RequestType.READ_DESCRIPTOR, mBatteryLevelCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
}
if (mEnvironmentConfigurationCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mEnvironmentConfigurationCharacteristic);
}
add(RequestType.READ_DESCRIPTOR, mTemperatureCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mPressureCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mHumidityCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mAirQualityCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mColorCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
if (mLedCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mLedCharacteristic);
}
if (mButtonCharacteristic != null) {
add(RequestType.READ_DESCRIPTOR, mButtonCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
}
if (mMotionConfigurationCharacteristic != null) {
add(RequestType.READ_CHARACTERISTIC, mMotionConfigurationCharacteristic);
}
add(RequestType.READ_DESCRIPTOR, mTapCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mOrientationCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mQuaternionCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mPedometerCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mRawDataCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mEulerCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mRotationMatrixCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mHeadingCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_DESCRIPTOR, mGravityVectorCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
add(RequestType.READ_CHARACTERISTIC, mSoundConfigurationCharacteristic);
add(RequestType.READ_DESCRIPTOR, mSpeakerStatusCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
if (mMicrophoneCharacteristic != null) {
add(RequestType.READ_DESCRIPTOR, mMicrophoneCharacteristic.getDescriptor(ThingyUtils.CLIENT_CHARACTERISTIC_CONFIGURATOIN_DESCRIPTOR));
}
}