mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
casio: introduce BLE legacy writes to fake not-yet-written characteristic values (#5008)
This commit is contained in:
committed by
José Rebelo
parent
ed5de171e8
commit
2709446597
+18
@@ -18,6 +18,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.btle;
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
@@ -64,6 +65,23 @@ public class TransactionBuilder {
|
||||
return add(action);
|
||||
}
|
||||
|
||||
/// Use this only if <strong>ALL</strong> conditions are true:
|
||||
/// <ol>
|
||||
/// <li>characteristic has write type {@link BluetoothGattCharacteristic#WRITE_TYPE_NO_RESPONSE},</li>
|
||||
/// <li>custom {@link GattCallback#onCharacteristicWrite(BluetoothGatt, BluetoothGattCharacteristic, int)}
|
||||
/// uses {@link BluetoothGattCharacteristic#getValue()} and</li>
|
||||
/// <li>no {@link BluetoothGatt#beginReliableWrite()} was used.</li>
|
||||
/// </ol>
|
||||
/// @see WriteAction
|
||||
public TransactionBuilder writeLegacy(BluetoothGattCharacteristic characteristic, byte[] data) {
|
||||
if (characteristic == null) {
|
||||
LOG.warn("Unable to write characteristic: null");
|
||||
return this;
|
||||
}
|
||||
WriteAction action = new WriteAction(characteristic, data, true);
|
||||
return add(action);
|
||||
}
|
||||
|
||||
/// @see WriteAction
|
||||
public TransactionBuilder write(BluetoothGattCharacteristic characteristic, byte[] data) {
|
||||
if (characteristic == null) {
|
||||
|
||||
+12
-3
@@ -40,10 +40,16 @@ public class WriteAction extends BtLEAction {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WriteAction.class);
|
||||
|
||||
private final byte[] value;
|
||||
private final boolean legacyCompat;
|
||||
|
||||
public WriteAction(BluetoothGattCharacteristic characteristic, byte[] value) {
|
||||
this(characteristic, value, false);
|
||||
}
|
||||
|
||||
public WriteAction(BluetoothGattCharacteristic characteristic, byte[] value, boolean legacyCompat) {
|
||||
super(characteristic);
|
||||
this.value = value;
|
||||
this.legacyCompat = legacyCompat;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,7 +58,7 @@ public class WriteAction extends BtLEAction {
|
||||
int properties = characteristic.getProperties();
|
||||
//TODO: expectsResult should return false if PROPERTY_WRITE_NO_RESPONSE is true, but this leads to timing issues
|
||||
if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0 || ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0)) {
|
||||
return writeCharacteristicImp(gatt, characteristic, getValue());
|
||||
return writeCharacteristicImp(gatt, characteristic, getValue(), legacyCompat);
|
||||
}
|
||||
|
||||
LOG.error("WriteAction for non-writeable characteristic {}", characteristic.getUuid());
|
||||
@@ -64,14 +70,17 @@ public class WriteAction extends BtLEAction {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("writing to characteristic: {} - {}", characteristic.getUuid(), Logging.formatBytes(value));
|
||||
}
|
||||
return writeCharacteristicImp(gatt, characteristic, value);
|
||||
return writeCharacteristicImp(gatt, characteristic, value, false);
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private static boolean writeCharacteristicImp(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
|
||||
private static boolean writeCharacteristicImp(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value, boolean legacyCompat) {
|
||||
if (GBApplication.isRunningTiramisuOrLater()) {
|
||||
// use API introduced in SDK level 33 to catch exceptions and more specific errors
|
||||
try {
|
||||
if (legacyCompat) {
|
||||
characteristic.setValue(value);
|
||||
}
|
||||
final int status = gatt.writeCharacteristic(characteristic, value, characteristic.getWriteType());
|
||||
if (status == BluetoothStatusCodes.SUCCESS) {
|
||||
return true;
|
||||
|
||||
+2
-2
@@ -131,11 +131,11 @@ public abstract class Casio2C2DSupport extends CasioSupport {
|
||||
if (!requests.isEmpty()) {
|
||||
LOG.warn("writing while waiting for a response may lead to incorrect received responses");
|
||||
}
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID), arr);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID), arr);
|
||||
}
|
||||
|
||||
public void writeAllFeaturesRequest(TransactionBuilder builder, byte[] arr) {
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_READ_REQUEST_FOR_ALL_FEATURES_CHARACTERISTIC_UUID), arr);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_READ_REQUEST_FOR_ALL_FEATURES_CHARACTERISTIC_UUID), arr);
|
||||
}
|
||||
|
||||
public interface ResponseHandler {
|
||||
|
||||
+7
-7
@@ -208,7 +208,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
|
||||
BluetoothGattService llService = mBtGatt.getService(CasioConstants.LINK_LOSS_SERVICE);
|
||||
BluetoothGattCharacteristic charact = llService.getCharacteristic(CasioConstants.ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
builder.write(charact, value);
|
||||
builder.writeLegacy(charact, value);
|
||||
builder.wait(mCasioSleepTime);
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
BluetoothGattCharacteristic charact = getCharacteristic(CasioConstants.CURRENT_TIME_CHARACTERISTIC_UUID);
|
||||
if(charact != null) {
|
||||
charact.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
builder.write(charact, arr);
|
||||
builder.writeLegacy(charact, arr);
|
||||
}
|
||||
else {
|
||||
LOG.warn("Characteristic not found: CURRENT_TIME_CHARACTERISTIC_UUID");
|
||||
@@ -259,7 +259,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
byte byte1 = (byte)(dstOffset / 15);
|
||||
BluetoothGattCharacteristic charact = getCharacteristic(CasioConstants.LOCAL_TIME_CHARACTERISTIC_UUID);
|
||||
if(charact != null) {
|
||||
builder.write(charact, new byte[]{byte0, byte1});
|
||||
builder.writeLegacy(charact, new byte[]{byte0, byte1});
|
||||
}
|
||||
else {
|
||||
LOG.warn("Characteristic not found: LOCAL_TIME_CHARACTERISTIC_UUID");
|
||||
@@ -276,7 +276,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
|
||||
BluetoothGattCharacteristic charact = getCharacteristic(CasioConstants.CASIO_VIRTUAL_SERVER_FEATURES);
|
||||
if(charact != null) {
|
||||
builder.write(charact, new byte[]{byte0, 0x00});
|
||||
builder.writeLegacy(charact, new byte[]{byte0, 0x00});
|
||||
}
|
||||
else {
|
||||
LOG.warn("Characteristic not found: CASIO_VIRTUAL_SERVER_FEATURES");
|
||||
@@ -462,7 +462,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
msg[1] = 1;
|
||||
System.arraycopy(titleBytes, 0, msg, 2, len);
|
||||
|
||||
builder.write(getCharacteristic(CasioConstants.ALERT_CHARACTERISTIC_UUID), msg);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.ALERT_CHARACTERISTIC_UUID), msg);
|
||||
LOG.info("Showing notification, title: " + title + " message (not sent): " + message);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
@@ -563,7 +563,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
arr[1] = 10;
|
||||
arr[2] = 1;
|
||||
System.arraycopy(bInfo, 0, arr, 3, len);
|
||||
builder.write(getCharacteristic(CasioConstants.MORE_ALERT_FOR_LONG_UUID), arr);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.MORE_ALERT_FOR_LONG_UUID), arr);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
LOG.warn("sendMusicInfo failed: " + e.getMessage());
|
||||
@@ -596,7 +596,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
|
||||
|
||||
BluetoothGattService service = mBtGatt.getService(CasioConstants.IMMEDIATE_ALERT_SERVICE_UUID);
|
||||
BluetoothGattCharacteristic charact = service.getCharacteristic(CasioConstants.ALERT_LEVEL_CHARACTERISTIC_UUID);
|
||||
builder.write(charact, value);
|
||||
builder.writeLegacy(charact, value);
|
||||
LOG.info("onFindDevice sent");
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ public class InitOperation extends AbstractBTLEOperation<CasioGB6900DeviceSuppor
|
||||
try {
|
||||
TransactionBuilder builder = getSupport().createTransactionBuilder("writeBleInit");
|
||||
builder.setCallback(this);
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID), mBleSettings);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID), mBleSettings);
|
||||
getSupport().performImmediately(builder);
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error writing BLE settings: " + e.getMessage());
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ public class SetAlarmOperation extends AbstractBTLEOperation<CasioGB6900DeviceSu
|
||||
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("setAlarm");
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_ALM_CHARACTERISTIC_UUID), data);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_ALM_CHARACTERISTIC_UUID), data);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error setting alarm: " + e.getMessage());
|
||||
|
||||
+1
-1
@@ -402,7 +402,7 @@ public class CasioGBX100DeviceSupport extends Casio2C2DSupport implements Shared
|
||||
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("showNotification");
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_NOTIFICATION_CHARACTERISTIC_UUID), copy);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_NOTIFICATION_CHARACTERISTIC_UUID), copy);
|
||||
LOG.info("Showing notification, title: {} message: {}", title, message);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("requestStepCountDate");
|
||||
builder.setCallback(this);
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error requesting step count data", e);
|
||||
@@ -78,7 +78,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("writeStepCountAck");
|
||||
builder.setCallback(this);
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.writeLegacy(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error writing step count ack", e);
|
||||
|
||||
Reference in New Issue
Block a user