diff options
Diffstat (limited to 'app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java')
-rw-r--r-- | app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java | 218 |
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; + } + } +} |