package sample.ble.sensortag.ui; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ExpandableListView; import android.widget.TextView; import com.chimeraiot.android.ble.BleService; import com.chimeraiot.android.ble.BleServiceBindingActivity; import com.chimeraiot.android.ble.sensor.DeviceDef; import com.chimeraiot.android.ble.sensor.Sensor; import java.util.List; import sample.ble.sensortag.BleSensorService; import sample.ble.sensortag.R; import sample.ble.sensortag.config.AppConfig; import sample.ble.sensortag.fusion.SensorFusionActivity; import sample.ble.sensortag.info.InfoService; import sample.ble.sensortag.sensor.BaseSensor; import sample.ble.sensortag.sensor.ti.TiPeriodicalSensor; import sample.ble.sensortag.ui.adapters.BleServicesAdapter; /** * For a given BLE device, this Activity provides the user interface to connect, display data, * and display GATT services and characteristics supported by the device. The Activity * communicates with {@code BleService}, which in turn interacts with the * Bluetooth LE API. */ public class DeviceServicesActivity extends BleServiceBindingActivity implements ExpandableListView.OnChildClickListener, BleServicesAdapter.OnServiceItemClickListener { /** Log tag. */ @SuppressWarnings("UnusedDeclaration") private final static String TAG = DeviceServicesActivity.class.getSimpleName(); /** Data output field for active sensor. */ private TextView dataCharacteristic; /** Data output field for active sensor. */ private TextView dataValue; /** Services list. */ private ExpandableListView gattServicesList; /** Services adapter. */ private BleServicesAdapter gattServiceAdapter; /** Active sensor. */ private BaseSensor<?> activeSensor; @Override public Class<? extends BleService> getServiceClass() { return BleSensorService.class; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.device_services_activity); gattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list); gattServicesList.setOnChildClickListener(this); final View emptyView = findViewById(R.id.empty_view); gattServicesList.setEmptyView(emptyView); dataCharacteristic = (TextView) findViewById(R.id.data_characteristic_uuid); dataValue = (TextView) findViewById(R.id.data_characteristic_value); //noinspection ConstantConditions final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); final ActionBar actionBar = getSupportActionBar(); final String deviceName = getDeviceName(); if (TextUtils.isEmpty(deviceName)) { //noinspection ConstantConditions actionBar.setTitle(getDeviceAddress()); } else { //noinspection ConstantConditions actionBar.setTitle(deviceName); actionBar.setSubtitle(getDeviceAddress()); } actionBar.setDisplayHomeAsUpEnabled(true); } @Override public boolean onCreateOptionsMenu(Menu menu) { final String deviceName = getDeviceName(); if (deviceName != null) { getMenuInflater().inflate(R.menu.gatt_services, menu); // enable demo for SensorTag device only menu.findItem(R.id.menu_demo).setEnabled( AppConfig.SENSOR_FUSION_DEVICES.contains(deviceName)); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_demo: final Intent demoIntent = new Intent(); demoIntent.setClass(DeviceServicesActivity.this, SensorFusionActivity.class); demoIntent.putExtra(SensorFusionActivity.EXTRA_DEVICE_ADDRESS, getDeviceAddress()); startActivity(demoIntent); break; case android.R.id.home: onBackPressed(); return true; } return super.onOptionsItemSelected(item); } @Override public void onDisconnected(final String name, final String address) { super.onDisconnected(name, address); finish(); } @Override public void onServiceDiscovered(final String name, final String address) { super.onServiceDiscovered(name, address); displayGattServices(getBleManager().getSupportedGattServices(address)); } @Override public void onCharacteristicChanged(final String name, final String address, final String serviceUuid, final String characteristicUuid) { super.onCharacteristicChanged(name, address, serviceUuid, characteristicUuid); final Sensor<?> sensor = (Sensor<?>) getBleManager().getDeviceDefCollection() .get(name, address).getSensor(serviceUuid); if (sensor != null) { String uuid = sensor.getName(); if (TextUtils.isEmpty(uuid)) { uuid = characteristicUuid; } dataCharacteristic.setText(uuid); if (sensor instanceof BaseSensor) { final BaseSensor<?> tiSensor = (BaseSensor<?>) sensor; dataValue.setText(tiSensor.getDataString()); } else if (sensor instanceof InfoService) { final InfoService<?> infoSensor = (InfoService<?>) sensor; dataValue.setText(infoSensor.getValue()); } else { final Object data = sensor.getData(); dataValue.setText(String.valueOf(data)); } } } @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { if (gattServiceAdapter == null) { return false; } final BluetoothGattCharacteristic characteristic = gattServiceAdapter.getChild( groupPosition, childPosition); final DeviceDef def = getBleManager().getDeviceDefCollection().get( getDeviceName(), getDeviceAddress()); if (def == null) { return false; } final Sensor<?> sensor = (Sensor<?>) def.getSensor( characteristic.getService().getUuid().toString()); if (sensor == null) { return true; } if (sensor == activeSensor) { return true; } final String address = getDeviceAddress(); if (sensor instanceof BaseSensor) { final BaseSensor<?> baseSensor = (BaseSensor<?>) sensor; if (activeSensor != null) { activeSensor.setEnabled(false); getBleManager().update(address, activeSensor, activeSensor.getConfigUUID(), null); } activeSensor = baseSensor; baseSensor.setEnabled(true); getBleManager().update(address, sensor, baseSensor.getConfigUUID(), null); getBleManager().listen(address, sensor, baseSensor.getDataUUID()); } else { getBleManager().read(address, sensor, characteristic.getUuid().toString()); } return true; } @Override public void onServiceUpdated(BluetoothGattService service) { final BaseSensor<?> sensor = (BaseSensor<?>) getBleManager().getDeviceDefCollection() .get(getDeviceName(), getDeviceAddress()) .getSensor(service.getUuid().toString()); if (sensor != null && sensor instanceof TiPeriodicalSensor) { getBleManager().update(getDeviceAddress(), sensor, ((TiPeriodicalSensor) sensor).getPeriodUUID(), null); } } private void displayGattServices(List<BluetoothGattService> gattServices) { if (gattServices == null) { return; } final DeviceDef def = getBleManager().getDeviceDefCollection().get( getDeviceName(), getDeviceAddress()); gattServiceAdapter = new BleServicesAdapter(this, gattServices, def); gattServiceAdapter.setServiceListener(this); gattServicesList.setAdapter(gattServiceAdapter); } }