From da80f3d219c0c05568db0cb9a8910f02cc281d47 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 2 Jan 2015 21:38:52 +0100 Subject: o Getting closer to something that actually work. --- .../soilmoisture/DefaultSmDevicesManager.java | 224 +++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java (limited to 'app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java') diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java new file mode 100644 index 0000000..301bfc7 --- /dev/null +++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java @@ -0,0 +1,224 @@ +package io.trygvis.soilmoisture; + +import android.app.Service; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattService; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import io.trygvis.android.LocalBinder; +import io.trygvis.android.bt.BtActionExecutor; +import io.trygvis.android.bt.BtDevice; +import io.trygvis.android.bt.BtService; +import io.trygvis.android.bt.DefaultBtService; +import io.trygvis.bluetooth.TrygvisIoUuids; + +import static io.trygvis.android.bt.BtService.BtServiceListenerBroadcastReceiver; + +public class DefaultSmDevicesManager extends Service implements SmDevicesManager { + private final static String TAG = DefaultSmDevicesManager.class.getSimpleName(); + + private final IBinder binder = new LocalBinder<>(this); + + @SuppressWarnings("UnusedDeclaration") + private final DefaultSmDevicesManager context = DefaultSmDevicesManager.this; + + private ServiceConnection serviceConnection; + + private BtService btService; + + + @Override + public IBinder onBind(Intent intent) { + return binder; + } + + @Override + public void onCreate() { + Log.i(TAG, "onCreate"); + + serviceConnection = new ServiceConnection() { + @SuppressWarnings("unchecked") + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + btService = ((LocalBinder>) service).getService(); + boolean ok = btService.initialize(DefaultSmDevicesManager.this::onNewDevice); + + sendBroadcast(createReady(ok)); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + btService = null; + } + }; + + bindService(new Intent(this, DefaultBtService.class), serviceConnection, BIND_AUTO_CREATE); + registerReceiver(btServiceListener, BtServiceListenerBroadcastReceiver.INTENT_FILTER); + } + + @Override + public void onDestroy() { + unregisterReceiver(btServiceListener); + Log.i(TAG, "onDestroy" + btService); + if (serviceConnection != null) { + unbindService(serviceConnection); + } + } + + private final BtServiceListenerBroadcastReceiver btServiceListener = new BtServiceListenerBroadcastReceiver() { + @Override + public void onScanStarted() { + sendBroadcast(createScanStarted()); + } + + @Override + public void onScanStopped() { + sendBroadcast(createScanStopped()); + } + + @Override + public void onNewDevice(String address) { + BtDevice btDevice = btService.getDevice(address); + SmDevice smDevice = btDevice.getTag(); + + if (!smDevice.isProbed()) { + Log.i(TAG, "Probing " + address + ", name=" + btDevice.getName()); + BtActionExecutor executor = new BtActionExecutor(). + onConnectionStateChange((gatt, newState) -> { + //noinspection SimplifiableIfStatement + if (newState == BluetoothGatt.STATE_CONNECTED) { + Log.i(TAG, "Connected to " + address + ", getting services"); + return gatt.discoverServices(); + } + + Log.i(TAG, "Could not connect to to " + address); + smDevice.setIsUseful(false); + return false; + }). + onServicesDiscovered(gatt -> { + Log.i(TAG, "Services discovered"); + + BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE); + + if (service == null) { + smDevice.setIsUseful(false); + return false; + } + + BluetoothGattCharacteristic characteristic = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE); + + if (characteristic == null) { + smDevice.setIsUseful(false); + return false; + } + + smDevice.setIsUseful(true); + sendBroadcast(createNewDevice(address)); + + gatt.disconnect(); + + return true; + }); + + btDevice.connect(executor); + } else { + sendBroadcast(createNewDevice(address)); + } + } + }; + + // ----------------------------------------------------------------------- + // SmDevicesManager Implementation + // ----------------------------------------------------------------------- + + @Override + public List getDevices(Comparator comparator) { + Set devices = new TreeSet<>(comparator); + for (BtDevice btDevice : btService.getDevices()) { + devices.add(btDevice.getTag()); + } + return new ArrayList<>(devices); + } + + @Override + public SmDevice getDevice(String address) { + return btService.getTag(address); + } + + @Override + public boolean isScanning() { + return btService.isScanning(); + } + + @Override + public boolean startScanning(long scanPeriod) { + return btService.startScanning(scanPeriod); + } + + @Override + public void stopScanning() { + btService.stopScanning(); + } + + // ----------------------------------------------------------------------- + // + // ----------------------------------------------------------------------- + + private SmDevice onNewDevice(BtDevice btDevice) { + return new SmDevice(btDevice); + } + + private Intent createReady(boolean success) { + return new Intent(SmDeviceListener.INTENT_NAME). + putExtra("event", "ready"). + putExtra("success", success); + } + + private Intent createScanStarted() { + return new Intent(SmDeviceListener.INTENT_NAME). + putExtra("event", "scanStarted"); + } + + private Intent createScanStopped() { + return new Intent(SmDeviceListener.INTENT_NAME). + putExtra("event", "scanStopped"); + } + + private Intent createNewDevice(String address) { + return new Intent(SmDeviceListener.INTENT_NAME). + putExtra("event", "newDevice"). + putExtra("address", address); + } + + public static void dispatchEvent(Intent intent, SmDeviceListener listener) { + String event = intent.getStringExtra("event"); + Log.i(TAG, "Dispatching event " + intent.getAction() + "/" + event); + switch (event) { + case "ready": + listener.onReady(intent.getBooleanExtra("success", false)); + break; + case "newDevice": + listener.onNewDevice(intent.getStringExtra("address")); + break; + case "scanStarted": + listener.onScanStarted(); + break; + case "scanStopped": + listener.onScanStopped(); + break; + default: + break; + } + } +} -- cgit v1.2.3