added some requests

This commit is contained in:
dakhnod 2019-10-27 23:24:02 +01:00
parent 7d5810fdf0
commit 37d7df2d31
47 changed files with 902 additions and 56 deletions

View File

@ -5,13 +5,10 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid;//
import java.util.zip.Checksum;
public final class CRC32C_stolen implements Checksum {
private static final int[] bqC = new int[]{0, (int) 4067132163L, (int) 3778769143L, 324072436, (int) 3348797215L, 904991772, 648144872, (int) 3570033899L, (int) 2329499855L, 2024987596, 1809983544, (int) 2575936315L, 1296289744, (int) 3207089363L, (int) 2893594407L, 1578318884, 274646895, (int) 3795141740L, (int) 4049975192L, 51262619, (int) 3619967088L, 632279923, 922689671, (int) 3298075524L, (int) 2592579488L, 1760304291, 2075979607, (int) 2312596564L, 1562183871, (int) 2943781820L, (int) 3156637768L, 1313733451, 549293790, (int) 3537243613L, (int) 3246849577L, 871202090, (int) 3878099393L, 357341890, 102525238, (int) 4101499445L, (int) 2858735121L, 1477399826, 1264559846, (int) 3107202533L, 1845379342, (int) 2677391885L, (int) 2361733625L, 2125378298, 820201905, (int) 3263744690L, (int) 3520608582L, 598981189, (int) 4151959214L, 85089709, 373468761, (int) 3827903834L, (int) 3124367742L, 1213305469, 1526817161, (int) 2842354314L, 2107672161, (int) 2412447074L, (int) 2627466902L, 1861252501, 1098587580, (int) 3004210879L, (int) 2688576843L, 1378610760, (int) 2262928035L, 1955203488, 1742404180, (int) 2511436119L, (int) 3416409459L, 969524848, 714683780, (int) 3639785095L, 205050476, (int) 4266873199L, (int) 3976438427L, 526918040, 1361435347, (int) 2739821008L, (int) 2954799652L, 1114974503, (int) 2529119692L, 1691668175, 2005155131, (int) 2247081528L, (int) 3690758684L, 697762079, 986182379, (int) 3366744552L, 476452099, (int) 3993867776L, (int) 4250756596L, 255256311, 1640403810, (int) 2477592673L, (int) 2164122517L, 1922457750, (int) 2791048317L, 1412925310, 1197962378, (int) 3037525897L, (int) 3944729517L, 427051182, 170179418, (int) 4165941337L, 746937522, (int) 3740196785L, (int) 3451792453L, 1070968646, 1905808397, (int) 2213795598L, (int) 2426610938L, 1657317369, (int) 3053634322L, 1147748369, 1463399397, (int) 2773627110L, (int) 4215344322L, 153784257, 444234805, (int) 3893493558L, 1021025245, (int) 3467647198L, (int) 3722505002L, 797665321, (int) 2197175160L, 1889384571, 1674398607, (int) 2443626636L, 1164749927, (int) 3070701412L, (int) 2757221520L, 1446797203, 137323447, (int) 4198817972L, (int) 3910406976L, 461344835, (int) 3484808360L, 1037989803, 781091935, (int) 3705997148L, (int) 2460548119L, 1623424788, 1939049696, (int) 2180517859L, 1429367560, (int) 2807687179L, (int) 3020495871L, 1180866812, 410100952, (int) 3927582683L, (int) 4182430767L, 186734380, (int) 3756733383L, 763408580, 1053836080, (int) 3434856499L, (int) 2722870694L, 1344288421, 1131464017, (int) 2971354706L, 1708204729, (int) 2545590714L, (int) 2229949006L, 1988219213, 680717673, (int) 3673779818L, (int) 3383336350L, 1002577565, (int) 4010310262L, 493091189, 238226049, (int) 4233660802L, (int) 2987750089L, 1082061258, 1395524158, (int) 2705686845L, 1972364758, (int) 2279892693L, (int) 2494862625L, 1725896226, 952904198, (int) 3399985413L, (int) 3656866545L, 731699698, (int) 4283874585L, 222117402, 510512622, (int) 3959836397L, (int) 3280807620L, 837199303, 582374963, (int) 3504198960L, 68661723, (int) 4135334616L, (int) 3844915500L, 390545967, 1230274059, (int) 3141532936L, (int) 2825850620L, 1510247935, (int) 2395924756L, 2091215383, 1878366691, (int) 2644384480L, (int) 3553878443L, 565732008, 854102364, (int) 3229815391L, 340358836, (int) 3861050807L, (int) 4117890627L, 119113024, 1493875044, (int) 2875275879L, (int) 3090270611L, 1247431312, (int) 2660249211L, 1828433272, 2141937292, (int) 2378227087L, (int) 3811616794L, 291187481, 34330861, (int) 4032846830L, 615137029, (int) 3603020806L, (int) 3314634738L, 939183345, 1776939221, (int) 2609017814L, (int) 2295496738L, 2058945313, (int) 2926798794L, 1545135305, 1330124605, (int) 3173225534L, (int) 4084100981L, 17165430, 307568514, (int) 3762199681L, 888469610, (int) 3332340585L, (int) 3587147933L, 665062302, 2042050490, (int) 2346497209L, (int) 2559330125L, 1793573966, (int) 3190661285L, 1279665062, 1595330642, (int) 2910671697L};
public final class CRC32C implements Checksum {
private static final int[] crcTable = new int[]{0, (int) 4067132163L, (int) 3778769143L, 324072436, (int) 3348797215L, 904991772, 648144872, (int) 3570033899L, (int) 2329499855L, 2024987596, 1809983544, (int) 2575936315L, 1296289744, (int) 3207089363L, (int) 2893594407L, 1578318884, 274646895, (int) 3795141740L, (int) 4049975192L, 51262619, (int) 3619967088L, 632279923, 922689671, (int) 3298075524L, (int) 2592579488L, 1760304291, 2075979607, (int) 2312596564L, 1562183871, (int) 2943781820L, (int) 3156637768L, 1313733451, 549293790, (int) 3537243613L, (int) 3246849577L, 871202090, (int) 3878099393L, 357341890, 102525238, (int) 4101499445L, (int) 2858735121L, 1477399826, 1264559846, (int) 3107202533L, 1845379342, (int) 2677391885L, (int) 2361733625L, 2125378298, 820201905, (int) 3263744690L, (int) 3520608582L, 598981189, (int) 4151959214L, 85089709, 373468761, (int) 3827903834L, (int) 3124367742L, 1213305469, 1526817161, (int) 2842354314L, 2107672161, (int) 2412447074L, (int) 2627466902L, 1861252501, 1098587580, (int) 3004210879L, (int) 2688576843L, 1378610760, (int) 2262928035L, 1955203488, 1742404180, (int) 2511436119L, (int) 3416409459L, 969524848, 714683780, (int) 3639785095L, 205050476, (int) 4266873199L, (int) 3976438427L, 526918040, 1361435347, (int) 2739821008L, (int) 2954799652L, 1114974503, (int) 2529119692L, 1691668175, 2005155131, (int) 2247081528L, (int) 3690758684L, 697762079, 986182379, (int) 3366744552L, 476452099, (int) 3993867776L, (int) 4250756596L, 255256311, 1640403810, (int) 2477592673L, (int) 2164122517L, 1922457750, (int) 2791048317L, 1412925310, 1197962378, (int) 3037525897L, (int) 3944729517L, 427051182, 170179418, (int) 4165941337L, 746937522, (int) 3740196785L, (int) 3451792453L, 1070968646, 1905808397, (int) 2213795598L, (int) 2426610938L, 1657317369, (int) 3053634322L, 1147748369, 1463399397, (int) 2773627110L, (int) 4215344322L, 153784257, 444234805, (int) 3893493558L, 1021025245, (int) 3467647198L, (int) 3722505002L, 797665321, (int) 2197175160L, 1889384571, 1674398607, (int) 2443626636L, 1164749927, (int) 3070701412L, (int) 2757221520L, 1446797203, 137323447, (int) 4198817972L, (int) 3910406976L, 461344835, (int) 3484808360L, 1037989803, 781091935, (int) 3705997148L, (int) 2460548119L, 1623424788, 1939049696, (int) 2180517859L, 1429367560, (int) 2807687179L, (int) 3020495871L, 1180866812, 410100952, (int) 3927582683L, (int) 4182430767L, 186734380, (int) 3756733383L, 763408580, 1053836080, (int) 3434856499L, (int) 2722870694L, 1344288421, 1131464017, (int) 2971354706L, 1708204729, (int) 2545590714L, (int) 2229949006L, 1988219213, 680717673, (int) 3673779818L, (int) 3383336350L, 1002577565, (int) 4010310262L, 493091189, 238226049, (int) 4233660802L, (int) 2987750089L, 1082061258, 1395524158, (int) 2705686845L, 1972364758, (int) 2279892693L, (int) 2494862625L, 1725896226, 952904198, (int) 3399985413L, (int) 3656866545L, 731699698, (int) 4283874585L, 222117402, 510512622, (int) 3959836397L, (int) 3280807620L, 837199303, 582374963, (int) 3504198960L, 68661723, (int) 4135334616L, (int) 3844915500L, 390545967, 1230274059, (int) 3141532936L, (int) 2825850620L, 1510247935, (int) 2395924756L, 2091215383, 1878366691, (int) 2644384480L, (int) 3553878443L, 565732008, 854102364, (int) 3229815391L, 340358836, (int) 3861050807L, (int) 4117890627L, 119113024, 1493875044, (int) 2875275879L, (int) 3090270611L, 1247431312, (int) 2660249211L, 1828433272, 2141937292, (int) 2378227087L, (int) 3811616794L, 291187481, 34330861, (int) 4032846830L, 615137029, (int) 3603020806L, (int) 3314634738L, 939183345, 1776939221, (int) 2609017814L, (int) 2295496738L, 2058945313, (int) 2926798794L, 1545135305, 1330124605, (int) 3173225534L, (int) 4084100981L, 17165430, 307568514, (int) 3762199681L, 888469610, (int) 3332340585L, (int) 3587147933L, 665062302, 2042050490, (int) 2346497209L, (int) 2559330125L, 1793573966, (int) 3190661285L, 1279665062, 1595330642, (int) 2910671697L};
private int crc = 0xFFFFFFFF;
public CRC32C_stolen() {
}
public long getValue() {
return ~this.crc;
}
@ -20,27 +17,17 @@ public final class CRC32C_stolen implements Checksum {
this.crc = 0xFFFFFFFF;
}
public void update(int var1) {
int var2 = this.crc;
this.crc = bqC[(var1 & 255 ^ var2) & 255] ^ var2 >>> 8;
public void update(int data) {
crc = crcTable[(data & 255 ^ crc) & 255] ^ crc >>> 8;
}
public void update(byte[] var1, int var2, int var3) {
for (int var4 = var2; var4 < var3 + var2; ++var4) {
this.crc = bqC[(this.crc ^ var1[var4]) & 255] ^ this.crc >>> 8;
public void update(byte[] data, int offset, int length) {
for (int index = offset; index < length + offset; index++) {
this.crc = crcTable[(this.crc ^ data[index]) & 255] ^ this.crc >>> 8;
}
}
public void update(byte[] data){
update(data, 0, data.length);
}
public static int crc32c(byte[] data)
{
int crc = 0xffffffff;
for(int i = 0; i < data.length; i++){
crc = (crc>>>8) ^ bqC[(crc ^ data[i]) & 0xFF];
}
return ~crc;
}
}

View File

@ -37,10 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateA
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapterFactory;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.DownloadFileRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.GetStepGoalRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.VibrateRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class QHybridSupport extends QHybridBaseSupport {
@ -264,7 +261,7 @@ public class QHybridSupport extends QHybridBaseSupport {
@Override
public void onTestNewFunction() {
watchAdapter.onTestNewFunction();
}
private void backupFile(DownloadFileRequest request) {

View File

@ -19,7 +19,7 @@ public abstract class WatchAdapter {
this.deviceSupport = deviceSupport;
}
protected QHybridSupport getDeviceSupport(){
public QHybridSupport getDeviceSupport(){
return this.deviceSupport;
}
@ -41,6 +41,7 @@ public abstract class WatchAdapter {
public abstract void releaseHandsControl();
public abstract void setStepGoal(int stepGoal);
public abstract void setVibrationStrength(short strength);
public abstract void onTestNewFunction();
public abstract boolean supportsExtendedVibration();
public abstract boolean supportsActivityHand();
@ -50,4 +51,15 @@ public abstract class WatchAdapter {
public abstract boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
public String arrayToString(byte[] bytes) {
if (bytes.length == 0) return "";
StringBuilder s = new StringBuilder();
final String chars = "0123456789ABCDEF";
for (byte b : bytes) {
s.append(chars.charAt((b >> 4) & 0xF)).append(chars.charAt(b & 0xF)).append(" ");
}
return s.substring(0, s.length() - 1) + "\n";
}
}

View File

@ -1,7 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.misfit.MisfitWatchAdapter;
public final class WatchAdapterFactory {
@ -9,6 +9,7 @@ public final class WatchAdapterFactory {
char major = firmwareVersion.charAt(6);
switch (major){
case '1': return new MisfitWatchAdapter(deviceSupport);
case '2': return new FossilWatchAdapter(deviceSupport);
}
throw new UnsupportedOperationException("Firmware " + firmwareVersion + " not supported");

View File

@ -1,6 +1,232 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.util.Log;
import java.util.ArrayDeque;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.TimeZone;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfig;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.ConfigurationGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.ConfigurationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FileGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FileLookupAndGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FileLookupRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.NotifcationFilterGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest;
public class FossilWatchAdapter extends WatchAdapter {
private Queue<Request> requestQueue = new ArrayDeque<>();
FilePutRequest filePutRequest;
FileGetRequest fileGetRequest;
FileLookupRequest fileLookupRequest;
public FossilWatchAdapter(QHybridSupport deviceSupport) {
super(deviceSupport);
}
@Override
public void initialize() {
playPairingAnimation();
}
@Override
public void playPairingAnimation() {
queueWrite(new AnimationRequest());
}
@Override
public void playNotification(PackageConfig config) {
queueWrite(new PlayNotificationRequest(config.getPackageName(), this));
}
@Override
public void setTime() {
long millis = System.currentTimeMillis();
TimeZone zone = new GregorianCalendar().getTimeZone();
queueWrite(
new ConfigurationRequest(
new ConfigurationRequest.TimeConfigItem(
(int) (millis / 1000 + getDeviceSupport().getTimeOffset() * 60),
(short) (millis % 1000),
(short) ((zone.getRawOffset() + (zone.inDaylightTime(new Date()) ? 1 : 0)) / 60000)
),
this)
);
}
@Override
public void overwriteButtons() {
}
@Override
public void setActivityHand(double progress) {
}
@Override
public void setHands(short hour, short minute) {
}
@Override
public void vibrate(nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest.VibrationType vibration) {
}
@Override
public void vibrateFindMyDevicePattern() {
}
@Override
public void requestHandsControl() {
}
@Override
public void releaseHandsControl() {
}
@Override
public void setStepGoal(int stepGoal) {
}
@Override
public void setVibrationStrength(short strength) {
}
@Override
public void onTestNewFunction() {
queueWrite(new FileLookupAndGetRequest((byte)8, this));
}
@Override
public boolean supportsExtendedVibration() {
String modelNumber = getDeviceSupport().getDevice().getModel();
switch (modelNumber) {
case "HW.0.0":
return true;
case "HL.0.0":
return false;
}
throw new UnsupportedOperationException("model " + modelNumber + " not supported");
}
@Override
public boolean supportsActivityHand() {
String modelNumber = getDeviceSupport().getDevice().getModel();
switch (modelNumber) {
case "HW.0.0":
return true;
case "HL.0.0":
return false;
}
throw new UnsupportedOperationException("Model " + modelNumber + " not supported");
}
@Override
public String getModelName() {
String modelNumber = getDeviceSupport().getDevice().getModel();
switch (modelNumber) {
case "HW.0.0":
return "Q Commuter";
case "HL.0.0":
return "Q Activist";
}
return "unknwon Q";
}
@Override
public void onFetchActivityData() {
}
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
switch (characteristic.getUuid().toString()) {
case "3dda0004-957f-7d4a-34a6-74696673696d":
case "3dda0003-957f-7d4a-34a6-74696673696d": {
if (filePutRequest != null) {
filePutRequest.handleResponse(characteristic);
if (filePutRequest.isFinished()) {
filePutRequest = null;
try {
queueWrite(requestQueue.remove());
} catch (NoSuchElementException e) {
}
}
} else if(fileGetRequest != null){
boolean requestFinished;
try {
fileGetRequest.handleResponse(characteristic);
requestFinished = fileGetRequest.isFinished();
}catch (RuntimeException e){
e.printStackTrace();
requestFinished = true;
}
if(requestFinished){
fileGetRequest = null;
try {
queueWrite(requestQueue.remove());
} catch (NoSuchElementException e) {
}
}
} else if(fileLookupRequest != null){
boolean requestFinished;
try {
fileLookupRequest.handleResponse(characteristic);
requestFinished = fileLookupRequest.isFinished();
}catch (RuntimeException e){
e.printStackTrace();
requestFinished = true;
}
if(requestFinished){
fileLookupRequest = null;
try {
queueWrite(requestQueue.remove());
} catch (NoSuchElementException e) {
}
}
}
}
}
return true;
}
public void queueWrite(Request request) {
if (filePutRequest != null || fileGetRequest != null || fileLookupRequest != null) {
requestQueue.add(request);
return;
}
if (request instanceof FilePutRequest) filePutRequest = (FilePutRequest) request;
else if (request instanceof FileGetRequest) fileGetRequest = (FileGetRequest) request;
else if (request instanceof FileLookupRequest) fileLookupRequest = (FileLookupRequest) request;
new TransactionBuilder(request.getClass().getSimpleName()).write(getDeviceSupport().getCharacteristic(request.getRequestUUID()), request.getRequestData()).queue(getDeviceSupport().getQueue());
}
}

View File

@ -3,10 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.mis
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.util.SparseArray;
import android.widget.Toast;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -29,8 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfig;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.WatchAdapter;
@ -51,7 +47,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mis
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.OTAEraseRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.ReleaseHandsControlRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.RequestHandControlRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetCurrentStepCountRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetStepGoalRequest;
@ -59,7 +55,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mis
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.SetVibrationStrengthRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.UploadFileRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.VibrateRequest;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.ITEM_ACTIVITY_POINT;
import static nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport.ITEM_STEP_COUNT;
@ -175,16 +170,6 @@ public class MisfitWatchAdapter extends WatchAdapter {
return getDeviceSupport().onCharacteristicChanged(gatt, characteristic);
}
private String arrayToString(byte[] bytes) {
if (bytes.length == 0) return "";
StringBuilder s = new StringBuilder();
final String chars = "0123456789ABCDEF";
for (byte b : bytes) {
s.append(chars.charAt((b >> 4) & 0xF)).append(chars.charAt(b & 0xF)).append(" ");
}
return s.substring(0, s.length() - 1) + "\n";
}
private void fillResponseList() {
Class<? extends Request>[] classes = new Class[]{
BatteryLevelRequest.class,
@ -349,7 +334,7 @@ public class MisfitWatchAdapter extends WatchAdapter {
//buffer.put(value, 2, 8);
//buffer.put(new byte[]{(byte)0xFF, 0x05, 0x00, 0x01, 0x00});
//UploadFileRequest request = new UploadFileRequest((short)0, buffer.array());
//FilePutRequest request = new FilePutRequest((short)0, buffer.array());
//for(byte[] packet : request.packets){
// new TransactionBuilder("File upload").write(getCharacteristic(UUID.fromString("3dda0007-957f-7d4a-34a6-74696673696d")), packet).queue(getQueue());
//}
@ -399,6 +384,11 @@ public class MisfitWatchAdapter extends WatchAdapter {
queueWrite(new SetVibrationStrengthRequest(strength));
}
@Override
public void onTestNewFunction() {
}
@Override
public boolean supportsExtendedVibration() {
String modelNumber = getDeviceSupport().getDevice().getModel();

View File

@ -1,4 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests;
public class CRC32C {
}

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests;
import android.bluetooth.BluetoothGattCharacteristic;
import android.util.Log;

View File

@ -1,4 +1,16 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
import android.util.Log;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class ConfigurationGetRequest extends FileGetRequest {
public ConfigurationGetRequest(short handle, FossilWatchAdapter adapter) {
super(handle, adapter);
}
@Override
void handleFileData(byte[] fileData) {
log("config file: " + getAdapter().arrayToString(fileData));
}
}

View File

@ -1,4 +1,154 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
public class ConfigurationRequest extends UploadFileRequest {
import android.graphics.Bitmap;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class ConfigurationRequest extends FilePutRequest {
private static HashMap<Byte, Class<? extends ConfigItem>> itemsById;
static {
itemsById.put((byte)3, DailyStepGoalConfigItem.class);
itemsById.put((byte)10, VibrationStrengthConfigItem.class);
itemsById.put((byte)2, CurrentStepCountConfigItem.class);
itemsById.put((byte)3, DailyStepGoalConfigItem.class);
itemsById.put((byte)12, TimeConfigItem.class);
}
static ConfigItem parsePayload(byte id, byte[] data) throws InstantiationException, IllegalAccessException {
Class<? extends ConfigItem> itemClass = itemsById.get(id);
ConfigItem item = itemClass.newInstance();
item.parseData(data);
return item;
}
public ConfigurationRequest(ConfigItem item, FossilWatchAdapter adapter) {
super((short) 0x0800, createFileContent(item), adapter);
}
public static byte[] createFileContent(ConfigItem item) {
ByteBuffer buffer = ByteBuffer.allocate(item.getItemSize() + 3);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putShort(item.getId());
buffer.put((byte) item.getItemSize());
buffer.put(item.getContent());
return buffer.array();
}
public interface ConfigItem {
public int getItemSize();
public short getId();
public byte[] getContent();
public void parseData(byte[] data);
}
static public class GenericConfigItem<T> implements ConfigItem {
T value;
short configId;
public GenericConfigItem(short configId, T value) {
this.value = value;
this.configId = configId;
}
@Override
public int getItemSize() {
switch (value.getClass().getName()) {
case "Byte":
return 1;
case "Integer":
return 4;
case "Long":
return 8;
}
throw new UnsupportedOperationException("config type " + value.getClass().getName() + " not supported");
}
@Override
public short getId() {
return 0;
}
@Override
public byte[] getContent() {
ByteBuffer buffer = ByteBuffer.allocate(getItemSize());
buffer.order(ByteOrder.LITTLE_ENDIAN);
switch (value.getClass().getName()) {
case "Byte": {
buffer.put((Byte) this.value);
break;
}
case "Integer": {
buffer.putInt((Integer) this.value);
break;
}
case "Long": {
buffer.putLong((Long) this.value);
break;
}
}
return buffer.array();
}
}
static public class DailyStepGoalConfigItem extends GenericConfigItem<Integer> {
public DailyStepGoalConfigItem(int value) {
super((short) 3, value);
}
}
static public class VibrationStrengthConfigItem extends GenericConfigItem<Byte> {
public VibrationStrengthConfigItem(Byte value) {
super((short) 10, value);
}
}
static public class CurrentStepCountConfigItem extends GenericConfigItem<Integer> {
public CurrentStepCountConfigItem(Integer value) {
super((short) 2, value);
}
}
static public class TimeConfigItem implements ConfigItem {
private int epochSeconds;
private short millis, offsetMinutes;
public TimeConfigItem(int epochSeconds, short millis, short offsetMinutes) {
this.epochSeconds = epochSeconds;
this.millis = millis;
this.offsetMinutes = offsetMinutes;
}
@Override
public int getItemSize() {
return 8;
}
@Override
public short getId() {
return (short) 12;
}
@Override
public byte[] getContent() {
ByteBuffer buffer = ByteBuffer.allocate(getItemSize());
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(this.epochSeconds);
buffer.putShort(millis);
buffer.putShort(offsetMinutes);
return buffer.array();
}
}
}

View File

@ -1,4 +1,114 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
public class FileGetRequest {
import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public abstract class FileGetRequest extends Request {
private short handle;
private FossilWatchAdapter adapter;
private ByteBuffer fileBuffer;
private byte[] fileData;
private boolean finished = false;
public FileGetRequest(short handle, FossilWatchAdapter adapter) {
this.handle = handle;
this.adapter = adapter;
this.data =
createBuffer()
.putShort(handle)
.putInt(0)
.putInt(0xFFFFFFFF)
.array();
}
public FossilWatchAdapter getAdapter() {
return adapter;
}
public boolean isFinished(){
return finished;
}
@Override
public void handleResponse(BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue();
byte first = value[0];
if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")){
if((first & 0x0F) == 1){
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
short handle = buffer.getShort(1);
int size = buffer.getInt(4);
byte status = buffer.get(3);
if(status != 0){
throw new RuntimeException("FileGet error: " + status);
}
if(this.handle != handle){
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
log("file size: " + size);
fileBuffer = ByteBuffer.allocate(size);
}else if((first & 0x0F) == 8){
this.finished = true;
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
short handle = buffer.getShort(1);
if(this.handle != handle){
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
CRC32 crc = new CRC32();
crc.update(this.fileData);
int crcExpected = buffer.getInt(8);
if((int) crc.getValue() != crcExpected){
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
this.handleFileData(this.fileData);
}
}else if(characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")){
fileBuffer.put(value, 1, value.length - 1);
if((first & 0x80) == 0x80){
this.fileData = fileBuffer.array();
}
}
}
@Override
public UUID getRequestUUID() {
return UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d");
}
@Override
public byte[] getStartSequence() {
return new byte[]{1};
}
@Override
public int getPayloadLength() {
return 11;
}
abstract void handleFileData(byte[] fileData);
}

View File

@ -1,4 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class FileLookupAndGetRequest extends FileLookupRequest {
public FileLookupAndGetRequest(byte fileType, FossilWatchAdapter adapter) {
super(fileType, adapter);
}
@Override
public void handleFileLookup(short fileHandle) {
this.getAdapter().queueWrite(new ConfigurationGetRequest(fileHandle, getAdapter()));
}
}

View File

@ -1,6 +1,121 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class FileLookupRequest extends Request {
private short handle = -1;
private byte fileType;
private FossilWatchAdapter adapter;
private ByteBuffer fileBuffer;
private byte[] fileData;
private boolean finished = false;
public FileLookupRequest(byte fileType, FossilWatchAdapter adapter) {
this.fileType = fileType;
this.adapter = adapter;
this.data =
createBuffer()
.put(fileType)
.array();
}
protected FossilWatchAdapter getAdapter() {
return adapter;
}
public short getHandle() {
if(!finished){
throw new UnsupportedOperationException("File lookup not finished");
}
return handle;
}
public boolean isFinished(){
return finished;
}
@Override
public void handleResponse(BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue();
byte first = value[0];
if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")){
if((first & 0x0F) == 2){
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
short handle = buffer.getShort(1);
int size = buffer.getInt(4);
byte status = buffer.get(3);
if(status != 0){
throw new RuntimeException("FileGet error: " + status);
}
if(this.handle != handle){
// throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
log("file size: " + size);
fileBuffer = ByteBuffer.allocate(size);
}else if((first & 0x0F) == 8){
this.finished = true;
ByteBuffer buffer = ByteBuffer.wrap(value);
buffer.order(ByteOrder.LITTLE_ENDIAN);
CRC32 crc = new CRC32();
crc.update(this.fileData);
int crcExpected = buffer.getInt(8);
if((int) crc.getValue() != crcExpected){
throw new RuntimeException("handle: " + handle + " expected: " + this.handle);
}
ByteBuffer dataBuffer = ByteBuffer.wrap(fileData);
dataBuffer.order(ByteOrder.LITTLE_ENDIAN);
this.handle = dataBuffer.getShort(0);
this.handleFileLookup(this.handle);
}
}else if(characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")){
fileBuffer.put(value, 1, value.length - 1);
if((first & 0x80) == 0x80){
this.fileData = fileBuffer.array();
}
}
}
public void handleFileLookup(short fileHandle){}
@Override
public UUID getRequestUUID() {
return UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d");
}
@Override
public byte[] getStartSequence() {
return new byte[]{2, (byte) 0xFF};
}
@Override
public int getPayloadLength() {
return 3;
}
}

View File

@ -13,7 +13,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.CRC32C;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class UploadFileRequest extends Request {
public abstract class FilePutRequest extends Request {
public enum UploadState{INITIALIZED, UPLOADING, CLOSING, UPLOADED, ERROR}
public UploadState state;
@ -26,7 +26,7 @@ public class UploadFileRequest extends Request {
private FossilWatchAdapter adapter;
public UploadFileRequest(short handle, byte[] file, FossilWatchAdapter adapter) {
public FilePutRequest(short handle, byte[] file, FossilWatchAdapter adapter) {
this.handle = handle;
this.adapter = adapter;

View File

@ -1,4 +1,33 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.CRC32C;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class NotifcationFilterGetRequest extends FileGetRequest {
public NotifcationFilterGetRequest(FossilWatchAdapter adapter) {
super((short) 0x0C00, adapter);
}
@Override
void handleFileData(byte[] fileData) {
log("handleFileData");
ByteBuffer buffer = ByteBuffer.wrap(fileData);
buffer.order(ByteOrder.LITTLE_ENDIAN);
byte[] data = new byte[fileData.length - 12 - 4];
System.arraycopy(fileData, 12, data, 0, data.length);
CRC32C crc32c = new CRC32C();
crc32c.update(data);
if((int) crc32c.getValue() != buffer.getInt(fileData.length - 4)){
throw new RuntimeException("CRC invalid");
}
}
}

View File

@ -1,4 +1,92 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
public class PlayNotificationRequest extends UploadFileRequest {
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class PlayNotificationRequest extends FilePutRequest {
public PlayNotificationRequest(String packageName, FossilWatchAdapter adapter) {
// super((short) 0x0900, createFile("org.telegram.messenger", "org.telegram.messenger", "org.telegram.messenger"), adapter);
super((short) 0x0900, createFile(packageName), adapter);
}
private static byte[] createFile(String packageName){
CRC32 crc = new CRC32();
crc.update(packageName.getBytes());
return createFile("", "", "", (int)crc.getValue());
}
private static byte[] createFile(String title, String sender, String message, int packageCrc) {
// return new byte[]{(byte) 0x57, (byte) 0x00, (byte) 0x0A, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x17, (byte) 0x17, (byte) 0x17, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x49, (byte) 0x7B, (byte) 0x3B, (byte) 0x62, (byte) 0x6F, (byte) 0x72, (byte) 0x67, (byte) 0x2E, (byte) 0x74, (byte) 0x65, (byte) 0x6C, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x61, (byte) 0x6D, (byte) 0x2E, (byte) 0x6D, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x65, (byte) 0x6E, (byte) 0x67, (byte) 0x65, (byte) 0x72, (byte) 0x00, (byte) 0x6F, (byte) 0x72, (byte) 0x67, (byte) 0x2E, (byte) 0x74, (byte) 0x65, (byte) 0x6C, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x61, (byte) 0x6D, (byte) 0x2E, (byte) 0x6D, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x65, (byte) 0x6E, (byte) 0x67, (byte) 0x65, (byte) 0x72, (byte) 0x00, (byte) 0x6F, (byte) 0x72, (byte) 0x67, (byte) 0x2E, (byte) 0x74, (byte) 0x65, (byte) 0x6C, (byte) 0x65, (byte) 0x67, (byte) 0x72, (byte) 0x61, (byte) 0x6D, (byte) 0x2E, (byte) 0x6D, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x65, (byte) 0x6E, (byte) 0x67, (byte) 0x65, (byte) 0x72, (byte) 0x00};
// gwb.k(var6, "ByteBuffer.allocate(10)");
byte lengthBufferLength = (byte) 10;
byte typeId = 3;
byte flags = getFlags();
byte uidLength = (byte) 4;
byte appBundleCRCLength = (byte) 4;
String nullTerminatedTitle = terminateNull(title);
Charset charsetUTF8 = Charset.forName("UTF-8");
byte[] titleBytes = nullTerminatedTitle.getBytes(charsetUTF8);
// gwb.k(var13, "(this as java.lang.String).getBytes(charset)");
String nullTerminatedSender = terminateNull(sender);
byte[] senderBytes = nullTerminatedSender.getBytes(charsetUTF8);
// gwb.k(var15, "(this as java.lang.String).getBytes(charset)");
String nullTerminatedMessage = terminateNull(message);
byte[] messageBytes = nullTerminatedMessage.getBytes(charsetUTF8);
// gwb.k(var17, "(this as java.lang.String).getBytes(charset)");
short mainBufferLength = (short) (lengthBufferLength + uidLength + appBundleCRCLength + titleBytes.length + senderBytes.length + messageBytes.length);
ByteBuffer lengthBuffer = ByteBuffer.allocate(lengthBufferLength);
lengthBuffer.order(ByteOrder.LITTLE_ENDIAN);
lengthBuffer.putShort(mainBufferLength);
lengthBuffer.put(lengthBufferLength);
lengthBuffer.put(typeId);
lengthBuffer.put(flags);
lengthBuffer.put(uidLength);
lengthBuffer.put(appBundleCRCLength);
lengthBuffer.put((byte) titleBytes.length);
lengthBuffer.put((byte) senderBytes.length);
lengthBuffer.put((byte) messageBytes.length);
ByteBuffer mainBuffer = ByteBuffer.allocate(mainBufferLength);
// gwb.k(var11, "ByteBuffer.allocate(totalLen.toInt())");
mainBuffer.order(ByteOrder.LITTLE_ENDIAN);
mainBuffer.put(lengthBuffer.array());
lengthBuffer = ByteBuffer.allocate(mainBufferLength - lengthBufferLength);
// gwb.k(var6, "ByteBuffer.allocate(totalLen - headerLen)");
lengthBuffer.order(ByteOrder.LITTLE_ENDIAN);
lengthBuffer.putInt(0);
lengthBuffer.putInt(packageCrc);
lengthBuffer.put(titleBytes);
lengthBuffer.put(senderBytes);
lengthBuffer.put(messageBytes);
mainBuffer.put(lengthBuffer.array());
return mainBuffer.array();
}
private static byte getFlags(){
return (byte) 2;
}
public static String terminateNull(String input){
if(input.length() == 0){
return new String(new byte[]{(byte) 0});
}
char lastChar = input.charAt(input.length() - 1);
if(lastChar == 0) return input;
byte[] newArray = new byte[input.length() + 1];
System.arraycopy(input.getBytes(), 0, newArray, 0, input.length());
newArray[newArray.length - 1] = 0;
return new String(newArray);
}
}

View File

@ -1,4 +1,67 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
public class SendNotificationFilterRequest extends UploadFileRequest {
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter;
public class SendNotificationFilterRequest extends FilePutRequest {
public SendNotificationFilterRequest(FossilWatchAdapter adapter) {
super((short) 0x0C00, createFile(), adapter);
}
private static byte[] createFile() {
return null;
/*ByteArrayOutputStream var3 = new ByteArrayOutputStream();
byte var1 = NotificationEntryId.APP_BUNDLE_CRC32.getId$blesdk_productionRelease();
byte[] var4 = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt((int)this.appBundleCrc).array();
gwb.k(var4, "ByteBuffer.allocate(4)\n … .array()");
var3.write(this.c(var1, var4));
var3.write(this.c(NotificationEntryId.GROUP_ID.getId$blesdk_productionRelease(), new byte[]{this.groupId}));
boolean var2;
if (((CharSequence)this.sender).length() > 0) {
var2 = true;
} else {
var2 = false;
}
if (var2) {
var1 = NotificationEntryId.SENDER_NAME.getId$blesdk_productionRelease();
String var7 = bcf.da(this.sender);
Charset var5 = bdq.bqp.Qs();
if (var7 == null) {
throw new TypeCastException("null cannot be cast to non-null type java.lang.String");
}
var4 = var7.getBytes(var5);
gwb.k(var4, "(this as java.lang.String).getBytes(charset)");
var3.write(this.c(var1, var4));
}
if (this.priority != (short)-1) {
var3.write(this.c(NotificationEntryId.PRIORITY.getId$blesdk_productionRelease(), new byte[]{(byte)this.priority}));
}
NotificationHandMovingConfig var8 = this.handMovingConfig;
if (var8 != null) {
var3.write(this.c(NotificationEntryId.HAND_MOVING.getId$blesdk_productionRelease(), var8.getData$blesdk_productionRelease()));
}
NotificationVibePattern var9 = this.vibePattern;
if (var9 != null) {
var3.write(this.c(NotificationEntryId.VIBE.getId$blesdk_productionRelease(), new byte[]{var9.getId$blesdk_productionRelease()}));
}
NotificationIconConfig var10 = this.iconConfig;
if (var10 != null) {
var3.write(this.c(NotificationEntryId.ICON_IMAGE.getId$blesdk_productionRelease(), var10.getNotificationFilterIconConfigData$blesdk_productionRelease()));
}
byte[] var6 = var3.toByteArray();
var6 = ByteBuffer.allocate(var6.length + 2).order(ByteOrder.LITTLE_ENDIAN).putShort((short)var6.length).put(var6).array();
gwb.k(var6, "ByteBuffer\n …\n .array()");
return var6;*/
}
}

View File

@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class ActivityPointGetRequest extends Request {
public int activityPoint;

View File

@ -1,6 +1,8 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
public class AnimationRequest extends Request{
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class AnimationRequest extends Request {
@Override
public byte[] getStartSequence() {
return new byte[]{(byte)2, (byte) -15, (byte)5};

View File

@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class BatteryLevelRequest extends Request {
public short level = -1;
@Override

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class EventStreamRequest extends Request {
public EventStreamRequest(short handle) {
super();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class FileRequest extends Request {
public boolean completed = false;
public int status;

View File

@ -5,6 +5,8 @@ import android.util.Log;
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GetCountdownSettingsRequest extends Request {
@Override
public byte[] getStartSequence() {

View File

@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GetCurrentStepCountRequest extends Request {
public int steps = -1;

View File

@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GetStepGoalRequest extends Request {
public int stepGoal = -1;
@Override

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GetTripleTapEnabledRequest extends Request {
@Override
public byte[] getStartSequence() {

View File

@ -6,6 +6,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GetVibrationStrengthRequest extends Request {
public int strength = -1;

View File

@ -5,6 +5,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GoalTrackingGetRequest extends Request {
@Override
public void handleResponse(BluetoothGattCharacteristic characteristic) {

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class GoalTrackingSetRequest extends Request {
public GoalTrackingSetRequest(int id, boolean state) {

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class MoveHandsRequest extends Request {
public MoveHandsRequest(boolean moveRelative, short degreesMin, short degreesHour, short degreesSub){
init(moveRelative, degreesMin, degreesHour, degreesSub);

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import android.bluetooth.BluetoothGattCharacteristic;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class OTAEnterRequest extends Request {
public boolean success = false;

View File

@ -6,6 +6,8 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class OTAEraseRequest extends Request {
public OTAEraseRequest(int pageOffset) {

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class OTAResetRequest extends Request {
@Override
public byte[] getStartSequence() {

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import java.security.InvalidParameterException;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class PlayNotificationRequest extends Request {
public enum VibrationType{

View File

@ -1,5 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class PutSettingsFileRequest extends Request {
@Override
public byte[] getStartSequence() {

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class ReleaseHandsControlRequest extends Request {
public ReleaseHandsControlRequest(){
super();

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class RequestHandControlRequest extends Request {
public RequestHandControlRequest(byte priority, boolean moveCompleteNotify, boolean controlLostNOtify){
super();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetCountdownSettings extends Request {
public SetCountdownSettings(int startTime, int endTime, short offset) {
ByteBuffer buffer = createBuffer();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetCurrentStepCountRequest extends Request {
public SetCurrentStepCountRequest(int steps){
super();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetCurrentTimeServiceRequest extends Request {
public SetCurrentTimeServiceRequest(int timeStampSecs, short millis, short offsetInMins){
super();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetStepGoalRequest extends Request {
public SetStepGoalRequest(int goal){
super();

View File

@ -2,6 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetTimeRequest extends Request {
public SetTimeRequest(int epochSeconds, short millis, short minutesOffset) {
ByteBuffer buffer = createBuffer();

View File

@ -1,6 +1,8 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit;
public class SetTripleTapEnabledRequest extends Request{
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetTripleTapEnabledRequest extends Request {
@Override
public byte[] getStartSequence() {
return new byte[]{2, 7, 3, 1};

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SetVibrationStrengthRequest extends Request {
public SetVibrationStrengthRequest(short strength){
super();

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class SettingsFilePutRequest extends Request {
public int fileLength;
public byte[] file;

View File

@ -8,6 +8,8 @@ import java.util.ArrayList;
import java.util.UUID;
import java.util.zip.CRC32;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class UploadFileRequest extends Request {
public enum UploadState{INITIALIZED, UPLOAD, UPLOADED, ERROR}

View File

@ -3,6 +3,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.mi
import java.nio.ByteBuffer;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request;
public class VibrateRequest extends Request {
public VibrateRequest(boolean longVibration, short repeats, short millisBetween){