aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java')
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java224
1 files changed, 224 insertions, 0 deletions
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<SmDevice> 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<BtService<SmDevice>>) 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<SmDevice> 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<SmDevice> getDevices(Comparator<SmDevice> comparator) {
+ Set<SmDevice> devices = new TreeSet<>(comparator);
+ for (BtDevice<SmDevice> 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<SmDevice> 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;
+ }
+ }
+}