1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 12:56:49 +01:00

Lefun: Add comments

This commit is contained in:
Yukai Li 2020-10-05 15:08:11 -06:00 committed by Gitea
parent 6974a86b87
commit 1242009b55
8 changed files with 372 additions and 40 deletions

View File

@ -22,6 +22,9 @@ import java.util.UUID;
import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport.BASE_UUID;
/**
* Constants used with Lefun device support
*/
public class LefunConstants {
// BLE UUIDs
public static final UUID UUID_SERVICE_LEFUN = UUID.fromString(String.format(BASE_UUID, "18D0"));
@ -31,16 +34,12 @@ public class LefunConstants {
// Coordinator constants
public static final String ADVERTISEMENT_NAME = "Lefun";
public static final String MANUFACTURER_NAME = "Teng Jin Da";
public static int NUM_ALARM_SLOTS = 5;
// Commands
public static final byte CMD_REQUEST_ID = (byte)0xab;
public static final byte CMD_REQUEST_ID = (byte) 0xab;
public static final byte CMD_RESPONSE_ID = 0x5a;
public static final int CMD_MAX_LENGTH = 20;
// 3 header bytes plus checksum
public static final int CMD_HEADER_LENGTH = 4;
public static final byte CMD_FIRMWARE_INFO = 0x00;
public static final byte CMD_BONDING_REQUEST = 0x01;
public static final byte CMD_SETTINGS = 0x02;
@ -67,25 +66,23 @@ public class LefunConstants {
public static final byte CMD_LANGUAGE = 0x21;
public static final byte CMD_UNKNOWN_22 = 0x22;
public static final byte CMD_UNKNOWN_25 = 0x25;
public static final byte CMD_UNKNOWN_80 = (byte)0x80;
public static final byte CMD_UNKNOWN_80 = (byte) 0x80;
public static final int PPG_TYPE_INVALID = -1;
public static final int PPG_TYPE_HEART_RATE = 0;
public static final int PPG_TYPE_BLOOD_PRESSURE = 1;
public static final int PPG_TYPE_BLOOD_OXYGEN = 2;
public static final int PPG_TYPE_COUNT = 3;
// DB activity kinds
public static final int DB_ACTIVITY_KIND_UNKNOWN = 0;
public static final int DB_ACTIVITY_KIND_ACTIVITY = 1;
public static final int DB_ACTIVITY_KIND_HEART_RATE = 2;
public static final int DB_ACTIVITY_KIND_LIGHT_SLEEP = 3;
public static final int DB_ACTIVITY_KIND_DEEP_SLEEP = 4;
// Pseudo-intensity
public static final int INTENSITY_MIN = 0;
public static final int INTENSITY_DEEP_SLEEP = 1;
public static final int INTENSITY_LIGHT_SLEEP = 2;
public static final int INTENSITY_AWAKE = 3;
public static final int INTENSITY_MAX = 4;
public static int NUM_ALARM_SLOTS = 5;
}

View File

@ -41,6 +41,9 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants.
import static nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants.MANUFACTURER_NAME;
import static nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants.NUM_ALARM_SLOTS;
/**
* Device coordinator for Lefun band
*/
public class LefunDeviceCoordinator extends AbstractDeviceCoordinator {
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {

View File

@ -18,6 +18,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.lefun;
/**
* Feature support utilities for Lefun devices
*/
public class LefunFeatureSupport {
public static final int SUPPORT_HEART_RATE = 1 << 2;
public static final int SUPPORT_BLOOD_PRESSURE = 1 << 3;
@ -31,10 +34,27 @@ public class LefunFeatureSupport {
public static final int RESERVE_WALLPAPER = 1 << 6;
public static final int RESERVE_REMOTE_CAMERA = 1 << 7;
/**
* Checks whether a feature is supported
*
* @param deviceSupport the feature flags from the device
* @param featureSupport the feature you want to check
* @return whether feature is supported
*/
public static boolean checkSupported(short deviceSupport, int featureSupport) {
return (deviceSupport & featureSupport) == featureSupport;
}
/**
* Checks whether a feature is not reserved
* <p>
* Reserve flags indicate a feature is not available if set. This function takes care of the
* inverting for you, so if you get true, the feature is available.
*
* @param deviceReserve the reserve flags from the device
* @param featureReserve the reserve flag you want to check
* @return whether feature is supported
*/
public static boolean checkNotReserved(short deviceReserve, int featureReserve) {
return !((deviceReserve & featureReserve) == featureReserve);
}

View File

@ -24,14 +24,15 @@ import androidx.annotation.Nullable;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.LefunActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.LefunActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
/**
* Sample provider for Lefun devices
*/
public class LefunSampleProvider extends AbstractSampleProvider<LefunActivitySample> {
public LefunSampleProvider(GBDevice device, DaoSession session) {
super(device, session);
@ -91,7 +92,7 @@ public class LefunSampleProvider extends AbstractSampleProvider<LefunActivitySam
@Override
public float normalizeIntensity(int rawIntensity) {
return rawIntensity / (float)LefunConstants.INTENSITY_MAX;
return rawIntensity / (float) LefunConstants.INTENSITY_MAX;
}
@Override

View File

@ -23,32 +23,28 @@ import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.devices.lefun.LefunConstants;
/**
* Base class for Lefun Bluetooth commands and responses
*/
public abstract class BaseCommand {
// Common constants
/**
* Common get operation type
*/
public static final byte OP_GET = 0;
/**
* Common set operation type
*/
public static final byte OP_SET = 1;
abstract protected void deserializeParams(byte id, ByteBuffer params);
abstract protected byte serializeParams(ByteBuffer params);
public void deserialize(byte[] response) {
if (response.length < LefunConstants.CMD_HEADER_LENGTH || response.length < response[1])
throw new IllegalArgumentException("Response is too short");
if (calculateChecksum(response, 0, response[1] - 1) != response[response[1] - 1])
throw new IllegalArgumentException("Incorrect message checksum");
ByteBuffer buffer = ByteBuffer.wrap(response, LefunConstants.CMD_HEADER_LENGTH - 1,
response[1] - LefunConstants.CMD_HEADER_LENGTH);
buffer.order(ByteOrder.BIG_ENDIAN);
deserializeParams(response[2], buffer);
}
public byte[] serialize() {
ByteBuffer buffer = ByteBuffer.allocate(LefunConstants.CMD_MAX_LENGTH - LefunConstants.CMD_HEADER_LENGTH);
buffer.order(ByteOrder.BIG_ENDIAN);
byte id = serializeParams(buffer);
return makeCommand(id, buffer);
}
/**
* Calculates command checksum
*
* @param data the data to generate checksum from
* @param offset the offset in data to start calculating from
* @param length the number of bytes to include in calculation
* @return the computed checksum
*/
public static byte calculateChecksum(byte[] data, int offset, int length) {
int checksum = 0;
for (int i = offset; i < offset + length; ++i) {
@ -62,7 +58,51 @@ public abstract class BaseCommand {
b >>= 1;
}
}
return (byte)checksum;
return (byte) checksum;
}
/**
* When implemented in a subclass, parses the response from a device
*
* @param id the command ID
* @param params the params buffer
*/
abstract protected void deserializeParams(byte id, ByteBuffer params);
/**
* When implemented in a subclass, provides the arguments to send in the command
*
* @param params the params buffer to write to
* @return the command ID
*/
abstract protected byte serializeParams(ByteBuffer params);
/**
* Deserialize a response from the device
*
* @param response the response data to deserialize
*/
public void deserialize(byte[] response) {
if (response.length < LefunConstants.CMD_HEADER_LENGTH || response.length < response[1])
throw new IllegalArgumentException("Response is too short");
if (calculateChecksum(response, 0, response[1] - 1) != response[response[1] - 1])
throw new IllegalArgumentException("Incorrect message checksum");
ByteBuffer buffer = ByteBuffer.wrap(response, LefunConstants.CMD_HEADER_LENGTH - 1,
response[1] - LefunConstants.CMD_HEADER_LENGTH);
buffer.order(ByteOrder.BIG_ENDIAN);
deserializeParams(response[2], buffer);
}
/**
* Serializes a command to send to the device
*
* @return the data to send to the device
*/
public byte[] serialize() {
ByteBuffer buffer = ByteBuffer.allocate(LefunConstants.CMD_MAX_LENGTH - LefunConstants.CMD_HEADER_LENGTH);
buffer.order(ByteOrder.BIG_ENDIAN);
byte id = serializeParams(buffer);
return makeCommand(id, buffer);
}
/**
@ -87,25 +127,57 @@ public abstract class BaseCommand {
return request;
}
/**
* Throws a standard parameters length exception
*/
protected void throwUnexpectedLength() {
throw new IllegalArgumentException("Unexpected parameters length");
}
/**
* Checks for valid command ID and throws if wrong ID provided
*
* @param id command ID from device
* @param expectedId expected command ID
*/
protected void validateId(byte id, byte expectedId) {
if (id != expectedId)
throw new IllegalArgumentException("Wrong command ID");
}
/**
* Checks for valid command ID and command length
*
* @param id command ID from device
* @param params params buffer from device
* @param expectedId expected command ID
* @param expectedLength expected params length
*/
protected void validateIdAndLength(byte id, ByteBuffer params, byte expectedId, int expectedLength) {
validateId(id, expectedId);
if (params.limit() - params.position() != expectedLength)
throwUnexpectedLength();
}
/**
* Gets whether a bit is set
*
* @param value the value to check against
* @param mask the bitmask
* @return whether the bits indicated by the bitmask are set
*/
protected boolean getBit(int value, int mask) {
return (value & mask) != 0;
}
/**
* Sets a bit in a value
*
* @param value the value to modify
* @param mask the bitmask
* @param set whether to set or clear the bits
* @return the modified value
*/
protected int setBit(int value, int mask, boolean set) {
if (set) {
return value | mask;
@ -114,26 +186,43 @@ public abstract class BaseCommand {
}
}
/**
* Sets a bit in a value
*
* @param value the value to modify
* @param mask the bitmask
* @param set whether to set or clear the bits
* @return the modified value
*/
protected short setBit(short value, int mask, boolean set) {
if (set) {
return (short)(value | mask);
return (short) (value | mask);
} else {
return (short)(value & ~mask);
return (short) (value & ~mask);
}
}
/**
* Sets a bit in a value
*
* @param value the value to modify
* @param mask the bitmask
* @param set whether to set or clear the bits
* @return the modified value
*/
protected byte setBit(byte value, int mask, boolean set) {
if (set) {
return (byte)(value | mask);
return (byte) (value | mask);
} else {
return (byte)(value & ~mask);
return (byte) (value & ~mask);
}
}
/**
* Find index of first bit that is set
* @param value
* @return
*
* @param value the value to look at
* @return the index of the lowest set bit, starting at 0 for least significant bit; -1 if no bits set
*/
protected int getLowestSetBitIndex(int value) {
if (value == 0) return -1;

View File

@ -102,6 +102,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.requests.Start
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
* Device support class for Lefun devices
*/
public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(LefunDeviceSupport.class);
@ -111,6 +114,9 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
private int lastStepsCount = -1;
private int lastStepsTimestamp;
/**
* Instantiates a new instance of LefunDeviceSupport
*/
public LefunDeviceSupport() {
super(LOG);
addSupportedService(GattService.UUID_SERVICE_GENERIC_ACCESS);
@ -449,6 +455,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends unit of measurement to the device
*
* @param builder the transaction builder to append to
*/
private void sendUnitsSetting(TransactionBuilder builder) {
Prefs prefs = GBApplication.getPrefs();
String units = prefs.getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM,
@ -463,6 +474,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
sendGeneralSettings(builder, (byte) 0xff, lefunUnits);
}
/**
* Gets a features command with the currently enabled features set
*
* @return the features command
*/
private FeaturesCommand getCurrentEnabledFeatures() {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
boolean raiseToWakeEnabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED, true);
@ -479,6 +495,13 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
return cmd;
}
/**
* Sends general settings to the device
*
* @param builder the transaction builder to append to
* @param amPm AM/PM indicator setting
* @param units units of measurement setting
*/
private void sendGeneralSettings(TransactionBuilder builder, byte amPm, byte units) {
boolean givenBuilder = builder != null;
try {
@ -497,6 +520,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends the user profile to the device
*
* @param builder the transaction builder to append to
*/
private void sendUserProfile(TransactionBuilder builder) {
boolean givenBuilder = builder != null;
try {
@ -515,6 +543,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends enabled features settings to the device
*
* @param cmd the features command to send
*/
private void sendEnabledFeaturesSetting(FeaturesCommand cmd) {
try {
TransactionBuilder builder = performInitialized(SetEnabledFeaturesRequest.class.getSimpleName());
@ -529,6 +562,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends the sedentary reminder interval setting to the device
*
* @param period the reminder interval
*/
private void sendSedentaryReminderIntervalSetting(int period) {
try {
TransactionBuilder builder = performInitialized(SetSedentaryReminderIntervalRequest.class.getSimpleName());
@ -543,6 +581,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends the hydration reminder interval setting to the device
*
* @param period the reminder interval
*/
private void sendHydrationReminderIntervalSetting(int period) {
try {
TransactionBuilder builder = performInitialized(SetHydrationReminderIntervalRequest.class.getSimpleName());
@ -557,6 +600,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Sends the language selection to the device
*
* @param language the language selection
*/
private void sendLanguageSetting(byte language) {
try {
TransactionBuilder builder = performInitialized(SetLanguageRequest.class.getSimpleName());
@ -571,6 +619,12 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Stores received general settings to prefs
*
* @param amPm AM/PM indicator setting
* @param units units of measurement setting
*/
public void receiveGeneralSettings(int amPm, int units) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
boolean ampmEnabled = amPm == SettingsCommand.AM_PM_12_HOUR;
@ -579,6 +633,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
.apply();
}
/**
* Stores received enabled features settings to prefs
*
* @param cmd the features command
*/
public void receiveEnabledFeaturesSetting(FeaturesCommand cmd) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
prefs.edit()
@ -593,6 +652,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
.apply();
}
/**
* Stores received sedentary reminder interval setting to prefs
*
* @param period the interval
*/
public void receiveSedentaryReminderIntervalSetting(int period) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
prefs.edit()
@ -600,6 +664,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
.apply();
}
/**
* Stores received hydration reminder interval setting to prefs
*
* @param period the interval
*/
public void receiveHydrationReminderIntervalSetting(int period) {
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
prefs.edit()
@ -689,6 +758,13 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
return super.onCharacteristicChanged(gatt, characteristic);
}
/**
* Handles commands from the device that are not typically associated with a request
*
* @param commandId the command ID
* @param data the entire response
* @return whether the response has been handled
*/
private boolean handleAsynchronousResponse(byte commandId, byte[] data) {
// Assume data already checked for correct response code and length
switch (commandId) {
@ -702,6 +778,12 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
return false;
}
/**
* Handles live steps data
*
* @param data the response
* @return whether the response has been handled
*/
private boolean handleAsynchronousActivity(byte[] data) {
try {
GetStepsDataCommand cmd = new GetStepsDataCommand();
@ -715,6 +797,12 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
// Adapted from nodomain.freeyourgadget.gadgetbridge.service.devices.makibeshr3.MakibesHR3DeviceSupport.broadcastSample
/**
* Broadcasts live sample
*
* @param command the steps data
*/
private void broadcastSample(GetStepsDataCommand command) {
Calendar now = Calendar.getInstance();
int timestamp = (int) (now.getTimeInMillis() / 1000);
@ -735,6 +823,12 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
}
/**
* Handles PPG result from earlier request
*
* @param data the response
* @return whether the response has been handled
*/
private boolean handleAsynchronousPpgResult(byte[] data) {
try {
PpgResultCommand cmd = new PpgResultCommand();
@ -747,6 +841,12 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Handles find phone request
*
* @param data the response
* @return whether the response has been handled
*/
private boolean handleAntiLoss(byte[] data) {
try {
FindPhoneCommand cmd = new FindPhoneCommand();
@ -761,12 +861,26 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Callback when device info has been obtained
*/
public void completeInitialization() {
gbDevice.setState(GBDevice.State.INITIALIZED);
gbDevice.sendDeviceUpdateIntent(getContext());
onReadConfiguration("");
}
/**
* Converts Lefun datetime format to Unix timestamp
*
* @param year the year (2 digits based on 2000)
* @param month the month
* @param day the day
* @param hour the hour
* @param minute the minute
* @param second the second
* @return Unix timestamp of the datetime
*/
private int dateToTimestamp(byte year, byte month, byte day, byte hour, byte minute, byte second) {
Calendar calendar = Calendar.getInstance();
calendar.set(
@ -780,6 +894,13 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
return (int) (calendar.getTimeInMillis() / 1000);
}
/**
* Fetches an activity sample given the timestamp
*
* @param session DAO session
* @param timestamp the timestamp
* @return fetched activity or null if none exists
*/
private LefunActivitySample getActivitySample(DaoSession session, int timestamp) {
LefunActivitySampleDao dao = session.getLefunActivitySampleDao();
Long userId = DBHelper.getUser(session).getId();
@ -792,6 +913,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
return q.unique();
}
/**
* Processes activity data and stores it
*
* @param command the activity data
*/
public void handleActivityData(GetActivityDataCommand command) {
try (DBHandler handler = GBApplication.acquireDB()) {
DaoSession session = handler.getDaoSession();
@ -818,6 +944,13 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Processes PPG data and stores it
*
* @param timestamp the timestamp
* @param ppgType the PPG type
* @param ppgData the data from the PPG operation
*/
private void handlePpgData(int timestamp, int ppgType, byte[] ppgData) {
int ppgData0 = ppgData[0] & 0xff;
int ppgData1 = ppgData.length > 1 ? ppgData[1] & 0xff : 0;
@ -851,6 +984,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Processes PPG data from bulk get operation
*
* @param command the PPG data
*/
public void handlePpgData(GetPpgDataCommand command) {
int timestamp = dateToTimestamp(command.getYear(), command.getMonth(), command.getDay(),
command.getHour(), command.getMinute(), command.getSecond());
@ -859,6 +997,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
handlePpgData(timestamp, ppgType, ppgData);
}
/**
* Processes PPG result received as a result of requesting PPG operation
*
* @param command the PPG result
*/
public void handlePpgData(PpgResultCommand command) {
int timestamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
int ppgType = command.getPpgType();
@ -866,6 +1009,11 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
handlePpgData(timestamp, ppgType, ppgData);
}
/**
* Processes bulk sleep data
*
* @param command the sleep data
*/
public void handleSleepData(GetSleepDataCommand command) {
try (DBHandler handler = GBApplication.acquireDB()) {
DaoSession session = handler.getDaoSession();
@ -915,6 +1063,9 @@ public class LefunDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
/**
* Runs the next queued request
*/
public void runNextQueuedRequest() {
Request request = queuedRequests.poll();
if (request != null) {

View File

@ -31,7 +31,14 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.lefun.LefunDeviceSup
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
/**
* Represents a request that receives several responses
*/
public abstract class MultiFetchRequest extends Request {
/**
* Instantiates a new MultiFetchRequest
* @param support the device support
*/
protected MultiFetchRequest(LefunDeviceSupport support) {
super(support, null);
removeAfterHandling = false;
@ -97,5 +104,9 @@ public abstract class MultiFetchRequest extends Request {
return true;
}
/**
* Gets the display operation name
* @return the operation name
*/
protected abstract String getOperationName();
}

View File

@ -34,16 +34,31 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.Op
import nodomain.freeyourgadget.gadgetbridge.util.GB;
// Ripped from nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request
/**
* Basic request for operations with Lefun devices
*/
public abstract class Request extends AbstractBTLEOperation<LefunDeviceSupport> {
protected TransactionBuilder builder;
protected boolean removeAfterHandling = true;
private Logger logger = (Logger) LoggerFactory.getLogger(getName());
/**
* Instantiates Request
*
* @param support the device support
* @param builder the transaction builder to use
*/
protected Request(LefunDeviceSupport support, TransactionBuilder builder) {
super(support);
this.builder = builder;
}
/**
* Gets the transaction builder
*
* @return the transaction builder
*/
public TransactionBuilder getTransactionBuilder() {
return builder;
}
@ -57,36 +72,81 @@ public abstract class Request extends AbstractBTLEOperation<LefunDeviceSupport>
getSupport().performConnected(builder.getTransaction());
}
/**
* When implemented in a subclass, provides the request bytes to send to the device
*
* @return the request bytes
*/
public abstract byte[] createRequest();
/**
* When overridden in a subclass, handles the response to the current command
*
* @param data the response data
*/
public void handleResponse(byte[] data) {
operationStatus = OperationStatus.FINISHED;
}
/**
* Gets the class name of this instance
*
* @return the class name
*/
public String getName() {
Class thisClass = getClass();
while (thisClass.isAnonymousClass()) thisClass = thisClass.getSuperclass();
return thisClass.getSimpleName();
}
/**
* Logs a debug message
*
* @param message the message to log
*/
protected void log(String message) {
logger.debug(message);
}
/**
* When implemented in a subclass, returns the command ID associated with the current request
*
* @return the command ID
*/
public abstract int getCommandId();
/**
* Gets whether the request will queue itself
*
* @return whether the request is self-queuing
*/
public boolean isSelfQueue() {
return false;
}
/**
* Gets whether the request expects a response
*
* @return whether the request expects a response
*/
public boolean expectsResponse() {
return true;
}
/**
* Gets whether the response should be removed from in progress requests list after handling
*
* @return whether the response should be removed after handling
*/
public boolean shouldRemoveAfterHandling() {
return removeAfterHandling;
}
/**
* Reports an error to the user
*
* @param message the message to show
*/
protected void reportFailure(String message) {
GB.toast(getContext(), message, Toast.LENGTH_SHORT, GB.ERROR);
}