diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e792e65b9..869dc3998 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -814,7 +814,7 @@
android:exported="true"
android:parentActivityName=".devices.qhybrid.HRConfigActivity" />
. */
+package nodomain.freeyourgadget.gadgetbridge.activities.calibration;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
+import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.util.GB;
+
+public class HandCalibrationActivity extends AbstractGBActivity {
+ private GBDevice device;
+ private boolean shouldSave;
+
+ enum HAND {
+ MINUTE,
+ HOUR,
+ SUB;
+
+ public String getDisplayName() {
+ return name().substring(0, 1).toUpperCase() + name().substring(1).toLowerCase();
+ }
+
+ public String getVariableName() {
+ return name();
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return getDisplayName();
+ }
+ }
+
+ enum MOVE_BUTTON {
+ CLOCKWISE_ONE(R.id.hand_calibration_clockwise_1, 1),
+ CLOCKWISE_TEN(R.id.hand_calibration_clockwise_10, 10),
+ CLOCKWISE_HUNDRED(R.id.hand_calibration_clockwise_100, 100),
+
+ COUNTER_CLOCKWISE_ONE(R.id.hand_calibration_counter_clockwise_1, -1),
+ COUNTER_CLOCKWISE_TEN(R.id.hand_calibration_counter_clockwise_10, -10),
+ COUNTER_CLOCKWISE_HUNDRED(R.id.hand_calibration_counter_clockwise_100, -100),
+ ;
+
+ private final int layoutId;
+ private final int distance;
+
+ MOVE_BUTTON(final int layoutId, final int distance) {
+ this.layoutId = layoutId;
+ this.distance = distance;
+ }
+ }
+
+ HAND selectedHand = HAND.MINUTE;
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ device = getIntent().getParcelableExtra(GBDevice.EXTRA_DEVICE);
+ if (device == null || !device.isInitialized()) {
+ GB.toast(getString(R.string.watch_not_connected), Toast.LENGTH_SHORT, GB.INFO);
+ finish();
+ }
+
+ setContentView(R.layout.activity_hand_calibration);
+
+ final FloatingActionButton fab = findViewById(R.id.fab_hand_calibration_save);
+ fab.setOnClickListener(view -> {
+ // TODO save
+ shouldSave = true;
+ finish();
+ });
+
+ // TODO start calibration
+
+ initViews();
+ }
+
+ private void initViews() {
+ final Spinner handSpinner = findViewById(R.id.hand_calibration_hand_spinner);
+ handSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, HAND.values()));
+ handSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(final AdapterView> parent, final View view, final int position, final long id) {
+ selectedHand = (HAND) parent.getSelectedItem();
+ }
+
+ @Override
+ public void onNothingSelected(final AdapterView> parent) {
+
+ }
+ });
+
+ for (final MOVE_BUTTON buttonDeclaration : MOVE_BUTTON.values()) {
+ final Button button = findViewById(buttonDeclaration.layoutId);
+
+ button.setOnClickListener(v -> {
+ final short step = (short) buttonDeclaration.distance;
+
+ // TODO move
+ });
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ finish();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (!shouldSave) {
+ // If we're supposed to save, we already did it in the fab
+ // TODO abort
+ //GBApplication.deviceService(device).onGenericCommand();
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == android.R.id.home) {
+ // back button
+ // TODO abort
+ //GBApplication.deviceService(device).onGenericCommand();
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/calibration/HandCalibrationHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/calibration/HandCalibrationHandler.java
new file mode 100644
index 000000000..a2038d3cf
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/calibration/HandCalibrationHandler.java
@@ -0,0 +1,53 @@
+package nodomain.freeyourgadget.gadgetbridge.activities.calibration;
+
+import android.os.Bundle;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HandCalibrationHandler {
+ private static final Logger LOG = LoggerFactory.getLogger(HandCalibrationHandler.class);
+
+ public static final String ACTION_CALIBRATION_START = "qhybrid_command_save_calibration1";
+ public static final String ACTION_CALIBRATION_END = "qhybrid_command_save_calibration2";
+ public static final String ACTION_CALIBRATION_MOVE = "qhybrid_command_save_calibration3";
+
+ private final Callback mCallback;
+
+ public HandCalibrationHandler(final Callback callback) {
+ this.mCallback = callback;
+ }
+
+ public void onGenericCommand(final Bundle bundle) {
+ final String action = bundle.getString("asd");
+ if (action == null) {
+ LOG.warn("Got null action");
+ return;
+ }
+
+ switch (action) {
+ case ACTION_CALIBRATION_START: {
+ mCallback.onHandCalibrationStart();
+ break;
+ }
+ case ACTION_CALIBRATION_END: {
+ //mCallback.onHandCalibrationEnd();
+ break;
+ }
+ case ACTION_CALIBRATION_MOVE: {
+ //mCallback.onHandCalibrationMove();
+ break;
+ }
+ }
+ }
+
+ public void register() {
+
+ }
+
+ public interface Callback {
+ void onHandCalibrationStart();
+ void onHandCalibrationEnd(boolean save);
+ void onHandCalibrationMove(int hand, int direction, int step);
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
index ac1ba0ff4..ffed258cb 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java
@@ -633,13 +633,10 @@ public class GBDeviceAdapterv2 extends ListAdapter {
+ Intent startIntent = new Intent(context, coordinator.getCalibrationActivity());
+ startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
+ context.startActivity(startIntent);
});
holder.fmFrequencyBox.setVisibility(View.GONE);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java
index e11671d44..c63fbea12 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/EventHandler.java
@@ -154,4 +154,6 @@ public interface EventHandler {
void onSleepAsAndroidAction(String action, Bundle extras);
void onCameraStatusChange(GBDeviceEventCameraRemote.Event event, String filename);
+
+ void onGenericCommand(int type, Bundle data);
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveHrCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveHrCoordinator.java
index 49b12e38c..8f184a844 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveHrCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveHrCoordinator.java
@@ -1,9 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivomove;
+import android.app.Activity;
+
+import androidx.annotation.Nullable;
+
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationActivity;
public class GarminVivomoveHrCoordinator extends GarminCoordinator {
@Override
@@ -15,4 +20,10 @@ public class GarminVivomoveHrCoordinator extends GarminCoordinator {
public int getDeviceNameResource() {
return R.string.devicetype_garmin_vivomove_hr;
}
+
+ @Nullable
+ @Override
+ public Class extends Activity> getCalibrationActivity() {
+ return HandCalibrationActivity.class;
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveStyleCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveStyleCoordinator.java
index 1dcb41b1f..16f901ce9 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveStyleCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveStyleCoordinator.java
@@ -1,8 +1,13 @@
package nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivomove;
+import android.app.Activity;
+
+import androidx.annotation.Nullable;
+
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminCoordinator;
public class GarminVivomoveStyleCoordinator extends GarminCoordinator {
@@ -15,4 +20,10 @@ public class GarminVivomoveStyleCoordinator extends GarminCoordinator {
public int getDeviceNameResource() {
return R.string.devicetype_garmin_vivomove_style;
}
+
+ @Nullable
+ @Override
+ public Class extends Activity> getCalibrationActivity() {
+ return HandCalibrationActivity.class;
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveTrendCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveTrendCoordinator.java
index 4325598c4..ce0cac1a1 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveTrendCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/garmin/watches/vivomove/GarminVivomoveTrendCoordinator.java
@@ -1,9 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivomove;
+import android.app.Activity;
+
+import androidx.annotation.Nullable;
+
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.GarminCoordinator;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationActivity;
public class GarminVivomoveTrendCoordinator extends GarminCoordinator {
@Override
@@ -15,4 +20,11 @@ public class GarminVivomoveTrendCoordinator extends GarminCoordinator {
public int getDeviceNameResource() {
return R.string.devicetype_garmin_vivomove_trend;
}
+
+ @Nullable
+ @Override
+ public Class extends Activity> getCalibrationActivity() {
+ // untested!
+ return HandCalibrationActivity.class;
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/CalibrationActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/CalibrationActivity.java
deleted file mode 100644
index b0e4157ec..000000000
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/CalibrationActivity.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (C) 2020-2024 Daniel Dakhno, José Rebelo
-
- 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 . */
-package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.Spinner;
-import android.widget.SpinnerAdapter;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
-
-import java.util.List;
-
-import nodomain.freeyourgadget.gadgetbridge.GBApplication;
-import nodomain.freeyourgadget.gadgetbridge.R;
-import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
-import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
-import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
-import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
-
-public class CalibrationActivity extends AbstractGBActivity {
- enum HAND{
- MINUTE,
- HOUR,
- SUB;
-
- public String getDisplayName(){
- return name().substring(0, 1).toUpperCase() + name().substring(1).toLowerCase();
- }
-
- public String getVariableName(){
- return name();
- }
-
-
- @NonNull
- @Override
- public String toString() {
- return getDisplayName();
- }
- }
-
- enum MOVE_BUTTON{
- CLOCKWISE_ONE(R.id.qhybrid_calibration_clockwise_1, 1),
- CLOCKWISE_TEN(R.id.qhybrid_calibration_clockwise_10, 10),
- CLOCKWISE_HUNRED(R.id.qhybrid_calibration_clockwise_100, 100),
-
- COUNTER_CLOCKWISE_ONE(R.id.qhybrid_calibration_counter_clockwise_1, -1),
- COUNTER_CLOCKWISE_TEN(R.id.qhybrid_calibration_counter_clockwise_10, -10),
- COUNTER_CLOCKWISE_HUNRED(R.id.qhybrid_calibration_counter_clockwise_100, -100),
- ;
-
- int layoutId;
- int distance;
-
- MOVE_BUTTON(int layoutId, int distance) {
- this.layoutId = layoutId;
- this.distance = distance;
- }
- }
-
- HAND selectedHand = HAND.MINUTE;
- LocalBroadcastManager localBroadcastManager;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_qhybrid_calibration);
-
- List devices = GBApplication.app().getDeviceManager().getSelectedDevices();
- boolean atLeastOneConnected = false;
- for(GBDevice device : devices){
- if(device.getType() == DeviceType.FOSSILQHYBRID){
- atLeastOneConnected = true;
- break;
- }
- }
-
- if(!atLeastOneConnected){
- Toast.makeText(this, R.string.watch_not_connected, Toast.LENGTH_LONG).show();
- finish();
- return;
- }
-
- localBroadcastManager = LocalBroadcastManager.getInstance(this);
-
- localBroadcastManager.sendBroadcast(
- new Intent(QHybridSupport.QHYBRID_COMMAND_CONTROL)
- );
-
- initViews();
- }
-
- private void initViews(){
- Spinner handSpinner = findViewById(R.id.qhybrid_calibration_hand_spinner);
- handSpinner.setAdapter(new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, HAND.values()));
- handSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- selectedHand = (HAND) parent.getSelectedItem();
- }
-
- @Override
- public void onNothingSelected(AdapterView> parent) {
-
- }
- });
-
- for(final MOVE_BUTTON buttonDeclaration : MOVE_BUTTON.values()) {
- final Button button = findViewById(buttonDeclaration.layoutId);
-
- button.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(QHybridSupport.QHYBRID_COMMAND_MOVE);
- intent.putExtra("EXTRA_DISTANCE_" + selectedHand.getVariableName(), (short) buttonDeclaration.distance);
-
- localBroadcastManager.sendBroadcast(intent);
- }
- });
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- finish();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (localBroadcastManager != null) {
- localBroadcastManager.sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_SAVE_CALIBRATION));
- localBroadcastManager.sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UNCONTROL));
- }
- }
-}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
index cba18d037..d99d50fef 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/QHybridCoordinator.java
@@ -39,6 +39,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
@@ -183,6 +184,11 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
return isHybridHR() ? HybridHRWatchfaceDesignerActivity.class : null;
}
+ @Override
+ public Class extends Activity> getCalibrationActivity() {
+ return isHybridHR() ? HandCalibrationActivity.class : null;
+ }
+
/**
* Returns the directory containing the watch app cache.
* @throws IOException when the external files directory cannot be accessed
@@ -253,7 +259,6 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
generic.add(R.xml.devicesettings_fossilhybridhr_pre_fw220);
}
// Settings applicable to all firmware versions
- generic.add(R.xml.devicesettings_fossilhybridhr_calibration);
generic.add(R.xml.devicesettings_fossilhybridhr_navigation);
final List health = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.HEALTH);
health.add(R.xml.devicesettings_fossilhybridhr_workout_detection);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
index e8106c691..e8a984687 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestDeviceCoordinator.java
@@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@@ -540,8 +541,7 @@ public class TestDeviceCoordinator extends AbstractDeviceCoordinator {
@Nullable
@Override
public Class extends Activity> getCalibrationActivity() {
- // TODO getCalibrationActivity
- return super.getCalibrationActivity();
+ return supports(getTestDevice(), TestFeature.CALIBRATION) ? HandCalibrationActivity.class : null;
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestFeature.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestFeature.java
index ed5a485f4..fd7835239 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestFeature.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/test/TestFeature.java
@@ -28,6 +28,7 @@ public enum TestFeature {
APP_LIST_FETCHING,
APP_REORDERING,
APPS_MANAGEMENT,
+ CALIBRATION,
BATTERIES_MULTIPLE,
CACHED_APP_MANAGEMENT,
CALENDAR_EVENTS,
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
index bf5b5280f..320c31134 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java
@@ -568,4 +568,12 @@ public class GBDeviceService implements DeviceService {
intent.putExtra(EXTRA_CAMERA_FILENAME, filename);
invokeService(intent);
}
+
+ @Override
+ public void onGenericCommand(final int type, final Bundle data) {
+ Intent intent = createIntent().setAction(ACTION_GENERIC_COMMAND);
+ intent.putExtra(EXTRA_GENERIC_COMMAND_TYPE, type);
+ intent.putExtra(EXTRA_GENERIC_COMMAND_DATA, data);
+ invokeService(intent);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
index 79c40d8f5..3421303ad 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java
@@ -80,6 +80,7 @@ public interface DeviceService extends EventHandler {
String ACTION_SET_LED_COLOR = PREFIX + ".action.set_led_color";
String ACTION_POWER_OFF = PREFIX + ".action.power_off";
String ACTION_CAMERA_STATUS_CHANGE = PREFIX + ".action.camera_status_change";
+ String ACTION_GENERIC_COMMAND = PREFIX + ".action.generic_command";
String ACTION_SLEEP_AS_ANDROID = ".action.sleep_as_android";
String EXTRA_SLEEP_AS_ANDROID_ACTION = "sleepasandroid_action";
@@ -147,6 +148,8 @@ public interface DeviceService extends EventHandler {
String EXTRA_RESET_FLAGS = "reset_flags";
String EXTRA_CAMERA_EVENT = "event";
String EXTRA_CAMERA_FILENAME = "filename";
+ String EXTRA_GENERIC_COMMAND_TYPE = "type";
+ String EXTRA_GENERIC_COMMAND_DATA = "data";
/**
* Use EXTRA_REALTIME_SAMPLE instead
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
index 0a432a70e..8eceaaa0d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
@@ -1230,4 +1230,6 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
@Override
public void onCameraStatusChange(GBDeviceEventCameraRemote.Event event, String filename) {}
+
+ public void onGenericCommand(int type, Bundle data) {}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
index a309d3ed4..30c3d0eb9 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java
@@ -1127,6 +1127,11 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
}
deviceSupport.onCameraStatusChange(event, filename);
break;
+ case ACTION_GENERIC_COMMAND:
+ final int genericCommandType = intentCopy.getIntExtra(EXTRA_GENERIC_COMMAND_TYPE, 0);
+ final Bundle genericCommandData = intentCopy.getBundleExtra(EXTRA_GENERIC_COMMAND_DATA);
+ deviceSupport.onGenericCommand(genericCommandType, genericCommandData);
+ break;
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
index ad01d2cb8..73b2d0520 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java
@@ -524,4 +524,12 @@ public class ServiceDeviceSupport implements DeviceSupport {
}
delegate.onCameraStatusChange(event, filename);
}
+
+ @Override
+ public void onGenericCommand(int type, Bundle data) {
+ if (checkBusy("generic command " + type)) {
+ return;
+ }
+ delegate.onGenericCommand(type, data);
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java
index cab947e13..9b319ed79 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java
@@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
+import nodomain.freeyourgadget.gadgetbridge.activities.calibration.HandCalibrationHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.devices.PendingFileProvider;
@@ -52,6 +53,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiCore;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiDeviceStatus;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiFindMyWatch;
+import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiHandCalibrationService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiSettingsService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiSmartProto;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
@@ -87,7 +89,8 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SEND_APP_NOTIFICATIONS;
-public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommunicator.Callback {
+public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommunicator.Callback,
+ HandCalibrationHandler.Callback {
private static final Logger LOG = LoggerFactory.getLogger(GarminSupport.class);
private final ProtocolBufferHandler protocolBufferHandler;
private final NotificationsHandler notificationsHandler;
@@ -310,7 +313,9 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
super.evaluateGBDeviceEvent(deviceEvent);
}
- /** @noinspection BooleanMethodIsAlwaysInverted*/
+ /**
+ * @noinspection BooleanMethodIsAlwaysInverted
+ */
private boolean getKeepActivityDataOnDevice() {
return getDevicePrefs().getBoolean("keep_activity_data_on_device", false);
}
@@ -826,9 +831,26 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
}
}
+ int i = 0;
+
@Override
public void onTestNewFunction() {
- parseAllFitFilesFromStorage();
+ switch (i) {
+ case 0:
+ onHandCalibrationStart();
+ break;
+ case 1:
+ onHandCalibrationMove(1, 1, 1);
+ break;
+ case 2:
+ onHandCalibrationMove(1, 2, 10);
+ break;
+ case 3:
+ onHandCalibrationEnd(false);
+ break;
+ }
+
+ i++;
}
boolean parsingFitFilesFromStorage = false;
@@ -906,4 +928,45 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni
}
});
}
+
+ @Override
+ public void onHandCalibrationStart() {
+ sendOutgoingMessage("onHandCalibrationStart", protocolBufferHandler.prepareProtobufRequest(GdiSmartProto.Smart.newBuilder()
+ .setHandCalibrationService(
+ GdiHandCalibrationService.HandCalibrationService.newBuilder()
+ .setStartRequest(
+ GdiHandCalibrationService.HandCalibrationService.StartRequest.newBuilder()
+ .setCommand(1)
+ )
+ )
+ ));
+ }
+
+ @Override
+ public void onHandCalibrationEnd(final boolean save) {
+ sendOutgoingMessage("onHandCalibrationEnd", protocolBufferHandler.prepareProtobufRequest(GdiSmartProto.Smart.newBuilder()
+ .setHandCalibrationService(
+ GdiHandCalibrationService.HandCalibrationService.newBuilder()
+ .setStartRequest(
+ GdiHandCalibrationService.HandCalibrationService.StartRequest.newBuilder()
+ .setCommand(save ? 3 : 2)
+ )
+ )
+ ));
+ }
+
+ @Override
+ public void onHandCalibrationMove(final int hand, final int direction, final int step) {
+ sendOutgoingMessage("onHandCalibrationMove", protocolBufferHandler.prepareProtobufRequest(GdiSmartProto.Smart.newBuilder()
+ .setHandCalibrationService(
+ GdiHandCalibrationService.HandCalibrationService.newBuilder()
+ .setMoveRequest(
+ GdiHandCalibrationService.HandCalibrationService.MoveRequest.newBuilder()
+ .setHand(hand)
+ .setDirection(direction)
+ .setUnk3(step)
+ )
+ )
+ ));
+ }
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/ProtocolBufferHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/ProtocolBufferHandler.java
index 14c55d958..33defe259 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/ProtocolBufferHandler.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/ProtocolBufferHandler.java
@@ -31,6 +31,7 @@ import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiCore;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiDataTransferService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiDeviceStatus;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiFindMyWatch;
+import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiHandCalibrationService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiHttpService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiSettingsService;
import nodomain.freeyourgadget.gadgetbridge.proto.garmin.GdiSmartProto;
@@ -124,6 +125,18 @@ public class ProtocolBufferHandler implements MessageHandler {
processed = true;
processProtobufFindMyWatchResponse(smart.getFindMyWatchService());
}
+ if (smart.hasHandCalibrationService()) {
+ processed = true;
+
+ final GdiHandCalibrationService.HandCalibrationService handCalibrationService = smart.getHandCalibrationService();
+ if (handCalibrationService.hasStartResponse()) {
+ LOG.debug("Got hand calibration start response, status={}", handCalibrationService.getStartResponse().getStatus());
+ } else if (handCalibrationService.hasMoveResponse()) {
+ LOG.debug("Got hand calibration move response, status={}", handCalibrationService.getMoveResponse().getStatus());
+ } else {
+ LOG.warn("Got unknown hand calibration response {}", smart);
+ }
+ }
if (smart.hasSettingsService()) {
processed = true;
processProtobufSettingsService(smart.getSettingsService());
@@ -439,6 +452,10 @@ public class ProtocolBufferHandler implements MessageHandler {
return processed;
}
+ public ProtobufMessage prepareProtobufRequest(GdiSmartProto.Smart.Builder protobufPayloadBuilder) {
+ return prepareProtobufRequest(protobufPayloadBuilder.build());
+ }
+
public ProtobufMessage prepareProtobufRequest(GdiSmartProto.Smart protobufPayload) {
if (null == protobufPayload)
return null;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
index 19fbb40b7..f517003c3 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
@@ -83,8 +83,8 @@ public class QHybridSupport extends QHybridBaseSupport {
public static final String QHYBRID_COMMAND_CONTROL = "qhybrid_command_control";
public static final String QHYBRID_COMMAND_UNCONTROL = "qhybrid_command_uncontrol";
public static final String QHYBRID_COMMAND_SET = "qhybrid_command_set";
- public static final String QHYBRID_COMMAND_MOVE = "qhybrid_command_move";
- public static final String QHYBRID_COMMAND_SAVE_CALIBRATION = "qhybrid_command_save_calibration";
+ public static final String QHYBRID_COMMAND_MOVE = "qhybrid_command_move"; // TODO deprecated
+ public static final String QHYBRID_COMMAND_SAVE_CALIBRATION = "qhybrid_command_save_calibration"; // TODO deprecated
public static final String QHYBRID_COMMAND_VIBRATE = "qhybrid_command_vibrate";
public static final String QHYBRID_COMMAND_UPDATE = "qhybrid_command_update";
public static final String QHYBRID_COMMAND_UPDATE_TIMEZONE = "qhybrid_command_update_timezone";
diff --git a/app/src/main/proto/garmin/gdi_hand_calibration_service.proto b/app/src/main/proto/garmin/gdi_hand_calibration_service.proto
new file mode 100644
index 000000000..feb93b9cf
--- /dev/null
+++ b/app/src/main/proto/garmin/gdi_hand_calibration_service.proto
@@ -0,0 +1,27 @@
+syntax = "proto2";
+
+package garmin_vivomovehr;
+
+option java_package = "nodomain.freeyourgadget.gadgetbridge.proto.garmin";
+
+message HandCalibrationService {
+ optional StartRequest startRequest = 1;
+ optional StartResponse startResponse = 2;
+ optional MoveRequest moveRequest = 3;
+ optional MoveResponse moveResponse = 4;
+
+ message StartRequest {
+ optional uint32 command = 1; // 1 start 2 abort 3 save
+ }
+ message StartResponse {
+ optional uint32 status = 1; // 1
+ }
+ message MoveRequest {
+ optional uint32 hand = 1; // 1 hour 2 minute
+ optional uint32 direction = 2; // 1 + 2 -
+ optional uint32 unk3 = 3; // 1 - step?
+ }
+ message MoveResponse {
+ optional uint32 status = 1; // 1
+ }
+}
diff --git a/app/src/main/proto/garmin/gdi_smart_proto.proto b/app/src/main/proto/garmin/gdi_smart_proto.proto
index 218592db3..b2c4cdaa1 100644
--- a/app/src/main/proto/garmin/gdi_smart_proto.proto
+++ b/app/src/main/proto/garmin/gdi_smart_proto.proto
@@ -11,6 +11,7 @@ import "garmin/gdi_http_service.proto";
import "garmin/gdi_data_transfer_service.proto";
import "garmin/gdi_sms_notification.proto";
import "garmin/gdi_calendar_service.proto";
+import "garmin/gdi_hand_calibration_service.proto";
import "garmin/gdi_settings_service.proto";
message Smart {
@@ -21,6 +22,7 @@ message Smart {
optional FindMyWatchService find_my_watch_service = 12;
optional CoreService core_service = 13;
optional SmsNotificationService sms_notification_service = 16;
+ optional HandCalibrationService hand_calibration_service = 33;
optional SettingsService settings_service = 42;
}
diff --git a/app/src/main/res/layout/activity_qhybrid_calibration.xml b/app/src/main/res/layout/activity_hand_calibration.xml
similarity index 68%
rename from app/src/main/res/layout/activity_qhybrid_calibration.xml
rename to app/src/main/res/layout/activity_hand_calibration.xml
index 93fa46da9..9dcd35edd 100644
--- a/app/src/main/res/layout/activity_qhybrid_calibration.xml
+++ b/app/src/main/res/layout/activity_hand_calibration.xml
@@ -1,5 +1,6 @@
@@ -15,13 +16,14 @@
android:text="@string/qhybrid_calibration_align_hint" />
+ android:layout_height="wrap_content" />
@@ -29,30 +31,30 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
- android:gravity="center_horizontal">
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ android:text="@string/qhybrid_calibration_counterclockwise" />
@@ -61,30 +63,30 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
- android:gravity="center_horizontal">
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ android:text="@string/qhybrid_calibration_clockwise" />
@@ -93,4 +95,15 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/device_itemv2.xml b/app/src/main/res/layout/device_itemv2.xml
index cbde32e0f..95d6c3e94 100644
--- a/app/src/main/res/layout/device_itemv2.xml
+++ b/app/src/main/res/layout/device_itemv2.xml
@@ -441,7 +441,7 @@
android:focusable="true"
android:padding="3dp"
android:scaleType="fitXY"
- card_view:srcCompat="@drawable/ic_activity_unknown"
+ card_view:srcCompat="@drawable/ic_sensor_calibration"
card_view:tint="@color/secondarytext" />
-
-
-
-
-
-
-