From bc09707edf110da018a68be4d16bdfcee8af600f Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 17 Jan 2015 18:15:52 +0100 Subject: o Not disconnecting when the promise is done. o All user code can assume that they're already connected to the device, simplifying the life cycle. o When starting, send a 'new device' even for all stored devices. --- .../soilmoisture/DefaultSoilMoistureService.java | 137 ++++++++++++--------- .../java/io/trygvis/soilmoisture/MainActivity.java | 106 ++++++++++++++-- .../java/io/trygvis/soilmoisture/SmDevice.java | 2 +- .../trygvis/soilmoisture/SoilMoistureService.java | 2 + 4 files changed, 176 insertions(+), 71 deletions(-) (limited to 'app/src/main/java/io/trygvis/soilmoisture') diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java index 174c245..56f38f4 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java +++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java @@ -112,64 +112,90 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS sendBroadcast(createNewDevice(address)); + boolean candidate = btDevice.getAddress().startsWith("FB:"); + + if (!candidate) { + Log.w(TAG, "Skipping device: " + btDevice.getAddress()); + markDeviceAsNotUseful(smDevice); + return; + } + if (!smDevice.isProbed()) { - Log.i(TAG, "Probing " + address + ", name=" + btDevice.getName()); - BtPromise executor = new BtPromise(). - onDirect(v -> { - BluetoothGatt gatt = (BluetoothGatt) v; - return gatt.discoverServices() ? waitForNextEvent() : stop(); - }). - onServicesDiscovered(gatt -> { - Log.i(TAG, "Services discovered"); - - BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE); - - if (service == null) { - return stop(); - } - - BluetoothGattCharacteristic soilMoisture = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE); - - if (soilMoisture == null) { - return stop(); - } - - BluetoothGattDescriptor ccg = soilMoisture.getDescriptor(TrygvisIoUuids.CLIENT_CHARACTERISTIC_CONFIG); - ccg.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - gatt.setCharacteristicNotification(soilMoisture, true); - - return gatt.writeDescriptor(ccg) ? waitForNextEvent() : stop(); - }). - onDescriptorWrite((gatt, descriptor) -> { - Log.i(TAG, "Notifications enabled, getting sensor count"); - BluetoothGattCharacteristic c = descriptor.getCharacteristic(); - c.setValue(createGetSensorCountReq()); - return gatt.writeCharacteristic(c) ? waitForNextEvent() : stop(); - }). - onCharacteristicWrite((gatt, characteristic) -> waitForNextEvent()). - onCharacteristicChanged((gatt, characteristic) -> { - GetSensorCountRes getSensorCountRes = parseResponse(characteristic.getValue(), - GET_SENSOR_COUNT, GetSensorCountRes.class); - - Log.i(TAG, "The device has " + getSensorCountRes.count + " sensors."); - - markDeviceAsUseful(smDevice, getSensorCountRes.count); - - return stop(); - }). - onFinally(() -> { -// btDevice.disconnect(); - - if (smDevice.getIsUseful() == null) { - smDevice.setIsUseful(false); - } - }); - - btDevice.withConnection(executor); + probe(smDevice.getBtDevice().getAddress()); } } }; + public void probe(String address) { + BtDevice btDevice = btService.getDevice(address); + SmDevice smDevice = btDevice.getTag(); + + Log.i(TAG, "Probing " + address + ", name=" + btDevice.getName()); + BtPromise executor = new BtPromise(). + onDirect(v -> { + Log.i(TAG, "Discovering services"); + BluetoothGatt gatt = (BluetoothGatt) v; + return gatt.discoverServices() ? waitForNextEvent() : stop(); + }). + onServicesDiscovered(gatt -> { + Log.i(TAG, "Services discovered"); + + BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE); + + if (service == null) { + return stop(); + } + + BluetoothGattCharacteristic soilMoisture = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE); + + if (soilMoisture == null) { + return stop(); + } + + BluetoothGattDescriptor ccg = soilMoisture.getDescriptor(TrygvisIoUuids.CLIENT_CHARACTERISTIC_CONFIG); + ccg.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); + gatt.setCharacteristicNotification(soilMoisture, true); + + return gatt.writeDescriptor(ccg) ? waitForNextEvent() : stop(); + }). + onDescriptorWrite((gatt, descriptor) -> { + Log.i(TAG, "Notifications enabled, getting sensor count"); + BluetoothGattCharacteristic c = descriptor.getCharacteristic(); + c.setValue(createGetSensorCountReq()); + return gatt.writeCharacteristic(c) ? waitForNextEvent() : stop(); + }). + onCharacteristicWrite((gatt, characteristic) -> waitForNextEvent()). + onCharacteristicChanged((gatt, characteristic) -> { + GetSensorCountRes getSensorCountRes = parseResponse(characteristic.getValue(), + GET_SENSOR_COUNT, GetSensorCountRes.class); + + Log.i(TAG, "The device has " + getSensorCountRes.count + " sensors."); + + markDeviceAsUseful(smDevice, getSensorCountRes.count); + + return stop(); + }). + onFinally(() -> { + if (smDevice.getIsUseful() == null) { + smDevice.setIsUseful(false); + } + }); + + btDevice.withConnection(executor); + } + + private void markDeviceAsNotUseful(SmDevice device) { + btService.runTx(db -> { + device.setIsUseful(false); + + ContentValues values = new ContentValues(); + values.put(Tables.C_USEFUL, false); + db.update(Tables.T_SM_DEVICE, values, "id=?", new String[]{valueOf(device.id)}); + + return null; + }); + } + private void markDeviceAsUseful(SmDevice device, int sensorCount) { btService.runTx(db -> { device.setIsUseful(true); @@ -274,9 +300,6 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS BtPromise promise = new BtPromise(). onDirect(v -> { BluetoothGatt gatt = (BluetoothGatt) v; - return gatt.discoverServices() ? waitForNextEvent() : stop(); - }). - onServicesDiscovered(gatt -> { BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE); BluetoothGattCharacteristic soilMoisture = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE); @@ -298,8 +321,6 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS handleNewSensorValueReady(sensor, getSensorCountRes.value); -// gatt.disconnect(); - return stop(); }). onFinally(() -> { diff --git a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java index 3a88f6c..385a566 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java +++ b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java @@ -1,6 +1,10 @@ package io.trygvis.soilmoisture; import android.app.ActionBar; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.ComponentName; @@ -29,6 +33,7 @@ import java.util.List; import io.fabric.sdk.android.Fabric; import io.trygvis.android.LocalBinder; import io.trygvis.android.bt.BtActivitySupport; +import io.trygvis.android.bt.BtDevice; import static io.trygvis.soilmoisture.ExceptionHandler.EXCEPTION_HANDLER; import static io.trygvis.soilmoisture.SoilMoistureService.SoilMoistureListener; @@ -211,8 +216,52 @@ public class MainActivity extends ListActivity { // // ----------------------------------------------------------------------- - private void onDeviceClick(SmDevice device) { - Log.i(TAG, "onDeviceClick, device=" + device.getBtDevice().getId()); + public static class BtDeviceDialogFragment extends DialogFragment { + + private MainActivity mainActivity; +// private final BtDevice device; +// +// public BtDeviceDialogFragment(MainActivity mainActivity, BtDevice device) { +// this.mainActivity = mainActivity; +// this.device = device; +// } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + String address = getArguments().getString("address"); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.dialog_probe_device). + setPositiveButton(R.string.yes, (dialog, id) -> mainActivity.probe(address)); + return builder.create(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + mainActivity = (MainActivity) activity; + } + } + + private void probe(String address) { + soilMoistureService.probe(address); + } + + private boolean onBtDeviceLongClick(BtDevice device) { + Log.i(TAG, "onBtDeviceClick, device=" + device.getId()); + + BtDeviceDialogFragment dialog = new BtDeviceDialogFragment(); + Bundle arguments = new Bundle(); + arguments.putString("address", device.getAddress()); + dialog.setArguments(arguments); + dialog.show(getFragmentManager(), "BtDeviceDialogFragment"); + + return true; + } + + private void onSmDeviceClick(SmDevice device) { + Log.i(TAG, "onSmDeviceClick, device=" + device.getBtDevice().getId()); } private void onSensorClick(SmSensor sensor) { @@ -266,9 +315,13 @@ public class MainActivity extends ListActivity { current = new ArrayList<>(); List usefulDevices = new ArrayList<>(devices.size()); - List unusefulDevices = new ArrayList<>(devices.size()); + List unusefulDevices = new ArrayList<>(devices.size()); for (SmDevice d : devices) { - (d.isUseful() ? usefulDevices : unusefulDevices).add(d); + if (d.isUseful()) { + usefulDevices.add(d); + } else { + unusefulDevices.add(d.getBtDevice()); + } } List sensors = new ArrayList<>(); for (SmDevice d : devices) { @@ -355,10 +408,12 @@ public class MainActivity extends ListActivity { public int getItemViewType(int position) { Object o = current.get(position); - if (o instanceof SmDevice) { + if (o instanceof BtDevice) { return 0; - } else if (o instanceof SmSensor) { + } else if (o instanceof SmDevice) { return 1; + } else if (o instanceof SmSensor) { + return 2; } throw new RuntimeException("Unknown kind: " + o.getClass()); @@ -366,7 +421,7 @@ public class MainActivity extends ListActivity { @Override public int getViewTypeCount() { - return 2; + return 3; } @Override @@ -393,7 +448,10 @@ public class MainActivity extends ListActivity { public View getView(int position, View view, ViewGroup viewGroup) { Object o = current.get(position); - if (o instanceof SmDevice) { + if (o instanceof BtDevice) { + //noinspection unchecked + return getBtDeviceView((BtDevice) o, view); + } else if (o instanceof SmDevice) { return getSmDeviceView((SmDevice) o, view); } else if (o instanceof SmSensor) { return getSoilSensorView((SmSensor) o, view); @@ -402,12 +460,38 @@ public class MainActivity extends ListActivity { throw new RuntimeException("Not implemented"); } + private View getBtDeviceView(BtDevice device, View view) { + if (view == null) { + view = inflater.inflate(R.layout.fragment_device, null); + view.setTag(new DeviceItem(view)); + view.setClickable(false); + view.setLongClickable(true); + view.setOnLongClickListener(v -> MainActivity.this.onBtDeviceLongClick(device)); + } + + DeviceItem item = (DeviceItem) view.getTag(); + + if (device.getName() != null) { + item.deviceName.setText(device.getName()); + } else { + item.deviceName.setText(R.string.unknown_device); + } + String address = device.getAddress() + ", not useful"; + + item.deviceAddress.setText(address); + + item.rssi.setText(getText(R.string.rssi) + ": " + + (device.getRssi() != null ? valueOf(device.getRssi()) : getText(R.string.unknown))); + + return view; + } + private View getSmDeviceView(SmDevice smDevice, View view) { if (view == null) { view = inflater.inflate(R.layout.fragment_device, null); view.setTag(new DeviceItem(view)); view.setClickable(true); - view.setOnClickListener(v -> onDeviceClick(smDevice)); + view.setOnClickListener(v -> onSmDeviceClick(smDevice)); } DeviceItem item = (DeviceItem) view.getTag(); @@ -430,7 +514,7 @@ public class MainActivity extends ListActivity { item.deviceAddress.setText(address); item.rssi.setText(getText(R.string.rssi) + ": " + - (smDevice.getBtDevice().getRssi() != 0 ? valueOf(smDevice.getBtDevice().getRssi()) : getText(R.string.unknown))); + (smDevice.getBtDevice().getRssi() != null ? valueOf(smDevice.getBtDevice().getRssi()) : getText(R.string.unknown))); boolean useful = smDevice.isUseful(); @@ -440,8 +524,6 @@ public class MainActivity extends ListActivity { item.info.setText(""); } -// view.setClickable(useful); - return view; } diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java index 4cb25f3..5d439bc 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java +++ b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java @@ -15,7 +15,7 @@ import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_WARNING_VALUE; import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.SET_SENSOR_NAME; import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.SET_WARNING_VALUE; -class SmDevice implements BtDevice.BtDeviceWrapper { +class SmDevice { private final static String TAG = SmDevice.class.getSimpleName(); final DefaultSoilMoistureService smService; diff --git a/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java index 643fa08..a287c7b 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java +++ b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java @@ -13,6 +13,8 @@ public interface SoilMoistureService { SmDevice getDevice(String address); + void probe(String address); + boolean isScanning(); boolean startScanning(long scanPeriod); -- cgit v1.2.3