aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtPromise.java6
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java90
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/MainActivity.java21
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/SmDevice.java17
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/SmSensor.java5
-rw-r--r--app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java3
6 files changed, 110 insertions, 32 deletions
diff --git a/app/src/main/java/io/trygvis/android/bt/BtPromise.java b/app/src/main/java/io/trygvis/android/bt/BtPromise.java
index edb2894..50aad13 100644
--- a/app/src/main/java/io/trygvis/android/bt/BtPromise.java
+++ b/app/src/main/java/io/trygvis/android/bt/BtPromise.java
@@ -218,6 +218,12 @@ public class BtPromise {
return this;
}
+ public BtPromise andThen(BtPromise btPromise) {
+ actionQ.addAll(btPromise.actionQ);
+ finallyQ.addAll(btPromise.finallyQ);
+ return this;
+ }
+
public String toString() {
StringBuilder s = new StringBuilder("Queue: ");
diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
index 86a1917..85a6afb 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java
@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import io.trygvis.android.Function;
import io.trygvis.android.LocalBinder;
import io.trygvis.android.bt.BtDevice;
import io.trygvis.android.bt.BtPromise;
@@ -30,15 +31,20 @@ import io.trygvis.android.bt.BtService;
import io.trygvis.android.bt.DefaultBtService;
import io.trygvis.bluetooth.TrygvisIoUuids;
+import static io.trygvis.android.bt.BtPromise.PromiseResult.continueDirectly;
+import static io.trygvis.android.bt.BtPromise.PromiseResult.detour;
import static io.trygvis.android.bt.BtPromise.PromiseResult.stop;
import static io.trygvis.android.bt.BtPromise.PromiseResult.waitForNextEvent;
import static io.trygvis.android.bt.BtService.BtServiceListenerBroadcastReceiver;
import static io.trygvis.bluetooth.TrygvisIoUuids.CLIENT_CHARACTERISTIC_CONFIG;
import static io.trygvis.soilmoisture.SmDevice.GetSensorCountRes;
+import static io.trygvis.soilmoisture.SmDevice.GetSensorNameRes;
import static io.trygvis.soilmoisture.SmDevice.GetValueRes;
import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_SENSOR_COUNT;
+import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_SENSOR_NAME;
import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_VALUE;
import static io.trygvis.soilmoisture.SmDevice.createGetSensorCountReq;
+import static io.trygvis.soilmoisture.SmDevice.createGetSensorNameReq;
import static io.trygvis.soilmoisture.SmDevice.createGetValueReq;
import static io.trygvis.soilmoisture.SmDevice.parseResponse;
import static java.lang.String.valueOf;
@@ -127,12 +133,47 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
}
};
+ private BtPromise readAttribute(String value, byte[] req, Function<byte[], BtPromise.PromiseResult> handler) {
+ return new BtPromise().
+ onDirect(gatt -> {
+ Log.i(TAG, "Getting attribute: " + value);
+
+ BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE);
+ BluetoothGattCharacteristic soilMoisture = service.getCharacteristic(TrygvisIoUuids.Characteristics.SOIL_MOISTURE);
+
+ soilMoisture.setValue(req);
+ return gatt.writeCharacteristic(soilMoisture) ? waitForNextEvent() : stop();
+ }).
+ onCharacteristicWrite((gatt, characteristic) -> waitForNextEvent()).
+ onCharacteristicChanged((gatt, characteristic) -> {
+ byte[] bytes = characteristic.getValue();
+
+ return handler.apply(bytes);
+ });
+ }
+
+ private BtPromise readSensorName(SmDevice device, int index) {
+ byte[] req = createGetSensorNameReq((byte) index);
+
+ return readAttribute("sensor name, index#" + index, req, bytes -> {
+ GetSensorNameRes res = parseResponse(bytes, GET_SENSOR_NAME, GetSensorNameRes.class);
+ String name = res.name;
+
+ device.getSensorByIndex(index).ifPresent(sensor -> {
+ sensor.setName(name);
+ sendBroadcast(createDevicePropertyUpdated(device));
+ });
+
+ return index == device.getSensors().size() - 1 ? stop() : detour(readSensorName(device, index + 1));
+ });
+ }
+
public void probe(String address) {
BtDevice<SmDevice> btDevice = btService.getDevice(address);
SmDevice smDevice = btDevice.getTag();
Log.i(TAG, "Probing " + address + ", name=" + btDevice.getName());
- BtPromise executor = new BtPromise().
+ BtPromise promise = new BtPromise().
onDirect(gatt -> {
BluetoothGattService service = gatt.getService(TrygvisIoUuids.Services.SOIL_MOISTURE_SERVICE);
@@ -153,21 +194,8 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
return gatt.writeDescriptor(ccg) ? waitForNextEvent() : stop();
}).
onDescriptorWrite((gatt, descriptor) -> {
- Log.i(TAG, "Notifications enabled, getting sensor count");
- BluetoothGattCharacteristic c = descriptor.getCharacteristic();
- c.setValue(createGetSensorCountReq());
- return gatt.writeCharacteristic(c) ? waitForNextEvent() : stop();
- }).
- onCharacteristicWrite((gatt, characteristic) -> waitForNextEvent()).
- onCharacteristicChanged((gatt, characteristic) -> {
- GetSensorCountRes getSensorCountRes = parseResponse(characteristic.getValue(),
- GET_SENSOR_COUNT, GetSensorCountRes.class);
-
- Log.i(TAG, "The device has " + getSensorCountRes.count + " sensors.");
-
- markDeviceAsUseful(smDevice, getSensorCountRes.count);
-
- return stop();
+ Log.i(TAG, "Notifications enabled");
+ return continueDirectly();
}).
onFinally(success -> {
if (smDevice.getIsUseful() == null) {
@@ -175,7 +203,20 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
}
});
- btDevice.withConnection(executor);
+ BtPromise btPromise = readAttribute("sensor count", createGetSensorCountReq(), bytes -> {
+ GetSensorCountRes getSensorCountRes = parseResponse(bytes, GET_SENSOR_COUNT, GetSensorCountRes.class);
+
+ int count = getSensorCountRes.count;
+
+ Log.i(TAG, "The device has " + count + " sensors.");
+
+ markDeviceAsUseful(smDevice, count);
+
+ return detour(readSensorName(smDevice, 0));
+ });
+ promise.andThen(btPromise);
+
+ btDevice.withConnection(promise);
}
private void markDeviceAsNotUseful(SmDevice device) {
@@ -214,9 +255,9 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
values.put(Tables.C_SM_DEVICE, device.id);
values.put(Tables.C_INDEX, i);
id = db.insert(Tables.T_SM_SENSOR, null, values);
- }
- device.addSensor(new SmSensor(device, id, (byte) i));
+ device.addSensor(new SmSensor(device, id, (byte) i));
+ }
}
return null;
@@ -393,6 +434,12 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
putExtra("index", sensor.getIndex());
}
+ private Intent createDevicePropertyUpdated(SmDevice device) {
+ return new Intent(SoilMoistureListener.INTENT_NAME).
+ putExtra("event", "devicePropertyUpdated").
+ putExtra("address", device.getBtDevice().getAddress());
+ }
+
public static void dispatchEvent(Intent intent, SoilMoistureListener listener) {
String event = intent.getStringExtra("event");
Log.i(TAG, "Dispatching event " + intent.getAction() + "/" + event);
@@ -421,7 +468,12 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS
intent.getStringExtra("address"),
intent.getIntExtra("index", -1));
break;
+ case "devicePropertyUpdated":
+ listener.onDevicePropertyUpdated(
+ intent.getStringExtra("address"));
+ break;
default:
+ Log.w(TAG, "Unknown event: " + event);
break;
}
}
diff --git a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
index 79b09c4..e838f01 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/MainActivity.java
@@ -216,7 +216,7 @@ public class MainActivity extends ListActivity {
//
// -----------------------------------------------------------------------
- public static class BtDeviceDialogFragment extends DialogFragment {
+ public static class ProbeDeviceDialogFragment extends DialogFragment {
private MainActivity mainActivity;
@@ -243,17 +243,19 @@ public class MainActivity extends ListActivity {
}
private boolean onBtDeviceLongClick(BtDevice<SmDevice> device) {
- Log.i(TAG, "onBtDeviceClick, device=" + device.getId());
-
- BtDeviceDialogFragment dialog = new BtDeviceDialogFragment();
+ ProbeDeviceDialogFragment dialog = new ProbeDeviceDialogFragment();
Bundle arguments = new Bundle();
arguments.putString("address", device.getAddress());
dialog.setArguments(arguments);
- dialog.show(getFragmentManager(), "BtDeviceDialogFragment");
+ dialog.show(getFragmentManager(), "ProbeDeviceDialogFragment");
return true;
}
+ private boolean onSmDeviceLongClick(SmDevice device) {
+ return onBtDeviceLongClick(device.getBtDevice());
+ }
+
private void onSmDeviceClick(SmDevice device) {
Log.i(TAG, "onSmDeviceClick, device=" + device.getBtDevice().getId());
}
@@ -509,13 +511,8 @@ public class MainActivity extends ListActivity {
if (view == null) {
view = inflater.inflate(R.layout.fragment_device, null);
view.setTag(new DeviceItem(view));
- view.setOnClickListener(v -> {
- Log.i(TAG, "onClick: SmDevice, " +
-// "position=" + position + ", " +
- "device=" + smDevice /*+ ", " +
- "tag=" + v.getTag()*/);
- onSmDeviceClick(smDevice);
- });
+ view.setOnClickListener(v -> onSmDeviceClick(smDevice));
+ view.setOnLongClickListener(v -> onSmDeviceLongClick(smDevice));
}
DeviceItem item = (DeviceItem) view.getTag();
diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
index d56f33e..bf2b5f3 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/SmDevice.java
@@ -3,6 +3,7 @@ package io.trygvis.soilmoisture;
import android.util.Log;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -11,6 +12,7 @@ import io.trygvis.android.bt.BtDevice;
import static io.trygvis.android.Optional.empty;
import static io.trygvis.android.Optional.of;
+import static io.trygvis.android.bt.BtUtils.toHexString;
import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_SENSOR_COUNT;
import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_SENSOR_NAME;
import static io.trygvis.soilmoisture.SmDevice.SmCmdCode.GET_VALUE;
@@ -114,7 +116,7 @@ class SmDevice {
// Message parsing and handling.
// -----------------------------------------------------------------------
- @SuppressWarnings({"unchecked", "StatementWithEmptyBody"})
+ @SuppressWarnings({"unchecked", "StatementWithEmptyBody", "UnusedParameters"})
public static <T> T parseResponse(byte[] bytes, SmCmdCode code, Class<T> klass) {
byte c = bytes[0];
@@ -130,6 +132,7 @@ class SmDevice {
} else if (c == GET_WARNING_VALUE.code) {
} else if (c == SET_SENSOR_NAME.code) {
} else if (c == GET_SENSOR_NAME.code) {
+ return (T) new GetSensorNameRes(bytes);
}
throw new RuntimeException("Unknown code: " + c);
@@ -151,6 +154,18 @@ class SmDevice {
}
}
+ public static class GetSensorNameRes {
+ public final String name;
+
+ public GetSensorNameRes(byte[] bytes) {
+ int count = bytes[1];
+
+ Log.i(TAG, "count=" + count + ", bytes=" + toHexString(bytes));
+
+ name = new String(bytes, 2, Math.min(bytes.length - 1, count), StandardCharsets.UTF_8);
+ }
+ }
+
public static byte[] createGetSensorCountReq() {
return new byte[]{
GET_SENSOR_COUNT.code
diff --git a/app/src/main/java/io/trygvis/soilmoisture/SmSensor.java b/app/src/main/java/io/trygvis/soilmoisture/SmSensor.java
index 0f49027..3c6cac3 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/SmSensor.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/SmSensor.java
@@ -38,6 +38,10 @@ class SmSensor {
return name;
}
+ public void setName(String name) {
+ this.name = name;
+ }
+
public Integer getLastValue() {
return lastValue;
}
@@ -53,6 +57,7 @@ class SmSensor {
public String toString() {
return "SmSensor[id=" + id + ", " +
"device=" + device.getBtDevice().getAddress() + ", " +
+ "name=" + (name != null ? name : "unknown") + ", " +
"index=" + getIndex() + "]";
}
diff --git a/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java
index b7f2060..352cba3 100644
--- a/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java
+++ b/app/src/main/java/io/trygvis/soilmoisture/SoilMoistureService.java
@@ -52,5 +52,8 @@ public interface SoilMoistureService {
public void onNewSample(String address, int sensor) {
}
+
+ public void onDevicePropertyUpdated(String address) {
+ }
}
}