aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java')
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java218
1 files changed, 218 insertions, 0 deletions
diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
new file mode 100644
index 0000000..8a36476
--- /dev/null
+++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
@@ -0,0 +1,218 @@
+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 DefaultSoilMoistureService extends Service implements SoilMoistureService {
+ private final static String TAG = DefaultSoilMoistureService.class.getSimpleName();
+
+ private final IBinder binder = new LocalBinder<>(this);
+
+ @SuppressWarnings("UnusedDeclaration")
+ private final DefaultSoilMoistureService context = DefaultSoilMoistureService.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(DefaultSoilMoistureService.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);
+
+ boolean useful = false;
+ if (service != null) {
+ BluetoothGattCharacteristic characteristic = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE);
+
+ useful = characteristic != null;
+
+ smDevice.setIsUseful(useful);
+ }
+
+ gatt.disconnect();
+
+ return false;
+ }).
+ onFinally(() -> sendBroadcast(createNewDevice(address)));
+
+ 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();
+ }
+
+ // -----------------------------------------------------------------------
+ // Event creation and dispatching
+ // -----------------------------------------------------------------------
+
+ private SmDevice onNewDevice(BtDevice<SmDevice> btDevice) {
+ return new SmDevice(btDevice);
+ }
+
+ private Intent createReady(boolean success) {
+ return new Intent(SoilMoistureListener.INTENT_NAME).
+ putExtra("event", "ready").
+ putExtra("success", success);
+ }
+
+ private Intent createScanStarted() {
+ return new Intent(SoilMoistureListener.INTENT_NAME).
+ putExtra("event", "scanStarted");
+ }
+
+ private Intent createScanStopped() {
+ return new Intent(SoilMoistureListener.INTENT_NAME).
+ putExtra("event", "scanStopped");
+ }
+
+ private Intent createNewDevice(String address) {
+ return new Intent(SoilMoistureListener.INTENT_NAME).
+ putExtra("event", "newDevice").
+ putExtra("address", address);
+ }
+
+ public static void dispatchEvent(Intent intent, SoilMoistureListener 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;
+ }
+ }
+}