1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-01 14:32:54 +01:00

Add BTBR service

This commit is contained in:
Damien Gaignon 2022-10-15 18:06:01 +02:00 committed by José Rebelo
parent b2aa61e182
commit be575af314
47 changed files with 1132 additions and 55 deletions

View File

@ -0,0 +1,155 @@
/* Copyright (C) 2022 Damien Gaignon
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import org.slf4j.Logger;
import android.location.Location;
import java.io.IOException;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.CheckInitializedAction;
/**
* Abstract base class for devices connected through a serial protocol, like RFCOMM BT or TCP socket.
* <p/>
* The connection to the device and all communication is made with a generic {@link BtClassicIo}.
* Messages to the device are encoded
* sent via {@link BtClassicIo}.
*
* @see BtClassicIo
*/
public abstract class AbstractBTBRDeviceSupport extends AbstractDeviceSupport implements SocketCallback {
private BtBRQueue mQueue;
private UUID mSupportedService = null;
private Logger logger;
public AbstractBTBRDeviceSupport(Logger logger) {
this.logger = logger;
if (logger == null) {
throw new IllegalArgumentException("logger must not be null");
}
}
@Override
public boolean connect() {
if (mQueue == null) {
mQueue = new BtBRQueue(getBluetoothAdapter(), getDevice(), getContext(), this, getSupportedService());
}
return mQueue.connect();
}
/**
* Subclasses should populate the given builder to initialize the device (if necessary).
*
* @return the same builder as passed as the argument
*/
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
return builder;
}
@Override
public void dispose() {
if (mQueue != null) {
mQueue.dispose();
mQueue = null;
}
}
public TransactionBuilder createTransactionBuilder(String taskName) {
return new TransactionBuilder(taskName);
}
/**
* Ensures that the device is connected and (only then) performs the actions of the given
* transaction builder.
*
* In contrast to {@link #performInitialized(String)}, no initialization sequence is performed
* with the device, only the actions of the given builder are executed.
* @param transaction
* @throws IOException
* @see {@link #performInitialized(String)}
*/
public void performConnected(Transaction transaction) throws IOException {
if (!isConnected()) {
if (!connect()) {
throw new IOException("2: Unable to connect to device: " + getDevice());
}
}
getQueue().add(transaction);
}
public BtBRQueue getQueue() {
return mQueue;
}
/**
* Subclasses should call this method to add services they support.
* Only supported services will be queried for characteristics.
*
* @param aSupportedService
*/
protected void addSupportedService(UUID aSupportedService) {
mSupportedService = aSupportedService;
}
protected UUID getSupportedService() {
return mSupportedService;
}
/**
* Utility method that may be used to log incoming messages when we don't know how to deal with them yet.
*
* @param value
*/
public void logMessageContent(byte[] value) {
logger.info("RECEIVED DATA WITH LENGTH: " + ((value != null) ? value.length : "(null)"));
Logging.logBytes(logger, value);
}
public void onConnectionEstablished() {
initializeDevice(createTransactionBuilder("Initializing device")).queue(getQueue());
}
@Override
public void onSetFmFrequency(float frequency) {}
@Override
public void onSetLedColor(int color) {}
@Override
public void onSetGpsLocation(Location location) {}
@Override
public void onSetWorldClocks(ArrayList<? extends WorldClock> clocks) {}
@Override
public void onPowerOff() {}
@Override
public void onSetPhoneVolume(final float volume) {}
@Override
public void onSetReminders(ArrayList<? extends Reminder> reminders) {}
}

View File

@ -0,0 +1,47 @@
/* Copyright (C) 2015-2021 Andreas Böhler, Andreas Shimokawa, Carsten
Pfeiffer, Daniele Gobbetti
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public abstract class AbstractTransaction {
private final String mName;
private final long creationTimestamp = System.currentTimeMillis();
public AbstractTransaction(String taskName) {
this.mName = taskName;
}
public String getTaskName() {
return mName;
}
protected String getCreationTime() {
return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date(creationTimestamp));
}
public abstract int getActionCount();
@Override
public String toString() {
return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), getActionCount());
}
}

View File

@ -0,0 +1,64 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer, Uwe Hermann
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import android.bluetooth.BluetoothSocket;
import java.util.Date;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
/**
* This allows performing one socket request at a time.
* As they are asynchronous anyway, we encapsulate every socket request (only write)
* inside a runnable action.
* <p/>
* These actions are then executed one after another, ensuring that every action's result
* has been posted before invoking the next action.
* <p/>
* As there is only write action, this class will be needed for later usage.
*/
public abstract class BtBRAction {
private final long creationTimestamp;
public BtBRAction() {
creationTimestamp = System.currentTimeMillis();
}
/**
* Returns true if this action expects an (async) result which must
* be waited for, before continuing with other actions.
* <p/>
*/
public abstract boolean expectsResult();
/**
* Executes this action, e.g. reads or write a Socket characteristic.
*
* @param socket the characteristic to manipulate, or null if none.
* @return true if the action was successful, false otherwise
*/
public abstract boolean run(BluetoothSocket socket);
protected String getCreationTime() {
return DateTimeUtils.formatDateTime(new Date(creationTimestamp));
}
public String toString() {
return getCreationTime() + ": " + getClass().getSimpleName();
}
}

View File

@ -0,0 +1,250 @@
/* Copyright (C) 2022 Damien Gaignon
*
* This file is part of Gadgetbridge.
*
* Gadgetbridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gadgetbridge is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.ParcelUuid;
import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public final class BtBRQueue {
private static final Logger LOG = LoggerFactory.getLogger(BtBRQueue.class);
private BluetoothAdapter mBtAdapter = null;
private BluetoothSocket mBtSocket = null;
private GBDevice mGbDevice;
private SocketCallback mCallback;
private UUID mService;
private final BlockingQueue<AbstractTransaction> mTransactions = new LinkedBlockingQueue<>();
private volatile boolean mDisposed;
private volatile boolean mCrashed;
private Context mContext;
private CountDownLatch mConnectionLatch;
private CountDownLatch mAvailableData;
private Thread writeThread = new Thread("Gadgetbridge IO writeThread") {
@Override
public void run() {
LOG.debug("Socket Write Thread started.");
while (!mDisposed && !mCrashed) {
try {
AbstractTransaction qTransaction = mTransactions.take();
if (!isConnected()) {
LOG.debug("Not connected, waiting for connection...");
setDeviceConnectionState(GBDevice.State.NOT_CONNECTED);
// wait until the connection succeeds before running the actions
// Note that no automatic connection is performed. This has to be triggered
// on the outside typically by the DeviceSupport. The reason is that
// devices have different kinds of initializations and this class has no
// idea about them.
mConnectionLatch = new CountDownLatch(1);
mConnectionLatch.await();
mConnectionLatch = null;
}
LOG.info("Ready for a new message exchange.");
Transaction transaction = (Transaction)qTransaction;
for (BtBRAction action : transaction.getActions()) {
if (LOG.isDebugEnabled()) {
LOG.debug("About to run action: " + action);
}
if (action.run(mBtSocket)) {
LOG.debug("Action ok: " + action);
} else {
LOG.error("Action returned false: " + action);
break;
}
}
} catch (InterruptedException ignored) {
mConnectionLatch = null;
LOG.debug("Thread interrupted");
} catch (Throwable ex) {
LOG.error("IO Write Thread died: " + ex.getMessage(), ex);
mCrashed = true;
mConnectionLatch = null;
}
}
}
};
private Thread readThread = new Thread("Gadgetbridge IO readThread") {
@Override
public void run() {
LOG.debug("Queue Read Thread started.");
while (!mDisposed && !mCrashed) {
try {
if (!isConnected()) {
LOG.debug("not connected, waiting for connection...");
// wait until the connection succeeds before running the actions
// Note that no automatic connection is performed. This has to be triggered
// on the outside typically by the DeviceSupport. The reason is that
// devices have different kinds of initializations and this class has no
// idea about them.
mConnectionLatch = new CountDownLatch(1);
mConnectionLatch.await();
mConnectionLatch = null;
}
if (mAvailableData != null) {
if (mBtSocket.getInputStream().available() == 0) {
mAvailableData.countDown();
}
}
byte[] data = new byte[1024];
int len = mBtSocket.getInputStream().read(data);
LOG.debug("Received data: " + StringUtils.bytesToHex(data));
mCallback.onSocketRead(Arrays.copyOf(data, len));
} catch (InterruptedException ignored) {
mConnectionLatch = null;
LOG.debug("Thread interrupted");
} catch (Throwable ex) {
LOG.error("IO Read Thread died: " + ex.getMessage(), ex);
mCrashed = true;
mConnectionLatch = null;
}
}
}
};
public BtBRQueue(BluetoothAdapter btAdapter, GBDevice gbDevice, Context context, SocketCallback socketCallback, UUID supportedService) {
mBtAdapter = btAdapter;
mGbDevice = gbDevice;
mContext = context;
mCallback = socketCallback;
mService = supportedService;
writeThread.start();
readThread.start();
}
/**
* Connects to the given remote device. Note that this does not perform any device
* specific initialization. This should be done in the specific {@link DeviceSupport}
* class.
*
* @return <code>true</code> whether the connection attempt was successfully triggered and <code>false</code> if that failed or if there is already a connection
*/
protected boolean connect() {
if (isConnected()) {
LOG.warn("Ignoring connect() because already connected.");
return false;
}
LOG.info("Attemping to connect to " + mGbDevice.getName());
GBDevice.State originalState = mGbDevice.getState();
setDeviceConnectionState(GBDevice.State.CONNECTING);
try {
BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(mGbDevice.getAddress());
// UUID should be in a BluetoothSocket class and not in BluetoothSocketCharacteristic
mBtSocket = btDevice.createRfcommSocketToServiceRecord(mService);
mBtSocket.connect();
if (mBtSocket.isConnected()) {
setDeviceConnectionState(GBDevice.State.CONNECTED);
} else {
LOG.debug("Connection not established");
}
if (mConnectionLatch != null) {
mConnectionLatch.countDown();
}
} catch (IOException e) {
LOG.error("Server socket cannot be started.", e);
setDeviceConnectionState(originalState);
mBtSocket = null;
return false;
}
onConnectionEstablished();
return true;
}
protected void onConnectionEstablished() {
mCallback.onConnectionEstablished();
}
public void disconnect() {
if (mBtSocket != null) {
try {
mAvailableData = new CountDownLatch(1);
mAvailableData.await();
mAvailableData = null;
mBtSocket.close();
} catch (IOException e) {
LOG.error(e.getMessage());
} catch (InterruptedException e) {
LOG.error(e.getMessage());
}
}
}
protected boolean isConnected() {
return mGbDevice.isConnected();
}
/**
* Adds a transaction to the end of the queue.
*
* @param transaction
*/
public void add(Transaction transaction) {
LOG.debug("about to add: " + transaction);
if (!transaction.isEmpty()) {
mTransactions.add(transaction);
}
}
protected void setDeviceConnectionState(GBDevice.State newState) {
LOG.debug("New device connection state: " + newState);
mGbDevice.setState(newState);
mGbDevice.sendDeviceUpdateIntent(mContext, GBDevice.DeviceUpdateSubject.DEVICE_STATE);
}
public void dispose() {
if (mDisposed) {
return;
}
mDisposed = true;
disconnect();
writeThread.interrupt();
writeThread = null;
readThread.interrupt();
readThread = null;
}
}

View File

@ -0,0 +1,35 @@
/** Copyright (C) 2022 Damien Gaignon
*
* This file is part of Gadgetbridge.
*
* Gadgetbridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Gadgetbridge is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
/**
* Callback interface handling io events of a BluetoothSocket.
* It is the counterpart of GattCallback interface designed for GB.
*/
public interface SocketCallback {
void onConnectionEstablished();
/**
* Read data from InputStream of BluetoothSocket
*
* @param data
*/
void onSocketRead(byte[] data);
}

View File

@ -0,0 +1,71 @@
/* Copyright (C) 2015-2021 Andreas Böhler, Andreas Shimokawa, Carsten
Pfeiffer, Daniele Gobbetti
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import androidx.annotation.Nullable;
/**
* Groups a bunch of {@link BtBRAction actions} together, making sure
* that upon failure of one action, all subsequent actions are discarded.
*
* @author TREND
*/
public class Transaction extends AbstractTransaction {
private final List<BtBRAction> mActions = new ArrayList<>(4);
private
@Nullable
SocketCallback socketCallback;
public Transaction(String taskName) {
super(taskName);
}
public void add(BtBRAction action) {
mActions.add(action);
}
public List<BtBRAction> getActions() {
return Collections.unmodifiableList(mActions);
}
public boolean isEmpty() {
return mActions.isEmpty();
}
public void setCallback(@Nullable SocketCallback callback) {
socketCallback = callback;
}
/**
* Returns the GattCallback for this transaction, or null if none.
*/
public
@Nullable
SocketCallback getSocketCallback() {
return socketCallback;
}
@Override
public int getActionCount() {
return mActions.size();
}
}

View File

@ -0,0 +1,89 @@
/* Copyright (C) 2022 Damien Gaignon
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr;
import android.os.Build;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.WaitAction;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.WriteAction;
public class TransactionBuilder {
private static final Logger LOG = LoggerFactory.getLogger(TransactionBuilder.class);
private final Transaction mTransaction;
private boolean mQueued;
public TransactionBuilder(String taskName) {
mTransaction = new Transaction(taskName);
}
public TransactionBuilder write(byte[] data) {
WriteAction action = new WriteAction(data);
return add(action);
}
/**
* Causes the queue to sleep for the specified time.
* Note that this is usually a bad idea, since it will not be able to process messages
* during that time. It is also likely to cause race conditions.
* @param millis the number of milliseconds to sleep
*/
public TransactionBuilder wait(int millis) {
WaitAction action = new WaitAction(millis);
return add(action);
}
public TransactionBuilder add(BtBRAction action) {
mTransaction.add(action);
return this;
}
/**
* Sets a SocketCallback instance that will be called when the transaction is executed,
* resulting in SocketCallback events.
*
* @param callback the callback to set, may be null
*/
public void setCallback(@Nullable SocketCallback callback) {
mTransaction.setCallback(callback);
}
/**
* To be used as the final step to execute the transaction by the given queue.
*
* @param queue
*/
public void queue(BtBRQueue queue) {
if (mQueued) {
throw new IllegalStateException("This builder had already been queued. You must not reuse it.");
}
mQueued = true;
queue.add(mTransaction);
}
public Transaction getTransaction() {
return mTransaction;
}
}

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.bluetooth.BluetoothSocket;
/**
* A special action that checks for an abort-condition, and if met, the currently
* executing transaction will be aborted by returning false.
*/
public abstract class AbortTransactionAction extends PlainAction {
private static final Logger LOG = LoggerFactory.getLogger(AbortTransactionAction.class);
public AbortTransactionAction() {
}
@Override
public boolean run(BluetoothSocket socket) {
if (shouldAbort()) {
LOG.info("Aborting transaction because abort criteria met.");
return false;
}
return true;
}
protected abstract boolean shouldAbort();
@Override
public String toString() {
return getCreationTime() + ": " + getClass().getSimpleName() + ": aborting? " + shouldAbort();
}
}

View File

@ -0,0 +1,46 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
/**
* A special action that is executed at the very front of the initialization
* sequence (transaction). It will abort the entire initialization sequence
* by returning false, when the device is already initialized.
*/
public class CheckInitializedAction extends AbortTransactionAction {
private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
private final GBDevice device;
public CheckInitializedAction(GBDevice gbDevice) {
device = gbDevice;
}
@Override
protected boolean shouldAbort() {
boolean abort = device.isInitialized();
if (abort) {
LOG.info("Aborting device initialization, because already initialized: " + device);
}
return abort;
}
}

View File

@ -0,0 +1,39 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.BtBRAction;
/**
* An abstract non-BTBR action. It performs no bluetooth operation,
* does not have a BluetoothSocketCharacteristic instance and expects no result.
*/
public abstract class PlainAction extends BtBRAction {
public PlainAction() {
}
@Override
public boolean expectsResult() {
return false;
}
@Override
public String toString() {
return getCreationTime() + ": " + getClass().getSimpleName();
}
}

View File

@ -0,0 +1,53 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class SetDeviceBusyAction extends PlainAction {
private final GBDevice device;
private final Context context;
private final String busyTask;
/**
* When run, will mark the device as busy (or not busy).
*
* @param device the device to mark
* @param busyTask the task name to set as busy task, or null to mark as not busy
* @param context
*/
public SetDeviceBusyAction(GBDevice device, String busyTask, Context context) {
this.device = device;
this.busyTask = busyTask;
this.context = context;
}
@Override
public boolean run(BluetoothSocket socket) {
device.setBusyTask(busyTask);
device.sendDeviceUpdateIntent(context);
return true;
}
@Override
public String toString() {
return getCreationTime() + ": " + getClass().getName() + ": " + busyTask;
}
}

View File

@ -0,0 +1,53 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import androidx.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class SetDeviceStateAction extends PlainAction {
private final GBDevice device;
private final GBDevice.State deviceState;
private final Context context;
public SetDeviceStateAction(GBDevice device, GBDevice.State deviceState, Context context) {
this.device = device;
this.deviceState = deviceState;
this.context = context;
}
@Override
public boolean run(BluetoothSocket socket) {
device.setState(deviceState);
device.sendDeviceUpdateIntent(getContext(), GBDevice.DeviceUpdateSubject.DEVICE_STATE);
return true;
}
public Context getContext() {
return context;
}
@NonNull
@Override
public String toString() {
return super.toString() + " to " + deviceState;
}
}

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import android.bluetooth.BluetoothSocket;
/**
* An action that will cause the queue to sleep for the specified time.
* Note that this is usually a bad idea, since it will not be able to process messages
* during that time. It is also likely to cause race conditions.
*/
public class WaitAction extends PlainAction {
private final int mMillis;
public WaitAction(int millis) {
mMillis = millis;
}
@Override
public boolean run(BluetoothSocket socket) {
try {
Thread.sleep(mMillis);
return true;
} catch (InterruptedException e) {
return false;
}
}
}

View File

@ -0,0 +1,83 @@
/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer, Daniele
Gobbetti, Uwe Hermann
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
import android.bluetooth.BluetoothSocket;
import java.io.IOException;
import java.io.OutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.BtBRAction;
/**
* Invokes a write operation on a given socket.
* The result status will be made available asynchronously through the
* {@link SocketCallback}
*/
public class WriteAction extends BtBRAction {
private static final Logger LOG = LoggerFactory.getLogger(WriteAction.class);
private final byte[] value;
private OutputStream mOutputStream = null;
public WriteAction(byte[] value) {
this.value = value;
}
@Override
public boolean run(BluetoothSocket socket) {
try {
mOutputStream = socket.getOutputStream();
if (mOutputStream == null) {
LOG.error("mOutStream is null");
return false;
}
return writeValue(value);
} catch (IOException e) {
LOG.error("Can not get the output stream");
}
return false;
}
protected boolean writeValue(byte[] value) {
if (LOG.isDebugEnabled()) {
LOG.debug("writing to socket: " + Logging.formatBytes(value));
}
try {
mOutputStream.write(value);
mOutputStream.flush();
return true;
} catch (IOException e) {
LOG.error("Error writing to socket: ", e);
}
return false;
}
protected final byte[] getValue() {
return value;
}
@Override
public boolean expectsResult() {
return true;
}
}

View File

@ -105,13 +105,13 @@ public abstract class AbstractBTLEOperation<T extends AbstractBTLEDeviceSupport>
*/
public TransactionBuilder performInitialized(String taskName) throws IOException {
TransactionBuilder builder = mSupport.performInitialized(taskName);
builder.setGattCallback(this);
builder.setCallback(this);
return builder;
}
public TransactionBuilder createTransactionBuilder(String taskName) {
TransactionBuilder builder = getSupport().createTransactionBuilder(taskName);
builder.setGattCallback(this);
builder.setCallback(this);
return builder;
}

View File

@ -57,7 +57,7 @@ public class ServerTransaction extends AbstractTransaction {
return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), mActions.size());
}
public void setGattCallback(@Nullable GattServerCallback callback) {
public void setCallback(@Nullable GattServerCallback callback) {
gattCallback = callback;
}

View File

@ -54,8 +54,8 @@ public class ServerTransactionBuilder {
*
* @param callback the callback to set, may be null
*/
public void setGattCallback(@Nullable GattServerCallback callback) {
mTransaction.setGattCallback(callback);
public void setCallback(@Nullable GattServerCallback callback) {
mTransaction.setCallback(callback);
}
public

View File

@ -54,7 +54,7 @@ public class Transaction extends AbstractTransaction {
return mActions.isEmpty();
}
public void setGattCallback(@Nullable GattCallback callback) {
public void setCallback(@Nullable GattCallback callback) {
gattCallback = callback;
modifyGattCallback = true;
}

View File

@ -108,8 +108,8 @@ public class TransactionBuilder {
*
* @param callback the callback to set, may be null
*/
public void setGattCallback(@Nullable GattCallback callback) {
mTransaction.setGattCallback(callback);
public void setCallback(@Nullable GattCallback callback) {
mTransaction.setCallback(callback);
}
public

View File

@ -88,7 +88,7 @@ public abstract class AbstractBleProfile<T extends AbstractBTLEDeviceSupport> ex
*/
public TransactionBuilder performInitialized(String taskName) throws IOException {
TransactionBuilder builder = mSupport.performInitialized(taskName);
builder.setGattCallback(this);
builder.setCallback(this);
return builder;
}

View File

@ -313,7 +313,7 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
rxCharacteristic = getCharacteristic(BangleJSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX);
txCharacteristic = getCharacteristic(BangleJSConstants.UUID_CHARACTERISTIC_NORDIC_UART_TX);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(rxCharacteristic, true);
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));

View File

@ -171,7 +171,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
getDevice().setFirmwareVersion2("N/A");
builder.setGattCallback(this);
builder.setCallback(this);
configureWatch(builder);

View File

@ -51,7 +51,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
private void enableRequiredNotifications(boolean enable) {
try {
TransactionBuilder builder = performInitialized("enableRequiredNotifications");
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), enable);
builder.notify(getCharacteristic(CasioConstants.CASIO_CONVOY_CHARACTERISTIC_UUID), enable);
builder.queue(getQueue());
@ -65,7 +65,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
try {
TransactionBuilder builder = performInitialized("requestStepCountDate");
builder.setGattCallback(this);
builder.setCallback(this);
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
builder.queue(getQueue());
} catch(IOException e) {
@ -78,7 +78,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
try {
TransactionBuilder builder = performInitialized("writeStepCountAck");
builder.setGattCallback(this);
builder.setCallback(this);
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
builder.queue(getQueue());
} catch(IOException e) {
@ -110,7 +110,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX
if (getDevice() != null) {
try {
TransactionBuilder builder = performInitialized("finished operation");
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.wait(0);
builder.queue(getQueue());
} catch (IOException ex) {

View File

@ -61,7 +61,7 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
byte[] command = new byte[1];
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_USER_PROFILE");
TransactionBuilder builder = performInitialized("getConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, command);
builder.queue(getQueue());
}
@ -74,7 +74,7 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
try {
TransactionBuilder builder = performInitialized("finished operation");
builder.wait(0);
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.queue(getQueue());
} catch (IOException ex) {
LOG.info("Error resetting Gatt callback: " + ex.getMessage());
@ -88,7 +88,7 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC");
try {
TransactionBuilder builder = performInitialized("getConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, command);
builder.queue(getQueue());
} catch(IOException e) {

View File

@ -42,14 +42,14 @@ public class InitOperationGB6900 extends AbstractBTLEOperation<CasioGB6900Device
public InitOperationGB6900(CasioGB6900DeviceSupport support, TransactionBuilder builder) {
super(support);
this.builder = builder;
builder.setGattCallback(this);
builder.setCallback(this);
}
@Override
protected void doPerform() throws IOException {
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
TransactionBuilder builder = getSupport().createTransactionBuilder("readBleSettings");
builder.setGattCallback(this);
builder.setCallback(this);
builder.read(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID));
getSupport().performImmediately(builder);
}
@ -84,7 +84,7 @@ public class InitOperationGB6900 extends AbstractBTLEOperation<CasioGB6900Device
private void writeBleSettings() {
try {
TransactionBuilder builder = getSupport().createTransactionBuilder("writeBleInit");
builder.setGattCallback(this);
builder.setCallback(this);
builder.write(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_BLE_CHARACTERISTIC_UUID), mBleSettings);
getSupport().performImmediately(builder);
} catch(IOException e) {

View File

@ -48,13 +48,13 @@ public class InitOperationGBX100 extends AbstractBTLEOperation<CasioGBX100Device
this.support = support;
this.mFirstConnect = firstConnect;
LOG.info("mFirstConnect: " + mFirstConnect);
builder.setGattCallback(this);
builder.setCallback(this);
}
private void writeAllFeaturesRequest(byte[] arr) {
try {
TransactionBuilder builder = createTransactionBuilder("writeAllFeaturesRequest");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, arr);
support.performImmediately(builder);
} catch(IOException e) {
@ -65,7 +65,7 @@ public class InitOperationGBX100 extends AbstractBTLEOperation<CasioGBX100Device
private void writeAllFeatures(byte[] arr) {
try {
TransactionBuilder builder = createTransactionBuilder("writeAllFeatures");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeatures(builder, arr);
support.performImmediately(builder);
} catch(IOException e) {
@ -252,7 +252,7 @@ public class InitOperationGBX100 extends AbstractBTLEOperation<CasioGBX100Device
private void enableAllFeatures(boolean enable) {
try {
TransactionBuilder builder = createTransactionBuilder("notifyAllFeatures");
builder.setGattCallback(this);
builder.setCallback(this);
enableAllFeatures(builder, enable);
support.performImmediately(builder);
} catch(IOException e) {

View File

@ -52,7 +52,7 @@ public class SetAlarmOperation extends AbstractBTLEOperation<CasioGB6900DeviceSu
if (getDevice() != null) {
try {
TransactionBuilder builder = performInitialized("getSettingForAlarm");
builder.setGattCallback(this);
builder.setCallback(this);
builder.read(getCharacteristic(CasioConstants.CASIO_SETTING_FOR_ALM_CHARACTERISTIC_UUID));
builder.queue(getQueue());
} catch (IOException ex) {
@ -74,7 +74,7 @@ public class SetAlarmOperation extends AbstractBTLEOperation<CasioGB6900DeviceSu
try {
TransactionBuilder builder = performInitialized("finished operation");
builder.wait(0);
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.queue(getQueue());
} catch (IOException ex) {
LOG.info("Error resetting Gatt callback: " + ex.getMessage());

View File

@ -67,7 +67,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
byte[] command = new byte[1];
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_USER_PROFILE");
TransactionBuilder builder = performInitialized("getConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, command);
builder.queue(getQueue());
}
@ -150,7 +150,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
// Target settings will be requested in write callback
try {
TransactionBuilder builder = performInitialized("setConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeatures(builder, data);
builder.queue(getQueue());
} catch (IOException e) {
@ -191,7 +191,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
// Basic settings will be requested in Gatt callback
try {
TransactionBuilder builder = performInitialized("setConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeatures(builder, data);
builder.queue(getQueue());
} catch (IOException e) {
@ -239,7 +239,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
// Operation will be finished in Gatt callback
try {
TransactionBuilder builder = performInitialized("setConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeatures(builder, data);
builder.queue(getQueue());
} catch (IOException e) {
@ -263,7 +263,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
if (getDevice() != null) {
try {
TransactionBuilder builder = performInitialized("finished operation");
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.wait(0);
builder.queue(getQueue());
} catch (IOException ex) {
@ -277,7 +277,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC");
try {
TransactionBuilder builder = performInitialized("getConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, command);
builder.queue(getQueue());
} catch(IOException e) {
@ -290,7 +290,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_TARGET_VALUE");
try {
TransactionBuilder builder = performInitialized("getConfiguration");
builder.setGattCallback(this);
builder.setCallback(this);
support.writeAllFeaturesRequest(builder, command);
builder.queue(getQueue());
} catch(IOException e) {

View File

@ -204,7 +204,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport {
builder.notify(getCharacteristic(UUID_CHARACTERISTIC_RX), true);
builder.notify(getCharacteristic(GattService.UUID_SERVICE_BATTERY_SERVICE), true);
builder.setGattCallback(this);
builder.setCallback(this);
deviceInfoProfile.requestDeviceInfo(builder);
batteryInfoProfile.requestBatteryInfo(builder);

View File

@ -100,7 +100,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
builder.notify(getCharacteristic(HPlusConstants.UUID_CHARACTERISTIC_MEASURE), true);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(measureCharacteristic, true);
//Initialize device
sendUserInfo(builder); //Sync preferences

View File

@ -61,7 +61,7 @@ public class InitOperation extends AbstractBTLEOperation<HuamiSupport> {
this.authFlags = authFlags;
this.cryptFlags = cryptFlags;
this.builder = builder;
builder.setGattCallback(this);
builder.setCallback(this);
}
@Override

View File

@ -62,7 +62,7 @@ public abstract class AbstractID115Operation extends AbstractBTLEOperation<ID115
try {
TransactionBuilder builder = performInitialized("reenabling disabled notifications");
enableNotifications(builder, false);
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.queue(getQueue());
} catch (IOException ex) {
GB.toast(getContext(), "Error enabling ID115 notifications, you may need to connect and disconnect", Toast.LENGTH_LONG, GB.ERROR, ex);

View File

@ -114,7 +114,7 @@ public class BFH16DeviceSupport extends AbstractBTLEDeviceSupport {
measureCharacteristic = getCharacteristic(BFH16Constants.BFH16_SERVICE1_NOTIFY);
ctrlCharacteristic = getCharacteristic(BFH16Constants.BFH16_SERVICE1_WRITE);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(measureCharacteristic, true);
syncSettings(builder);

View File

@ -76,7 +76,7 @@ public class JYouSupport extends AbstractBTLEDeviceSupport {
BluetoothGattCharacteristic measureCharacteristic = getCharacteristic(JYouConstants.UUID_CHARACTERISTIC_MEASURE);
ctrlCharacteristic = getCharacteristic(JYouConstants.UUID_CHARACTERISTIC_CONTROL);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(measureCharacteristic, true);
syncSettings(builder);

View File

@ -127,7 +127,7 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
builder.setGattCallback(this);
builder.setCallback(this);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
// Enable notification

View File

@ -63,7 +63,7 @@ public abstract class MultiFetchRequest extends Request {
try {
super.operationFinished();
TransactionBuilder builder = performInitialized("Finishing operation");
builder.setGattCallback(null);
builder.setCallback(null);
builder.queue(getQueue());
} catch (IOException e) {
GB.toast(getContext(), "Failed to reset callback", Toast.LENGTH_SHORT,

View File

@ -49,7 +49,7 @@ public class InitOperation extends AbstractBTLEOperation<WatchXPlusDeviceSupport
super(support);
this.needsAuth = needsAuth;
this.builder = builder;
builder.setGattCallback(this);
builder.setCallback(this);
}
@Override
@ -72,7 +72,7 @@ public class InitOperation extends AbstractBTLEOperation<WatchXPlusDeviceSupport
getSupport().logMessageContent(value);
if (ArrayUtils.equals(value, Watch9Constants.RESP_AUTHORIZATION_TASK, 5) && value[8] == 0x01) {
TransactionBuilder builder = getSupport().createTransactionBuilder("authInit");
builder.setGattCallback(this);
builder.setCallback(this);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
getSupport().initialize(builder).performImmediately(builder);
} else {

View File

@ -551,7 +551,7 @@ public class WatchXPlusDeviceSupport extends AbstractBTLEDeviceSupport {
.checkInitTime(builder)
.syncPreferences(builder); // read preferences from app and set them to watch
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
builder.setGattCallback(this);
builder.setCallback(this);
return this;
}

View File

@ -498,7 +498,7 @@ public class MakibesHR3DeviceSupport extends AbstractBTLEDeviceSupport implement
this.mReportCharacteristic = getCharacteristic(MakibesHR3Constants.UUID_CHARACTERISTIC_REPORT);
builder.notify(this.mReportCharacteristic, true);
builder.setGattCallback(this);
builder.setCallback(this);
// Allow modifications

View File

@ -48,7 +48,7 @@ public abstract class AbstractMiBandOperation<T extends AbstractBTLEDeviceSuppor
try {
TransactionBuilder builder = performInitialized("reenabling disabled notifications");
handleFinished(builder);
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
builder.setCallback(null); // unset ourselves from being the queue's gatt callback
builder.queue(getQueue());
} catch (IOException ex) {
GB.toast(getContext(), "Error enabling Mi Band notifications, you may need to connect and disconnect", Toast.LENGTH_LONG, GB.ERROR, ex);

View File

@ -91,7 +91,7 @@ public class MiScale2DeviceSupport extends AbstractBTLEDeviceSupport {
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
// Weight and body composition
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_BODY_COMPOSITION_MEASUREMENT), true);
return builder;

View File

@ -88,7 +88,7 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
measureCharacteristic = getCharacteristic(No1F1Constants.UUID_CHARACTERISTIC_MEASURE);
ctrlCharacteristic = getCharacteristic(No1F1Constants.UUID_CHARACTERISTIC_CONTROL);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(measureCharacteristic, true);
setTime(builder);

View File

@ -50,7 +50,7 @@ public class SuperCarsSupport extends AbstractBTLEDeviceSupport {
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
builder.notify(getCharacteristic(SuperCarsConstants.CHARACTERISTIC_UUID_FFF4), true); //for battery
builder.setGattCallback(this);
builder.setCallback(this);
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext());
IntentFilter filter = new IntentFilter();

View File

@ -94,7 +94,7 @@ public class TLW64Support extends AbstractBTLEDeviceSupport {
ctrlCharacteristic = getCharacteristic(TLW64Constants.UUID_CHARACTERISTIC_CONTROL);
notifyCharacteristic = getCharacteristic(TLW64Constants.UUID_CHARACTERISTIC_NOTIFY);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(notifyCharacteristic, true);
setTime(builder);

View File

@ -80,7 +80,7 @@ public class WaspOSDeviceSupport extends AbstractBTLEDeviceSupport {
rxCharacteristic = getCharacteristic(WaspOSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX);
txCharacteristic = getCharacteristic(WaspOSConstants.UUID_CHARACTERISTIC_NORDIC_UART_TX);
builder.setGattCallback(this);
builder.setCallback(this);
builder.notify(rxCharacteristic, true);
uartTx(builder, " \u0003"); // clear active line

View File

@ -314,7 +314,7 @@ public class Watch9DeviceSupport extends AbstractBTLEDeviceSupport {
.enableDoNotDisturb(builder, false)
.setFitnessGoal(builder);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
builder.setGattCallback(this);
builder.setCallback(this);
return this;
}

View File

@ -47,7 +47,7 @@ public class InitOperation extends AbstractBTLEOperation<Watch9DeviceSupport>{
super(support);
this.needsAuth = needsAuth;
this.builder = builder;
builder.setGattCallback(this);
builder.setCallback(this);
}
@Override
@ -73,7 +73,7 @@ public class InitOperation extends AbstractBTLEOperation<Watch9DeviceSupport>{
getSupport().logMessageContent(value);
if (ArrayUtils.equals(value, Watch9Constants.RESP_AUTHORIZATION_TASK, 5) && value[8] == 0x01) {
TransactionBuilder builder = getSupport().createTransactionBuilder("authInit");
builder.setGattCallback(this);
builder.setCallback(this);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
getSupport().initialize(builder).performImmediately(builder);
} else {