From 1b9a4defe73f3aa8c10aa4af49002f0cebd1c292 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 4 Jan 2015 11:12:12 +0100 Subject: o Adding SoilMonitors support in core and view. Still more to do. --- app/src/main/AndroidManifest.xml | 2 +- .../io/trygvis/android/bt/DefaultBtService.java | 4 + .../soilmoisture/DefaultSmDevicesManager.java | 224 -------------------- .../soilmoisture/DefaultSoilMoistureService.java | 218 +++++++++++++++++++ .../java/io/trygvis/soilmoisture/MainActivity.java | 234 +++++++++++++++++---- .../java/io/trygvis/soilmoisture/SmDevice.java | 11 +- .../io/trygvis/soilmoisture/SmDevicesManager.java | 50 ----- .../trygvis/soilmoisture/SoilMoistureService.java | 48 +++++ .../java/io/trygvis/soilmoisture/SoilMonitor.java | 35 +++ app/src/main/res/layout/main.xml | 15 ++ app/src/main/res/menu/gatt_services.xml | 29 --- app/src/main/res/menu/main.xml | 37 ++-- app/src/main/res/menu/menu_main.xml | 5 - app/src/main/res/values/strings.xml | 2 + 14 files changed, 542 insertions(+), 372 deletions(-) delete mode 100644 app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java create mode 100644 app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java delete mode 100644 app/src/main/java/io/trygvis/soilmoisture/SmDevicesManager.java create mode 100644 app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java create mode 100644 app/src/main/java/io/trygvis/soilmoisture/SoilMonitor.java create mode 100644 app/src/main/res/layout/main.xml delete mode 100644 app/src/main/res/menu/gatt_services.xml delete mode 100644 app/src/main/res/menu/menu_main.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 91cd1b2..500bd8d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,7 +47,7 @@ diff --git a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java index 5e13a1f..3c14c1f 100644 --- a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java +++ b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java @@ -179,6 +179,10 @@ public class DefaultBtService> extends Ser return binder; } + /** + * TODO: move this to initialize or somewhere it can be called so it doesn't block the UI + * thread. + */ @Override public void onCreate() { Bundle data; diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java deleted file mode 100644 index 301bfc7..0000000 --- a/app/src/main/java/io/trygvis/soilmoisture/DefaultSmDevicesManager.java +++ /dev/null @@ -1,224 +0,0 @@ -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; - } - } -} 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 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(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 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 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(); + } + + // ----------------------------------------------------------------------- + // Event creation and dispatching + // ----------------------------------------------------------------------- + + private SmDevice onNewDevice(BtDevice 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; + } + } +} diff --git a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java index 6adc96c..64e8202 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java +++ b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java @@ -6,6 +6,8 @@ import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; +import android.database.DataSetObservable; +import android.database.DataSetObserver; import android.os.Bundle; import android.os.IBinder; import android.util.Log; @@ -14,8 +16,8 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.BaseAdapter; import android.widget.Button; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; @@ -31,7 +33,7 @@ import io.trygvis.android.LocalBinder; import io.trygvis.android.bt.BtActivitySupport; import static io.trygvis.soilmoisture.ExceptionHandler.EXCEPTION_HANDLER; -import static io.trygvis.soilmoisture.SmDevicesManager.SmDeviceListener; +import static io.trygvis.soilmoisture.SoilMoistureService.SoilMoistureListener; import static java.lang.String.valueOf; public class MainActivity extends ListActivity { @@ -42,12 +44,12 @@ public class MainActivity extends ListActivity { private static final int REQUEST_ENABLE_BT = 1; private final BtActivitySupport btActivitySupport = new BtActivitySupport(this, REQUEST_ENABLE_BT); - private final SmDeviceListener serviceListener = new MySmDeviceListener(); + private final SoilMoistureListener serviceListener = new MySoilMoistureListener(); private final MainActivity context = this; private DeviceListAdapter deviceList; private ServiceConnection serviceConnection; - private SmDevicesManager smDevicesManager; + private SoilMoistureService soilMoistureService; private ProgressDialog initializing; private boolean ready; @@ -73,22 +75,24 @@ public class MainActivity extends ListActivity { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { Log.i(TAG, "onServiceConnected"); - smDevicesManager = ((LocalBinder) service).getService(); - registerReceiver(serviceListener, SmDeviceListener.INTENT_FILTER); + soilMoistureService = ((LocalBinder) service).getService(); + registerReceiver(serviceListener, SoilMoistureListener.INTENT_FILTER); } @Override public void onServiceDisconnected(ComponentName componentName) { Log.i(TAG, "onServiceDisconnected"); - smDevicesManager = null; + soilMoistureService = null; stopScan(); } }; - bindService(new Intent(this, DefaultSmDevicesManager.class), serviceConnection, BIND_AUTO_CREATE); + bindService(new Intent(this, DefaultSoilMoistureService.class), serviceConnection, BIND_AUTO_CREATE); initializing = ProgressDialog. show(this, "Initializing", "Connecting to Bluetooth system.", true); + + setContentView(R.layout.main); } @Override @@ -112,7 +116,7 @@ public class MainActivity extends ListActivity { return; } - registerReceiver(serviceListener, SmDeviceListener.INTENT_FILTER); + registerReceiver(serviceListener, SoilMoistureListener.INTENT_FILTER); } @Override @@ -141,20 +145,30 @@ public class MainActivity extends ListActivity { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); + MenuItem stop = menu.findItem(R.id.menu_stop); + MenuItem scan = menu.findItem(R.id.menu_scan); + MenuItem refresh = menu.findItem(R.id.menu_refresh); + MenuItem showAll = menu.findItem(R.id.menu_show_all); + MenuItem groupByDevice = menu.findItem(R.id.menu_group_by_device); + if (ready) { - if (!smDevicesManager.isScanning()) { - menu.findItem(R.id.menu_stop).setVisible(false); - menu.findItem(R.id.menu_scan).setVisible(true); - menu.findItem(R.id.menu_refresh).setActionView(null); + if (!soilMoistureService.isScanning()) { + stop.setVisible(false); + scan.setVisible(true); + refresh.setActionView(null); } else { - menu.findItem(R.id.menu_stop).setVisible(true); - menu.findItem(R.id.menu_scan).setVisible(false); - menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_indeterminate_progress); + stop.setVisible(true); + scan.setVisible(false); + refresh.setActionView(R.layout.actionbar_indeterminate_progress); } + showAll.setChecked(deviceList.isShowAll()); + groupByDevice.setChecked(deviceList.isGroupByDevice()); } else { - menu.findItem(R.id.menu_stop).setVisible(false); - menu.findItem(R.id.menu_scan).setVisible(true); - menu.findItem(R.id.menu_refresh).setActionView(null); + stop.setVisible(false); + scan.setVisible(true); + refresh.setActionView(null); + showAll.setVisible(false); + groupByDevice.setVisible(false); } return true; } @@ -163,6 +177,7 @@ public class MainActivity extends ListActivity { public boolean onOptionsItemSelected(MenuItem item) { Log.i(TAG, "onOptionsItemSelected"); + boolean consumed = true; switch (item.getItemId()) { case R.id.menu_scan: startScan(); @@ -170,39 +185,47 @@ public class MainActivity extends ListActivity { case R.id.menu_stop: stopScan(); break; + case R.id.menu_show_all: + item.setChecked(!item.isChecked()); + deviceList.setShowAll(item.isChecked()); + break; + case R.id.menu_group_by_device: + item.setChecked(!item.isChecked()); + deviceList.setGroupByDevice(item.isChecked()); + break; + default: + consumed = super.onOptionsItemSelected(item); } - return super.onOptionsItemSelected(item); + return consumed; } private void startScan() { - smDevicesManager.startScanning(SCAN_PERIOD); + soilMoistureService.startScanning(SCAN_PERIOD); } private void stopScan() { - if (smDevicesManager != null) { - smDevicesManager.stopScanning(); + if (soilMoistureService != null) { + soilMoistureService.stopScanning(); } } @Override protected void onListItemClick(ListView l, View v, int position, long id) { stopScan(); - -// SmDevice state = smDevicesManager.getDevices(SmDevice.deviceComparator).get(position); } // ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- - static class DeviceListItem { + static class DeviceItem { final TextView deviceName; final TextView deviceAddress; final TextView rssi; final ProgressBar spinner; final Button connect; - DeviceListItem(View view) { + DeviceItem(View view) { this.deviceName = (TextView) view.findViewById(R.id.device_name); this.deviceAddress = (TextView) view.findViewById(R.id.device_address); this.rssi = (TextView) view.findViewById(R.id.device_rssi); @@ -211,39 +234,162 @@ public class MainActivity extends ListActivity { } } - private class DeviceListAdapter extends BaseAdapter { + private class DeviceListAdapter implements ListAdapter { + private final DataSetObservable dataSetObservable = new DataSetObservable(); private List devices = new ArrayList<>(); + private List current = new ArrayList<>(); private LayoutInflater inflater = MainActivity.this.getLayoutInflater(); + private boolean groupByDevice = true; + private boolean showAll = false; + + public void sort() { + Log.i(TAG, "sort(), groupByDevice=" + groupByDevice + ", showAll=" + showAll); + current = new ArrayList<>(); + + List usefulDevices = new ArrayList<>(devices.size()); + List unusefulDevices = new ArrayList<>(devices.size()); + for (SmDevice d : devices) { + (d.isUseful() ? usefulDevices : unusefulDevices).add(d); + } + List monitors = new ArrayList<>(); + for (SmDevice d : devices) { + monitors.addAll(d.getMonitors()); + } + + if (groupByDevice) { + current.addAll(usefulDevices); + if (showAll) { + current.addAll(unusefulDevices); + } + } else { + current.addAll(monitors); + } + dataSetObservable.notifyChanged(); + } + + public void notifyDataSetChanged() { + dataSetObservable.notifyChanged(); + } + + public void setShowAll(boolean showAll) { + if (showAll == this.showAll) { + return; + } + + this.showAll = showAll; + sort(); + } + + public boolean isShowAll() { + return showAll; + } + + public void setGroupByDevice(boolean groupByDevice) { + if (groupByDevice == this.groupByDevice) { + return; + } + + this.groupByDevice = groupByDevice; + sort(); + } + + public boolean isGroupByDevice() { + return groupByDevice; + } + + // ----------------------------------------------------------------------- + // ListAdapter Implementation + // ----------------------------------------------------------------------- + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + dataSetObservable.registerObserver(observer); + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + dataSetObservable.unregisterObserver(observer); + } + + @Override + public boolean areAllItemsEnabled() { + return true; + } + + @Override + public boolean isEnabled(int position) { + return true; + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public int getItemViewType(int position) { + Object o = current.get(position); + + if (o instanceof SmDevice) { + return 0; + } else if (o instanceof SoilMonitor) { + return 1; + } + + throw new RuntimeException("Unknown kind: " + o.getClass()); + } + + @Override + public int getViewTypeCount() { + return 2; + } + + @Override + public boolean isEmpty() { + return current.isEmpty(); + } + @Override public int getCount() { - return devices.size(); + return current.size(); } @Override - public SmDevice getItem(int i) { - return devices.get(i); + public Object getItem(int position) { + return current.get(position); } @Override - public long getItemId(int i) { - return i; + public long getItemId(int position) { + return position; } @Override - public View getView(int i, View view, ViewGroup viewGroup) { - DeviceListItem item; + public View getView(int position, View view, ViewGroup viewGroup) { + Object o = current.get(position); + if (o instanceof SmDevice) { + return getSmDeviceView((SmDevice) o, view); + } else if (o instanceof SoilMonitor) { + return getSoilMonitorView((SoilMonitor) o, view); + } + + throw new RuntimeException("Not implemented"); + } + + private View getSmDeviceView(SmDevice smDevice, View view) { + + DeviceItem item; if (view == null) { view = inflater.inflate(R.layout.listitem_device, null); - item = new DeviceListItem(view); + item = new DeviceItem(view); view.setTag(item); view.setClickable(false); } else { - item = (DeviceListItem) view.getTag(); + item = (DeviceItem) view.getTag(); } - SmDevice smDevice = getItem(i); if (smDevice.getName() != null) { item.deviceName.setText(smDevice.getName()); } else { @@ -261,9 +407,13 @@ public class MainActivity extends ListActivity { return view; } + + private View getSoilMonitorView(SoilMonitor soilMonitor, View view) { + throw new RuntimeException("Not implemented"); + } } - private class MySmDeviceListener extends SmDeviceListener { + private class MySoilMoistureListener extends SoilMoistureListener { @Override public void onReady(boolean ok) { if (!ok) { @@ -297,11 +447,9 @@ public class MainActivity extends ListActivity { @Override public void onNewDevice(String address) { - SmDevice device = smDevicesManager.getDevice(address); + SmDevice device = soilMoistureService.getDevice(address); deviceList.devices.add(device); - deviceList.notifyDataSetInvalidated(); - - Log.i(TAG, "deviceList.devices.size() = " + deviceList.devices.size()); + deviceList.sort(); } } } diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java index 1ed7ecb..169f4b3 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java +++ b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java @@ -2,13 +2,12 @@ package io.trygvis.soilmoisture; import android.util.Log; -import java.util.Comparator; +import java.util.ArrayList; +import java.util.List; import io.trygvis.android.bt.BtDevice; class SmDevice implements BtDevice.BtDeviceWrapper { - public static final Comparator deviceComparator = (a, b) -> a.getBtDevice().getAddress().compareTo(b.getBtDevice().getAddress()); - private final static String TAG = SmDevice.class.getSimpleName(); private final BtDevice btDevice; @@ -17,6 +16,8 @@ class SmDevice implements BtDevice.BtDeviceWrapper { private Boolean isUseful; + private List monitors = new ArrayList<>(); + public SmDevice(BtDevice btDevice) { this.btDevice = btDevice; Log.i(TAG, "new device"); @@ -52,4 +53,8 @@ class SmDevice implements BtDevice.BtDeviceWrapper { public String getName() { return name; } + + public List getMonitors() { + return monitors; + } } diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmDevicesManager.java b/app/src/main/java/io/trygvis/soilmoisture/SmDevicesManager.java deleted file mode 100644 index 531061a..0000000 --- a/app/src/main/java/io/trygvis/soilmoisture/SmDevicesManager.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.trygvis.soilmoisture; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import java.util.Comparator; -import java.util.List; - -import io.trygvis.android.bt.BtDevice; - -public interface SmDevicesManager { - List getDevices(Comparator comparator); - - SmDevice getDevice(String address); - - boolean isScanning(); - - boolean startScanning(long scanPeriod); - - void stopScanning(); - - public abstract static class SmDeviceListener extends BroadcastReceiver { - - public static final String INTENT_NAME = SmDeviceListener.class.getName(); - - public static final IntentFilter INTENT_FILTER = new IntentFilter(INTENT_NAME); - - public void onReceive(Context context, Intent intent) { - if (!intent.getAction().equals(INTENT_NAME)) { - return; - } - - DefaultSmDevicesManager.dispatchEvent(intent, this); - } - - public void onReady(boolean ok) { - } - - public void onScanStarted() { - } - - public void onNewDevice(String address) { - } - - public void onScanStopped() { - } - } -} diff --git a/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java new file mode 100644 index 0000000..8100649 --- /dev/null +++ b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java @@ -0,0 +1,48 @@ +package io.trygvis.soilmoisture; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +import java.util.Comparator; +import java.util.List; + +public interface SoilMoistureService { + List getDevices(Comparator comparator); + + SmDevice getDevice(String address); + + boolean isScanning(); + + boolean startScanning(long scanPeriod); + + void stopScanning(); + + public abstract static class SoilMoistureListener extends BroadcastReceiver { + + public static final String INTENT_NAME = SoilMoistureListener.class.getName(); + + public static final IntentFilter INTENT_FILTER = new IntentFilter(INTENT_NAME); + + public void onReceive(Context context, Intent intent) { + if (!intent.getAction().equals(INTENT_NAME)) { + return; + } + + DefaultSoilMoistureService.dispatchEvent(intent, this); + } + + public void onReady(boolean ok) { + } + + public void onScanStarted() { + } + + public void onNewDevice(String address) { + } + + public void onScanStopped() { + } + } +} diff --git a/app/src/main/java/io/trygvis/soilmoisture/SoilMonitor.java b/app/src/main/java/io/trygvis/soilmoisture/SoilMonitor.java new file mode 100644 index 0000000..564202d --- /dev/null +++ b/app/src/main/java/io/trygvis/soilmoisture/SoilMonitor.java @@ -0,0 +1,35 @@ +package io.trygvis.soilmoisture; + +import java.util.Date; + +class SoilMonitor { + private final SmDevice device; + + private Date timestamp; + + private int lastValue; + + SoilMonitor(SmDevice device) { + this.device = device; + } + + public SmDevice getDevice() { + return device; + } + + public int getLastValue() { + return lastValue; + } + + public void setLastValue(int lastValue) { + this.lastValue = lastValue; + } + + public Date getTimestamp() { + return timestamp; + } + + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } +} diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml new file mode 100644 index 0000000..c96edfd --- /dev/null +++ b/app/src/main/res/layout/main.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/app/src/main/res/menu/gatt_services.xml b/app/src/main/res/menu/gatt_services.xml deleted file mode 100644 index 25d64b6..0000000 --- a/app/src/main/res/menu/gatt_services.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index 08b604e..2272040 100644 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -1,29 +1,32 @@ - - - - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml deleted file mode 100644 index 87a750e..0000000 --- a/app/src/main/res/menu/menu_main.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8aa5e33..0764a26 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,5 +31,7 @@ Name Refresh Current value + Show all + Group by device -- cgit v1.2.3