From 06aa945dc084161c70d1ccfc56cea18a09c2ae16 Mon Sep 17 00:00:00 2001 From: Vyacheslav Chigrin Date: Wed, 1 May 2024 17:08:52 +0300 Subject: [PATCH] Support "Find my phone" functionality in PineTime. --- .../devices/pinetime/PineTimeJFSupport.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java index 4cfc1ab66..c9ea82a22 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pinetime/PineTimeJFSupport.java @@ -25,8 +25,10 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.pinetime.weather.Weat import static nodomain.freeyourgadget.gadgetbridge.devices.pinetime.weather.WeatherData.mapOpenWeatherConditionToPineTimeSpecial; import static nodomain.freeyourgadget.gadgetbridge.devices.pinetime.weather.WeatherData.mapOpenWeatherConditionToPineTimeCondition; +import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattService; import android.content.Intent; import android.net.Uri; import android.os.Build; @@ -72,6 +74,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; @@ -260,6 +263,10 @@ public class PineTimeJFSupport extends AbstractBTLEDeviceSupport implements DfuL } }; + private static final byte AlertLevelNoAlert = 0; + private static final byte AlertLevelMildAlert = 1; + private static final byte AlertLevelHighAlert = 2; + public PineTimeJFSupport() { super(LOG); addSupportedService(GattService.UUID_SERVICE_ALERT_NOTIFICATION); @@ -296,6 +303,20 @@ public class PineTimeJFSupport extends AbstractBTLEDeviceSupport implements DfuL batteryInfoProfile = new BatteryInfoProfile<>(this); batteryInfoProfile.addListener(mListener); addSupportedProfile(batteryInfoProfile); + + BluetoothGattService alertGATTService = new BluetoothGattService( + GattService.UUID_SERVICE_IMMEDIATE_ALERT, + BluetoothGattService.SERVICE_TYPE_PRIMARY); + BluetoothGattCharacteristic alertLevelCharacteristic = new BluetoothGattCharacteristic( + GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL, + BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, + BluetoothGattCharacteristic.PERMISSION_WRITE); + + alertLevelCharacteristic.setValue(new byte[]{AlertLevelNoAlert}); + + alertGATTService.addCharacteristic(alertLevelCharacteristic); + + addSupportedServerService(alertGATTService); } private void handleBatteryInfo(nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfo info) { @@ -1272,4 +1293,28 @@ public class PineTimeJFSupport extends AbstractBTLEDeviceSupport implements DfuL LOG.debug(logMessage); //GB.toast(getContext(), toastMessage, Toast.LENGTH_LONG, GB.WARN); } + + @Override + public boolean onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { + if (!characteristic.getUuid().equals(GattCharacteristic.UUID_CHARACTERISTIC_ALERT_LEVEL)) { + return false; + } + if (value.length != 1) { + LOG.error("Got unexpected data length " + String.valueOf(value.length)); + return false; + } + boolean start = true; + if (value[0] == AlertLevelMildAlert || value[0] == AlertLevelHighAlert) { + start = true; + } else if (value[0] == AlertLevelNoAlert) { + start = false; + } else { + LOG.error("Got unexpected alert level " + String.valueOf(value[0])); + return false; + } + GBDeviceEventFindPhone deviceEventFindPhone = new GBDeviceEventFindPhone(); + deviceEventFindPhone.event = start ? GBDeviceEventFindPhone.Event.START : GBDeviceEventFindPhone.Event.STOP; + evaluateGBDeviceEvent(deviceEventFindPhone); + return true; + } }