aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/io/trygvis/soilmoisture
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/io/trygvis/soilmoisture')
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java15
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/MainActivity.java191
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/SensorActivity.java134
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/SmDevice.java4
4 files changed, 274 insertions, 70 deletions
diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
index 85a6afb..3e1c93b 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
@@ -119,7 +119,8 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
sendBroadcast(createNewDevice(address));
boolean candidate = btDevice.getAddress().startsWith("FB:") ||
- btDevice.getAddress().startsWith("FD:");
+ btDevice.getAddress().startsWith("FD:") ||
+ btDevice.getAddress().startsWith("CE:");
if (!candidate) {
Log.w(TAG, "Skipping device: " + btDevice.getAddress());
@@ -131,6 +132,11 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
probe(smDevice.getBtDevice().getAddress());
}
}
+
+ @Override
+ public void onDevicePropertyUpdated(String address) {
+ sendBroadcast(createDevicePropertyUpdated(getDevice(address)));
+ }
};
private BtPromise readAttribute(String value, byte[] req, Function<byte[], BtPromise.PromiseResult> handler) {
@@ -159,7 +165,7 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
GetSensorNameRes res = parseResponse(bytes, GET_SENSOR_NAME, GetSensorNameRes.class);
String name = res.name;
- device.getSensorByIndex(index).ifPresent(sensor -> {
+ device.getSensorByNumber(index).ifPresent(sensor -> {
sensor.setName(name);
sendBroadcast(createDevicePropertyUpdated(device));
});
@@ -198,6 +204,7 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
return continueDirectly();
}).
onFinally(success -> {
+ Log.i(TAG, "finally, smDevice.getIsUseful()=" + smDevice.getIsUseful());
if (smDevice.getIsUseful() == null) {
smDevice.setIsUseful(false);
}
@@ -256,7 +263,11 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
values.put(Tables.C_INDEX, i);
id = db.insert(Tables.T_SM_SENSOR, null, values);
+ Log.i(TAG, "Created new sensor row, id=" + id);
+
device.addSensor(new SmSensor(device, id, (byte) i));
+ } else {
+ Log.i(TAG, "Using existing sensor row, id=" + id);
}
}
diff --git a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
index e838f01..6996ef8 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
@@ -47,7 +47,7 @@ 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 SoilMoistureListener serviceListener = new MySoilMoistureListener();
+ private final SoilMoistureListener serviceListener = new MainSoilMoistureListener();
private final MainActivity context = this;
private DeviceListAdapter deviceList;
@@ -56,7 +56,10 @@ public class MainActivity extends ListActivity {
private ProgressDialog initializing;
private boolean ready;
- @Override
+ private int red;
+ private int yellow;
+ private int green;
+
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
Thread.setDefaultUncaughtExceptionHandler(EXCEPTION_HANDLER);
@@ -92,8 +95,12 @@ public class MainActivity extends ListActivity {
bindService(new Intent(this, DefaultSoilMoistureService.class), serviceConnection, BIND_AUTO_CREATE);
- initializing = ProgressDialog.
- show(this, "Initializing", "Connecting to Bluetooth system.", true);
+// initializing = ProgressDialog.
+// show(this, "Initializing", "Connecting to Bluetooth system.", true);
+
+ green = getResources().getColor(R.color.green);
+ yellow = getResources().getColor(R.color.yellow);
+ red = getResources().getColor(R.color.red);
setContentView(R.layout.main);
}
@@ -264,36 +271,126 @@ public class MainActivity extends ListActivity {
Log.i(TAG, "onSensorClick, device=" + sensor.getDevice().getBtDevice().getId() + "/" + sensor.getIndex());
sensor.readCurrentValue();
+
+// Intent intent = new Intent(this, SensorActivity.class);
+// intent.putExtra(SensorActivity.EXTRA_ADDRESS, sensor.getDevice().getBtDevice().getAddress());
+// intent.putExtra(SensorActivity.EXTRA_NUMBER, sensor.getIndex());
+// startActivity(intent);
}
// -----------------------------------------------------------------------
//
// -----------------------------------------------------------------------
- static class DeviceItem {
+ class DeviceItem {
+ final SmDevice device;
+ final TextView statusBar;
final TextView deviceName;
final TextView deviceAddress;
final TextView rssi;
final TextView info;
- DeviceItem(View view) {
+ DeviceItem(SmDevice device, View view) {
+ this.device = device;
+ this.statusBar = (TextView) view.findViewById(R.id.status_bar);
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);
this.info = (TextView) view.findViewById(R.id.device_info);
}
+
+ public void update() {
+ statusBar.setVisibility(deviceList.isGroupByDevice() ? View.VISIBLE : View.GONE);
+ statusBar.setBackgroundColor(statusColor(device));
+
+ if (device.getName() != null) {
+ deviceName.setText(device.getName());
+ } else {
+ deviceName.setText(R.string.unknown_device);
+ }
+ String address = device.getBtDevice().getAddress();
+
+ if (!device.isProbed()) {
+ address += " not probed";
+ } else if (device.isUseful()) {
+ address += " useful";
+ } else {
+ address += " not useful";
+ }
+
+ address += ", connected=" + device.getBtDevice().connected();
+ address += ", recentlySeen=" + device.getBtDevice().isRecentlySeen();
+
+ deviceAddress.setText(address);
+
+ String rssi = getText(R.string.rssi) + ": " +
+ (device.getBtDevice().getRssi() != null ? valueOf(device.getBtDevice().getRssi()) : getText(R.string.unknown));
+ rssi += ", device: " + device.toString();
+ this.rssi.setText(rssi);
+
+// boolean useful = device.isUseful();
+//
+// if (useful) {
+// info.setText("Number of sensors: " + device.getSensors().size());
+// } else {
+// info.setText("");
+// }
+ }
}
- static class SensorItem {
+ class SensorItem {
+ final SmDevice device;
final SmSensor sensor;
+ final TextView statusBar;
final TextView description;
final ProgressBar sensorProgress;
SensorItem(SmSensor sensor, View view) {
this.sensor = sensor;
+ this.statusBar = (TextView) view.findViewById(R.id.status_bar);
this.description = (TextView) view.findViewById(R.id.description);
this.sensorProgress = (ProgressBar) view.findViewById(R.id.sensor_progress);
sensorProgress.setMax(1024);
+
+ device = sensor.getDevice();
+
+ view.setClickable(true);
+ view.setOnClickListener(v -> {
+ Log.i(TAG, "onClick, SmSensor: " +
+// "position=" + position + ", " +
+ "sensor=" + sensor /*+ ", " +
+ "tag=" + v.getTag()*/);
+ onSensorClick(sensor);
+ });
+ }
+
+ public void update() {
+ statusBar.setVisibility(deviceList.isGroupByDevice() ? View.GONE : View.VISIBLE);
+ statusBar.setBackgroundColor(statusColor(device));
+
+ if (deviceList.isGroupByDevice()) {
+ statusBar.setVisibility(View.GONE);
+ } else {
+ statusBar.setVisibility(View.VISIBLE);
+ statusBar.setBackgroundColor(statusColor(device));
+ }
+
+ Integer value = sensor.getLastValue();
+ String text = "Sensor " + sensor;
+ text += ", value: " + (value == null ? "Unknown" : value);
+ description.setText(text);
+
+ sensorProgress.setProgress(value != null ? value : 0);
+ }
+ }
+
+ private int statusColor(SmDevice device) {
+ if (device.getBtDevice().connected()) {
+ return green;
+ } else if (device.getBtDevice().isRecentlySeen()) {
+ return yellow;
+ } else {
+ return red;
}
}
@@ -349,6 +446,7 @@ public class MainActivity extends ListActivity {
}
public void notifyDataSetChanged() {
+ Log.i(TAG, "notifyDataSetChanged");
dataSetObservable.notifyChanged();
}
@@ -475,9 +573,9 @@ public class MainActivity extends ListActivity {
//noinspection unchecked
return getBtDeviceView((BtDevice<SmDevice>) o, view);
} else if (o instanceof SmDevice) {
- return getSmDeviceView(position, (SmDevice) o, view);
+ return getSmDeviceView((SmDevice) o, view);
} else if (o instanceof SmSensor) {
- return getSoilSensorView(position, (SmSensor) o, view);
+ return getSoilSensorView((SmSensor) o, view);
}
throw new RuntimeException("Not implemented");
@@ -486,7 +584,7 @@ public class MainActivity extends ListActivity {
private View getBtDeviceView(BtDevice<SmDevice> device, View view) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_device, null);
- view.setTag(new DeviceItem(view));
+ view.setTag(new DeviceItem(device.getTag(), view));
view.setOnLongClickListener(v -> MainActivity.this.onBtDeviceLongClick(device));
}
@@ -507,79 +605,33 @@ public class MainActivity extends ListActivity {
return view;
}
- private View getSmDeviceView(int position, SmDevice smDevice, View view) {
+ private View getSmDeviceView(SmDevice smDevice, View view) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_device, null);
- view.setTag(new DeviceItem(view));
+ view.setTag(new DeviceItem(smDevice, view));
view.setOnClickListener(v -> onSmDeviceClick(smDevice));
view.setOnLongClickListener(v -> onSmDeviceLongClick(smDevice));
}
- DeviceItem item = (DeviceItem) view.getTag();
-
- if (smDevice.getName() != null) {
- item.deviceName.setText(smDevice.getName());
- } else {
- item.deviceName.setText(R.string.unknown_device);
- }
- String address = smDevice.getBtDevice().getAddress();
-
- if (!smDevice.isProbed()) {
- address += " not probed";
- } else if (smDevice.isUseful()) {
- address += " useful";
- } else {
- address += " not useful";
- }
-
- address += ", connected=" + smDevice.getBtDevice().connected();
-
- item.deviceAddress.setText(address);
-
- String rssi = getText(R.string.rssi) + ": " +
- (smDevice.getBtDevice().getRssi() != null ? valueOf(smDevice.getBtDevice().getRssi()) : getText(R.string.unknown));
- rssi += ", device: " + smDevice.toString();
- item.rssi.setText(rssi);
-
- boolean useful = smDevice.isUseful();
-
- if (useful) {
- item.info.setText("Number of sensors: " + smDevice.getSensors().size());
- } else {
- item.info.setText("");
- }
+ ((DeviceItem) view.getTag()).update();
return view;
}
- private View getSoilSensorView(int position, SmSensor smSensor, View view) {
+ private View getSoilSensorView(SmSensor smSensor, View view) {
if (view == null) {
- view = inflater.inflate(R.layout.fragment_sensor, null);
- view.setTag(new SensorItem(smSensor, view));
- view.setClickable(true);
- view.setOnClickListener(v -> {
- Log.i(TAG, "onClick, SmSensor: " +
-// "position=" + position + ", " +
- "sensor=" + smSensor /*+ ", " +
- "tag=" + v.getTag()*/);
- onSensorClick(smSensor);
- });
+ view = inflater.inflate(R.layout.fragment_main_sensor, null);
+ SensorItem item = new SensorItem(smSensor, view);
+ view.setTag(item);
}
- SensorItem item = (SensorItem) view.getTag();
-
- Integer value = smSensor.getLastValue();
- String text = "Sensor " + smSensor;
- text += ", value: " + (value == null ? "Unknown" : value);
- item.description.setText(text);
-
- item.sensorProgress.setProgress(value != null ? value : 0);
+ ((SensorItem) view.getTag()).update();
return view;
}
}
- private class MySoilMoistureListener extends SoilMoistureListener {
+ private class MainSoilMoistureListener extends SoilMoistureListener {
@Override
public void onToast(int id, int length) {
CharSequence text = getText(id);
@@ -605,7 +657,9 @@ public class MainActivity extends ListActivity {
deviceList.notifyDataSetChanged();
startScan();
- initializing.dismiss();
+ if (initializing != null) {
+ initializing.dismiss();
+ }
}
}
@@ -630,5 +684,10 @@ public class MainActivity extends ListActivity {
public void onNewSample(String address, int sensor) {
deviceList.notifyDataSetChanged();
}
+
+ @Override
+ public void onDevicePropertyUpdated(String address) {
+ deviceList.notifyDataSetChanged();
+ }
}
}
diff --git a/app/src/main/java/io/trygvis/soilmoisture/SensorActivity.java b/app/src/main/java/io/trygvis/soilmoisture/SensorActivity.java
new file mode 100644
index 0000000..358382c
--- /dev/null
+++ b/app/src/main/java/io/trygvis/soilmoisture/SensorActivity.java
@@ -0,0 +1,134 @@
+package io.trygvis.soilmoisture;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import io.trygvis.android.LocalBinder;
+import io.trygvis.android.Optional;
+
+import static io.trygvis.soilmoisture.SoilMoistureService.SoilMoistureListener;
+
+public class SensorActivity extends Activity {
+ private final static String TAG = SensorActivity.class.getSimpleName();
+
+ public static final String EXTRA_ADDRESS = "address";
+ public static final String EXTRA_NUMBER = "number";
+
+ private final Context context = this;
+ private String address;
+ private int number;
+
+ private ServiceConnection serviceConnection;
+ private SoilMoistureService soilMoistureService;
+ private SensorSoilMoistureListener serviceListener = new SensorSoilMoistureListener();
+ private SmDevice device;
+ private SmSensor sensor;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_sensor);
+ if (savedInstanceState == null) {
+ getFragmentManager().beginTransaction()
+ .add(R.id.container, new PlaceholderFragment())
+ .commit();
+ }
+
+ address = getIntent().getStringExtra(EXTRA_ADDRESS);
+ number = getIntent().getIntExtra(EXTRA_NUMBER, -1);
+
+ ActionBar actionBar = getActionBar();
+
+ if (actionBar != null) {
+ actionBar.setTitle(number + ": " + address);
+ }
+
+ serviceConnection = new ServiceConnection() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder service) {
+ Log.i(TAG, "onServiceConnected");
+ soilMoistureService = ((LocalBinder<SoilMoistureService>) service).getService();
+ registerReceiver(serviceListener, SoilMoistureListener.INTENT_FILTER);
+
+ device = soilMoistureService.getDevice(address);
+ Optional<SmSensor> o = device.getSensorByNumber(number);
+
+ if (!o.isPresent()) {
+ Toast.makeText(context, "Could not find sensor #" + number + " on device " + address,
+ Toast.LENGTH_LONG).show();
+ finish();
+ }
+ sensor = o.get();
+
+ runOnUiThread(SensorActivity.this::initializeView);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ Log.i(TAG, "onServiceDisconnected");
+ soilMoistureService = null;
+ }
+ };
+ }
+
+ public void initializeView() {
+ // current value, last updated
+ // sync to cloud
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_sensor, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+
+ public PlaceholderFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_sensor, container, false);
+ return rootView;
+ }
+ }
+
+
+
+ private class SensorSoilMoistureListener extends SoilMoistureListener {
+ }
+}
diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
index bf2b5f3..808cbb6 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
@@ -80,7 +80,7 @@ class SmDevice {
return sensors;
}
- public Optional<SmSensor> getSensorByIndex(int index) {
+ public Optional<SmSensor> getSensorByNumber(int index) {
if (!isUseful()) {
throw new IllegalStateException("Not a useful device");
}
@@ -95,7 +95,7 @@ class SmDevice {
}
void addSensor(SmSensor sensor) {
- if (getSensorByIndex(sensor.index).isPresent()) {
+ if (getSensorByNumber(sensor.index).isPresent()) {
throw new IllegalStateException("This device already contains a sensor with index=" + sensor.index);
}