mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-27 12:26:48 +01:00
Casio GBX-100: Add step count data and more device settings
Co-Authored-By: andyboeh <andyboeh@noreply.codeberg.org> Co-Committed-By: andyboeh <andyboeh@noreply.codeberg.org>
This commit is contained in:
parent
074bc885c8
commit
02b85f4c11
@ -43,7 +43,7 @@ public class GBDaoGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Schema schema = new Schema(31, MAIN_PACKAGE + ".entities");
|
||||
Schema schema = new Schema(32, MAIN_PACKAGE + ".entities");
|
||||
|
||||
Entity userAttributes = addUserAttributes(schema);
|
||||
Entity user = addUserInfo(schema, userAttributes);
|
||||
@ -79,6 +79,7 @@ public class GBDaoGenerator {
|
||||
addLefunSleepSample(schema, user, device);
|
||||
addSonySWR12Sample(schema, user, device);
|
||||
addBangleJSActivitySample(schema, user, device);
|
||||
addCasioGBX100Sample(schema, user, device);
|
||||
|
||||
addHybridHRActivitySample(schema, user, device);
|
||||
addCalendarSyncState(schema, device);
|
||||
@ -420,6 +421,16 @@ public class GBDaoGenerator {
|
||||
return activitySample;
|
||||
}
|
||||
|
||||
private static Entity addCasioGBX100Sample(Schema schema, Entity user, Entity device) {
|
||||
Entity activitySample = addEntity(schema, "CasioGBX100ActivitySample");
|
||||
activitySample.implementsSerializable();
|
||||
addCommonActivitySampleProperties("AbstractGBX100ActivitySample", activitySample, user, device);
|
||||
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
|
||||
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
|
||||
activitySample.addIntProperty("calories").notNull();
|
||||
return activitySample;
|
||||
}
|
||||
|
||||
private static Entity addLefunActivitySample(Schema schema, Entity user, Entity device) {
|
||||
Entity activitySample = addEntity(schema, "LefunActivitySample");
|
||||
activitySample.implementsSerializable();
|
||||
|
@ -52,6 +52,11 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREF_LONGSIT_SWITCH_NOSHED = "screen_longsit_noshed";
|
||||
public static final String PREF_DO_NOT_DISTURB_NOAUTO = "do_not_disturb_no_auto";
|
||||
public static final String PREF_FIND_PHONE_ENABLED = "prefs_find_phone";
|
||||
public static final String PREF_AUTOLIGHT = "autolight";
|
||||
public static final String PREF_AUTOREMOVE_MESSAGE = "autoremove_message";
|
||||
public static final String PREF_OPERATING_SOUNDS = "operating_sounds";
|
||||
public static final String PREF_KEY_VIBRATION = "key_vibration";
|
||||
public static final String PREF_FAKE_RING_DURATION = "fake_ring_duration";
|
||||
|
||||
public static final String PREF_ANTILOST_ENABLED = "pref_antilost_enabled";
|
||||
public static final String PREF_HYDRATION_SWITCH = "pref_hydration_switch";
|
||||
|
@ -48,6 +48,8 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AMPM_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ANTILOST_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BT_CONNECTED_ADVERTISEMENT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOLIGHT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOREMOVE_MESSAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_1_FUNCTION_DOUBLE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_1_FUNCTION_LONG;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_1_FUNCTION_SHORT;
|
||||
@ -61,17 +63,20 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DISCONNECTNOTIF_NOSHED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FAKE_RING_DURATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FIND_PHONE_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_FORCE_WHITE_COLOR;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYDRATION_PERIOD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYDRATION_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_KEY_VIBRATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LANGUAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LEFUN_INTERFACE_LANGUAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_OPERATING_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_POWER_MODE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_ORIENTATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONYSWR12_LOW_VIBRATION;
|
||||
@ -383,6 +388,11 @@ public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat {
|
||||
addPreferenceHandlerFor(PREF_LONGSIT_SWITCH);
|
||||
addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO);
|
||||
addPreferenceHandlerFor(PREF_FIND_PHONE_ENABLED);
|
||||
addPreferenceHandlerFor(PREF_AUTOLIGHT);
|
||||
addPreferenceHandlerFor(PREF_AUTOREMOVE_MESSAGE);
|
||||
addPreferenceHandlerFor(PREF_KEY_VIBRATION);
|
||||
addPreferenceHandlerFor(PREF_OPERATING_SOUNDS);
|
||||
addPreferenceHandlerFor(PREF_FAKE_RING_DURATION);
|
||||
addPreferenceHandlerFor(PREF_ANTILOST_ENABLED);
|
||||
addPreferenceHandlerFor(PREF_HYDRATION_SWITCH);
|
||||
addPreferenceHandlerFor(PREF_HYDRATION_PERIOD);
|
||||
|
@ -103,7 +103,7 @@ public final class CasioConstants {
|
||||
public static final byte CATEGORY_CONDITION = 12;
|
||||
public static final byte CATEGORY_EMAIL = 6;
|
||||
public static final byte CATEGORY_ENTERTAINMENT = 11;
|
||||
public static final byte CATEGORY_HEATH_AND_FITNESS = 8;
|
||||
public static final byte CATEGORY_HEALTH_AND_FITNESS = 8;
|
||||
public static final byte CATEGORY_INCOMING_CALL = 1;
|
||||
public static final byte CATEGORY_LOCATION = 10;
|
||||
public static final byte CATEGORY_MISSED_CALL = 2;
|
||||
@ -129,9 +129,21 @@ public final class CasioConstants {
|
||||
OPTION_STEP_GOAL,
|
||||
OPTION_DISTANCE_GOAL,
|
||||
OPTION_ACTIVITY_GOAL,
|
||||
OPTION_AUTOLIGHT,
|
||||
OPTION_TIMEFORMAT,
|
||||
OPTION_KEY_VIBRATION,
|
||||
OPTION_OPERATING_SOUNDS,
|
||||
OPTION_ALL
|
||||
}
|
||||
|
||||
public static final int CASIO_CONVOY_DATATYPE_STEPS = 0x04;
|
||||
public static final int CASIO_CONVOY_DATATYPE_CALORIES = 0x05;
|
||||
|
||||
public static final int CASIO_FAKE_RING_SLEEP_DURATION = 3000;
|
||||
public static final int CASIO_FAKE_RING_RETRIES = 10;
|
||||
|
||||
public static final int CASIO_AUTOREMOVE_MESSAGE_DELAY = 10000;
|
||||
|
||||
public static Map<String, Byte> characteristicToByte = new HashMap<String, Byte>() {
|
||||
{
|
||||
put("CASIO_WATCH_NAME", (byte) 0x23);
|
||||
@ -150,6 +162,10 @@ public final class CasioConstants {
|
||||
put("CASIO_SETTING_FOR_USER_PROFILE", (byte) 0x45);
|
||||
put("CASIO_SETTING_FOR_TARGET_VALUE", (byte) 0x43);
|
||||
put("ALERT_LEVEL", (byte) 0x0a);
|
||||
put("CASIO_SETTING_FOR_ALM", (byte) 0x15);
|
||||
put("CASIO_SETTING_FOR_ALM2", (byte) 0x16);
|
||||
put("CASIO_SETTING_FOR_BASIC", (byte) 0x13);
|
||||
put("CASIO_CURRENT_TIME_MANAGER", (byte) 0x39);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
/* Copyright (C) 2018-2020 Cre3per, Daniele Gobbetti, Sebastian Kranz
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.casio;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.greenrobot.dao.AbstractDao;
|
||||
import de.greenrobot.dao.Property;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class CasioGBX100SampleProvider extends AbstractSampleProvider<CasioGBX100ActivitySample> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CasioGBX100SampleProvider.class);
|
||||
|
||||
public CasioGBX100SampleProvider(GBDevice device, DaoSession session) {
|
||||
super(device, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int normalizeType(int rawType) {
|
||||
return rawType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toRawActivityKind(int activityKind) {
|
||||
return activityKind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float normalizeIntensity(int rawIntensity) {
|
||||
// The magic number 1500 is based on
|
||||
// https://www.livestrong.com/article/474836-what-sport-burns-the-most-calories-per-hour/
|
||||
return (rawIntensity / 1500f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CasioGBX100ActivitySample createActivitySample() {
|
||||
return new CasioGBX100ActivitySample();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractDao<CasioGBX100ActivitySample, ?> getSampleDao() {
|
||||
return getSession().getCasioGBX100ActivitySampleDao();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Property getRawKindSampleProperty() {
|
||||
return CasioGBX100ActivitySampleDao.Properties.RawKind;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getTimestampSampleProperty() {
|
||||
return CasioGBX100ActivitySampleDao.Properties.Timestamp;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getDeviceIdentifierSampleProperty() {
|
||||
return CasioGBX100ActivitySampleDao.Properties.DeviceId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<CasioGBX100ActivitySample> getActivitySamples(int timestamp_from, int timestamp_to) {
|
||||
return super.getActivitySamples(timestamp_from, timestamp_to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CasioGBX100ActivitySample> getAllActivitySamples(int timestamp_from, int timestamp_to) {
|
||||
return super.getActivitySamples(timestamp_from, timestamp_to);
|
||||
}
|
||||
}
|
@ -26,12 +26,15 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioGBX100SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
@ -97,17 +100,17 @@ public class CasioGBX100DeviceCoordinator extends AbstractDeviceCoordinator {
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityDataFetching() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsActivityTracking() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
||||
return null;
|
||||
return new CasioGBX100SampleProvider(device, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -147,14 +150,22 @@ public class CasioGBX100DeviceCoordinator extends AbstractDeviceCoordinator {
|
||||
|
||||
@Override
|
||||
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
|
||||
|
||||
Long deviceId = device.getId();
|
||||
QueryBuilder<?> qb = session.getCasioGBX100ActivitySampleDao().queryBuilder();
|
||||
qb.where(CasioGBX100ActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
|
||||
return new int[]{
|
||||
R.xml.devicesettings_find_phone,
|
||||
R.xml.devicesettings_wearlocation
|
||||
R.xml.devicesettings_wearlocation,
|
||||
R.xml.devicesettings_timeformat,
|
||||
R.xml.devicesettings_autolight,
|
||||
R.xml.devicesettings_key_vibration,
|
||||
R.xml.devicesettings_operating_sounds,
|
||||
R.xml.devicesettings_fake_ring_duration,
|
||||
R.xml.devicesettings_autoremove_message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -39,10 +40,17 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioGBX100SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.makibeshr3.MakibesHR3Constants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
@ -53,12 +61,20 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations.FetchStepCountDataOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations.GetConfigurationOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations.InitOperationGBX100;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations.SetConfigurationOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOLIGHT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOREMOVE_MESSAGE;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FAKE_RING_DURATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_FIND_PHONE_ENABLED;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_KEY_VIBRATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_OPERATING_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TIMEFORMAT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_ACTIVETIME_MINUTES;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_DISTANCE_METERS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.PREF_USER_GENDER;
|
||||
@ -72,9 +88,13 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
|
||||
private boolean mFirstConnect = false;
|
||||
private boolean mGetConfigurationPending = false;
|
||||
private ArrayList<Integer> mSyncedNotificationIDs = new ArrayList<>();
|
||||
private int mLastCallId = 0;
|
||||
private boolean mRingNotificationPending = false;
|
||||
private final ArrayList<Integer> mSyncedNotificationIDs = new ArrayList<>();
|
||||
private int mLastCallId = new AtomicInteger((int) (System.currentTimeMillis()/1000)).incrementAndGet();
|
||||
private int mFakeRingDurationCounter = 0;
|
||||
private final Handler mFindPhoneHandler = new Handler();
|
||||
private final Handler mFakeRingDurationHandler = new Handler();
|
||||
private final Handler mAutoRemoveMessageHandler = new Handler();
|
||||
|
||||
public CasioGBX100DeviceSupport() {
|
||||
super(LOG);
|
||||
@ -106,12 +126,20 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
getDevice().setFirmwareVersion("N/A");
|
||||
getDevice().setFirmwareVersion2("N/A");
|
||||
|
||||
SharedPreferences preferences = GBApplication.getDeviceSpecificSharedPrefs(this.getDevice().getAddress());
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
//preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
SharedPreferences prefs = GBApplication.getPrefs().getPreferences();
|
||||
prefs.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
if(mFirstConnect) {
|
||||
SharedPreferences preferences = GBApplication.getDeviceSpecificSharedPrefs(this.getDevice().getAddress());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
editor.putString("charts_tabs", "activity,activitylist,stepsweek");
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@ -128,6 +156,67 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
return super.onCharacteristicRead(gatt, characteristic, status);
|
||||
}
|
||||
|
||||
public CasioGBX100ActivitySample getSumWithinRange(int timestamp_from, int timestamp_to) {
|
||||
int steps = 0;
|
||||
int calories = 0;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
|
||||
User user = DBHelper.getUser(dbHandler.getDaoSession());
|
||||
Device device = DBHelper.getDevice(this.getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
CasioGBX100SampleProvider provider = new CasioGBX100SampleProvider(this.getDevice(), dbHandler.getDaoSession());
|
||||
List<CasioGBX100ActivitySample> samples = provider.getActivitySamples(timestamp_from, timestamp_to);
|
||||
for(CasioGBX100ActivitySample sample : samples) {
|
||||
if(sample.getDevice().equals(device) &&
|
||||
sample.getUser().equals(user)) {
|
||||
steps += sample.getSteps();
|
||||
calories += sample.getCalories();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error fetching activity data.");
|
||||
}
|
||||
|
||||
CasioGBX100ActivitySample ret = new CasioGBX100ActivitySample();
|
||||
ret.setCalories(calories);
|
||||
ret.setSteps(steps);
|
||||
LOG.debug("Fetched for today: " + calories + " cals and " + steps + " steps.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void addGBActivitySamples(ArrayList<CasioGBX100ActivitySample> samples) {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
|
||||
User user = DBHelper.getUser(dbHandler.getDaoSession());
|
||||
Device device = DBHelper.getDevice(this.getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
CasioGBX100SampleProvider provider = new CasioGBX100SampleProvider(this.getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
for (CasioGBX100ActivitySample sample : samples) {
|
||||
sample.setDevice(device);
|
||||
sample.setUser(user);
|
||||
sample.setProvider(provider);
|
||||
|
||||
provider.addGBActivitySample(sample);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
// Why is this a toast? The user doesn't care about the error.
|
||||
GB.toast(getContext(), "Error saving samples: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
|
||||
GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext());
|
||||
|
||||
LOG.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void stepCountDataFetched(int totalCount, int totalCalories, ArrayList<CasioGBX100ActivitySample> data) {
|
||||
LOG.info("Got the following step count data: ");
|
||||
LOG.info("Total Count: " + totalCount);
|
||||
LOG.info("Total Calories: " + totalCalories);
|
||||
|
||||
addGBActivitySamples(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
||||
BluetoothGattCharacteristic characteristic) {
|
||||
@ -144,7 +233,18 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
onReverseFindDevice(false);
|
||||
}
|
||||
return true;
|
||||
} else if(data[0] == CasioConstants.characteristicToByte.get("CASIO_CURRENT_TIME_MANAGER")) {
|
||||
if(data[1] == 0x00) {
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("writeCurrentTime");
|
||||
writeCurrentTime(builder);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
LOG.warn("writing current time failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + String.format("0x%1x ...", data[0]));
|
||||
@ -186,21 +286,22 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
arr[5] = (byte) 0x01; // Set to 0x00 to not vibrate/ring for this notification
|
||||
arr[6] = icon;
|
||||
// These bytes contain a timestamp, not yet decoded / implemented
|
||||
/*arr[7] = (byte) 0x32;
|
||||
arr[8] = (byte) 0x30;
|
||||
arr[9] = (byte) 0x32;
|
||||
arr[10] = (byte) 0x30;
|
||||
arr[11] = (byte) 0x31;
|
||||
arr[12] = (byte) 0x31;
|
||||
arr[13] = (byte) 0x31;
|
||||
arr[14] = (byte) 0x33;
|
||||
arr[15] = (byte) 0x54;
|
||||
arr[16] = (byte) 0x30;
|
||||
arr[17] = (byte) 0x39;
|
||||
arr[18] = (byte) 0x33;
|
||||
arr[19] = (byte) 0x31;
|
||||
arr[20] = (byte) 0x35;
|
||||
arr[21] = (byte) 0x33;*/
|
||||
// ASCII Codes:
|
||||
/*arr[7] = (byte) 0x32; // 2
|
||||
arr[8] = (byte) 0x30; // 0
|
||||
arr[9] = (byte) 0x32; // 2
|
||||
arr[10] = (byte) 0x30; // 0
|
||||
arr[11] = (byte) 0x31; // 1
|
||||
arr[12] = (byte) 0x31; // 1
|
||||
arr[13] = (byte) 0x31; // 1
|
||||
arr[14] = (byte) 0x33; // 3
|
||||
arr[15] = (byte) 0x54; // T
|
||||
arr[16] = (byte) 0x30; // 0
|
||||
arr[17] = (byte) 0x39; // 9
|
||||
arr[18] = (byte) 0x33; // 3
|
||||
arr[19] = (byte) 0x31; // 1
|
||||
arr[20] = (byte) 0x35; // 5
|
||||
arr[21] = (byte) 0x33;*/// 3
|
||||
byte[] copy = Arrays.copyOf(arr, arr.length + 2);
|
||||
copy[copy.length-2] = 0;
|
||||
copy[copy.length-1] = 0;
|
||||
@ -247,8 +348,9 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotification(NotificationSpec notificationSpec) {
|
||||
public void onNotification(final NotificationSpec notificationSpec) {
|
||||
byte icon;
|
||||
boolean autoremove = false;
|
||||
switch (notificationSpec.type.getGenericType()) {
|
||||
case "generic_calendar":
|
||||
icon = CasioConstants.CATEGORY_SCHEDULE_AND_ALARM;
|
||||
@ -256,13 +358,26 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
case "generic_email":
|
||||
icon = CasioConstants.CATEGORY_EMAIL;
|
||||
break;
|
||||
case "generic_sms":
|
||||
icon = CasioConstants.CATEGORY_SNS;
|
||||
SharedPreferences sharedPreferences = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||
autoremove = sharedPreferences.getBoolean(PREF_AUTOREMOVE_MESSAGE, false);
|
||||
break;
|
||||
default:
|
||||
icon = CasioConstants.CATEGORY_SNS;
|
||||
break;
|
||||
}
|
||||
LOG.info("onNotification id=" + notificationSpec.getId());
|
||||
showNotification(icon, notificationSpec.sender, notificationSpec.title, notificationSpec.body, notificationSpec.getId(), false);
|
||||
mSyncedNotificationIDs.add(new Integer(notificationSpec.getId()));
|
||||
mSyncedNotificationIDs.add(notificationSpec.getId());
|
||||
if(autoremove) {
|
||||
mAutoRemoveMessageHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onDeleteNotification(notificationSpec.getId());
|
||||
}
|
||||
}, CasioConstants.CASIO_AUTOREMOVE_MESSAGE_DELAY);
|
||||
}
|
||||
// The watch only holds up to 10 notifications. However, the user might have deleted
|
||||
// some notifications in the meantime, so to be sure, we keep the last 100 IDs.
|
||||
if(mSyncedNotificationIDs.size() > 100) {
|
||||
@ -273,7 +388,7 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
@Override
|
||||
public void onDeleteNotification(int id) {
|
||||
LOG.info("onDeleteNofication id=" + id);
|
||||
Integer idInt = new Integer(id);
|
||||
Integer idInt = id;
|
||||
if(mSyncedNotificationIDs.contains(idInt)) {
|
||||
showNotification(CasioConstants.CATEGORY_OTHER, null, null, null, id, true);
|
||||
mSyncedNotificationIDs.remove(idInt);
|
||||
@ -300,7 +415,7 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
int iDuration;
|
||||
|
||||
try {
|
||||
iDuration = Integer.valueOf(duration);
|
||||
iDuration = Integer.parseInt(duration);
|
||||
} catch (Exception ex) {
|
||||
LOG.warn(ex.getMessage());
|
||||
iDuration = 60;
|
||||
@ -331,7 +446,7 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
|
||||
int year = cal.get(Calendar.YEAR);
|
||||
arr[0] = CasioConstants.characteristicToByte.get("CASIO_CURRENT_TIME");
|
||||
arr[1] = (byte)((year >>> 0) & 0xff);
|
||||
arr[1] = (byte)(year & 0xff);
|
||||
arr[2] = (byte)((year >>> 8) & 0xff);
|
||||
arr[3] = (byte)(1 + cal.get(Calendar.MONTH));
|
||||
arr[4] = (byte)cal.get(Calendar.DAY_OF_MONTH);
|
||||
@ -358,7 +473,45 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
|
||||
@Override
|
||||
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
||||
int alarmOffset = 4;
|
||||
byte[] data1 = new byte[5];
|
||||
byte[] data2 = new byte[17];
|
||||
|
||||
if(!isConnected())
|
||||
return;
|
||||
|
||||
data1[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_ALM");
|
||||
data2[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_ALM2");
|
||||
|
||||
for(int i=0; i<alarms.size(); i++)
|
||||
{
|
||||
byte[] settings = new byte[4];
|
||||
Alarm alm = alarms.get(i);
|
||||
if(alm.getEnabled()) {
|
||||
settings[0] = 0x40;
|
||||
} else {
|
||||
settings[0] = 0;
|
||||
}
|
||||
if(alm.getRepetition(Alarm.ALARM_ONCE)) {
|
||||
settings[i * alarmOffset] |= 0x20;
|
||||
}
|
||||
settings[1] = 0x40;
|
||||
settings[2] = (byte)alm.getHour();
|
||||
settings[3] = (byte)alm.getMinute();
|
||||
if(i == 0) {
|
||||
System.arraycopy(settings, 0, data1, 1, settings.length);
|
||||
} else {
|
||||
System.arraycopy(settings, 0, data2, 1 + (i-1)*4, settings.length);
|
||||
}
|
||||
}
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("setAlarm");
|
||||
writeAllFeatures(builder, data1);
|
||||
writeAllFeatures(builder, data2);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error setting alarm: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -374,18 +527,33 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetCallState(CallSpec callSpec) {
|
||||
public void onSetCallState(final CallSpec callSpec) {
|
||||
switch (callSpec.command) {
|
||||
case CallSpec.CALL_INCOMING:
|
||||
final AtomicInteger c = new AtomicInteger((int) (System.currentTimeMillis()/1000));
|
||||
mLastCallId = c.incrementAndGet();
|
||||
showNotification(CasioConstants.CATEGORY_INCOMING_CALL, "Phone", callSpec.name, callSpec.number, mLastCallId, false);
|
||||
SharedPreferences sharedPreferences = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||
boolean fakeRingDuration = sharedPreferences.getBoolean(PREF_FAKE_RING_DURATION, false);
|
||||
if(fakeRingDuration && mFakeRingDurationCounter < CasioConstants.CASIO_FAKE_RING_RETRIES) {
|
||||
mFakeRingDurationCounter++;
|
||||
mFakeRingDurationHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showNotification(CasioConstants.CATEGORY_INCOMING_CALL, null, null, null, mLastCallId, true);
|
||||
onSetCallState(callSpec);
|
||||
}
|
||||
}, CasioConstants.CASIO_FAKE_RING_SLEEP_DURATION);
|
||||
} else {
|
||||
mFakeRingDurationCounter = 0;
|
||||
}
|
||||
mRingNotificationPending = true;
|
||||
break;
|
||||
case CallSpec.CALL_END:
|
||||
showNotification(CasioConstants.CATEGORY_INCOMING_CALL, null, null, null, mLastCallId, true);
|
||||
default:
|
||||
LOG.info("not sending CallSpec since only CALL_INCOMING is handled");
|
||||
break;
|
||||
if(mRingNotificationPending) {
|
||||
mFakeRingDurationHandler.removeCallbacksAndMessages(null);
|
||||
mFakeRingDurationCounter = 0;
|
||||
showNotification(CasioConstants.CATEGORY_INCOMING_CALL, null, null, null, mLastCallId, true);
|
||||
mLastCallId = new AtomicInteger((int) (System.currentTimeMillis() / 1000)).incrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,7 +608,11 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
|
||||
@Override
|
||||
public void onFetchRecordedData(int dataTypes) {
|
||||
|
||||
try {
|
||||
new FetchStepCountDataOperation(this).perform();
|
||||
} catch(IOException e) {
|
||||
GB.toast(getContext(), "Error fetching data", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -496,6 +668,7 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
@Override
|
||||
public void onSendConfiguration(String config) {
|
||||
LOG.info("onSendConfiguration" + config);
|
||||
onSharedPreferenceChanged(null, config);
|
||||
}
|
||||
|
||||
public void onGetConfigurationFinished() {
|
||||
@ -519,7 +692,16 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
|
||||
@Override
|
||||
public void onTestNewFunction() {
|
||||
|
||||
byte[] data = new byte[2];
|
||||
data[0] = (byte)0x2e;
|
||||
data[1] = (byte)0x03;
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("onTestNewFunction");
|
||||
writeAllFeaturesRequest(builder, data);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.error("Error setting alarm: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -540,27 +722,49 @@ public class CasioGBX100DeviceSupport extends AbstractBTLEDeviceSupport implemen
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (key.equals(DeviceSettingsPreferenceConst.PREF_WEARLOCATION)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_WRIST).perform();
|
||||
} else if(key.equals(PREF_USER_STEPS_GOAL)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_STEP_GOAL).perform();
|
||||
} else if(key.equals(PREF_USER_ACTIVETIME_MINUTES)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_ACTIVITY_GOAL).perform();
|
||||
} else if(key.equals(PREF_USER_DISTANCE_METERS)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_DISTANCE_GOAL).perform();
|
||||
} else if(key.equals(PREF_USER_GENDER)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_GENDER).perform();
|
||||
} else if(key.equals(PREF_USER_HEIGHT_CM)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_HEIGHT).perform();
|
||||
} else if(key.equals(PREF_USER_WEIGHT_KG)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_WEIGHT).perform();
|
||||
} else if(key.equals(PREF_USER_YEAR_OF_BIRTH)) {
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_BIRTHDAY).perform();
|
||||
} else if (key.equals(PREF_FIND_PHONE_ENABLED) ||
|
||||
key.equals(MakibesHR3Constants.PREF_FIND_PHONE_DURATION)) {
|
||||
// No action, we check the shared preferences when the device tries to ring the phone.
|
||||
} else {
|
||||
return;
|
||||
switch (key) {
|
||||
case DeviceSettingsPreferenceConst.PREF_WEARLOCATION:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_WRIST).perform();
|
||||
break;
|
||||
case PREF_USER_STEPS_GOAL:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_STEP_GOAL).perform();
|
||||
break;
|
||||
case PREF_USER_ACTIVETIME_MINUTES:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_ACTIVITY_GOAL).perform();
|
||||
break;
|
||||
case PREF_USER_DISTANCE_METERS:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_DISTANCE_GOAL).perform();
|
||||
break;
|
||||
case PREF_USER_GENDER:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_GENDER).perform();
|
||||
break;
|
||||
case PREF_USER_HEIGHT_CM:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_HEIGHT).perform();
|
||||
break;
|
||||
case PREF_USER_WEIGHT_KG:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_WEIGHT).perform();
|
||||
break;
|
||||
case PREF_USER_YEAR_OF_BIRTH:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_BIRTHDAY).perform();
|
||||
break;
|
||||
case PREF_TIMEFORMAT:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_TIMEFORMAT).perform();
|
||||
break;
|
||||
case PREF_KEY_VIBRATION:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_KEY_VIBRATION).perform();
|
||||
break;
|
||||
case PREF_AUTOLIGHT:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_AUTOLIGHT).perform();
|
||||
break;
|
||||
case PREF_OPERATING_SOUNDS:
|
||||
new SetConfigurationOperation(this, CasioConstants.ConfigurationOption.OPTION_OPERATING_SOUNDS).perform();
|
||||
break;
|
||||
case PREF_FAKE_RING_DURATION:
|
||||
case PREF_FIND_PHONE_ENABLED:
|
||||
case MakibesHR3Constants.PREF_FIND_PHONE_DURATION:
|
||||
// No action, we check the shared preferences when the device tries to ring the phone.
|
||||
break;
|
||||
default:
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.info("Error sending configuration change to watch");
|
||||
|
@ -0,0 +1,295 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations;
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.CasioGBX100DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public class FetchStepCountDataOperation extends AbstractBTLEOperation<CasioGBX100DeviceSupport> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FetchStepCountDataOperation.class);
|
||||
|
||||
private final CasioGBX100DeviceSupport support;
|
||||
|
||||
public FetchStepCountDataOperation(CasioGBX100DeviceSupport support) {
|
||||
super(support);
|
||||
this.support = support;
|
||||
}
|
||||
|
||||
private void enableRequiredNotifications(boolean enable) {
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("enableRequiredNotifications");
|
||||
builder.setGattCallback(this);
|
||||
builder.notify(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), enable);
|
||||
builder.notify(getCharacteristic(CasioConstants.CASIO_CONVOY_CHARACTERISTIC_UUID), enable);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.info("Error enabling required notifications" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void requestStepCountData() {
|
||||
byte[] command = {0x00, 0x11, 0x00, 0x00, 0x00};
|
||||
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("requestStepCountDate");
|
||||
builder.setGattCallback(this);
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.info("Error requesting step count data: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeStepCountAck() {
|
||||
byte[] command = {0x04, 0x11, 0x00, 0x00, 0x00};
|
||||
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("writeStepCountAck");
|
||||
builder.setGattCallback(this);
|
||||
builder.write(getCharacteristic(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID), command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.info("Error requesting step count data: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prePerform() throws IOException {
|
||||
super.prePerform();
|
||||
getDevice().setBusyTask("FetchStepCountDataOperation starting..."); // mark as busy quickly to avoid interruptions from the outside
|
||||
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, 0, getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPerform() throws IOException {
|
||||
enableRequiredNotifications(true);
|
||||
requestStepCountData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void operationFinished() {
|
||||
LOG.info("SetConfigurationOperation finished");
|
||||
unsetBusy();
|
||||
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), false, 100, getContext());
|
||||
|
||||
|
||||
operationStatus = OperationStatus.FINISHED;
|
||||
if (getDevice() != null) {
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("finished operation");
|
||||
builder.setGattCallback(null); // unset ourselves from being the queue's gatt callback
|
||||
builder.wait(0);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException ex) {
|
||||
LOG.info("Error resetting Gatt callback: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
||||
BluetoothGattCharacteristic characteristic) {
|
||||
UUID characteristicUUID = characteristic.getUuid();
|
||||
byte[] data = characteristic.getValue();
|
||||
|
||||
if (data.length == 0)
|
||||
return true;
|
||||
|
||||
if (characteristicUUID.equals(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID)) {
|
||||
int length = 0;
|
||||
if (data.length > 3) {
|
||||
length = (data[2] & 0xff) | ((data[3] & 0xff) << 8);
|
||||
}
|
||||
LOG.debug("Response is going to be " + length + " bytes long");
|
||||
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, 10, getContext());
|
||||
|
||||
return true;
|
||||
} else if(characteristicUUID.equals(CasioConstants.CASIO_CONVOY_CHARACTERISTIC_UUID)) {
|
||||
if(data.length < 18) {
|
||||
LOG.info("Data length too short.");
|
||||
} else {
|
||||
for(int i=0; i<data.length; i++)
|
||||
data[i] = (byte)(~data[i]);
|
||||
|
||||
int payloadLength = ((data[0] & 0xff) | ((data[1] & 0xff) << 8));
|
||||
|
||||
if(data.length == (payloadLength + 2)) {
|
||||
LOG.debug("Payload length and data length match.");
|
||||
} else {
|
||||
LOG.debug("Payload length and data length do not match: " + payloadLength + " vs. " + data.length);
|
||||
}
|
||||
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
ArrayList<CasioGBX100ActivitySample> stepCountData = new ArrayList<>();
|
||||
|
||||
int year = data[2];
|
||||
int month = data[3] - 1; // Zero-based
|
||||
int day = data[4];
|
||||
int hour = data[5];
|
||||
int minute = data[6];
|
||||
|
||||
int stepCount = ((data[7] & 0xff) | ((data[8] & 0xff) << 8) | ((data[9] & 0xff) << 16) | ((data[10] & 0xff) << 24));
|
||||
// it reports 0xfffffffe if no steps have been recorded
|
||||
if(stepCount == 0xfffffffe)
|
||||
stepCount = 0;
|
||||
|
||||
int calories = ((data[11] & 0xff) | ((data[12] & 0xff) << 8));
|
||||
if(calories == 0xfffe)
|
||||
calories = 0;
|
||||
int yearOfBirth = ((data[13] & 0xff) | ((data[14] & 0xff) << 8));
|
||||
int monthOfBirth = data[15];
|
||||
int dayOfBirth = data[16];
|
||||
LOG.debug("Current step count value: " + stepCount);
|
||||
LOG.debug("Current calories: " + calories);
|
||||
// data[17]:
|
||||
// 0x01 probably means finished.
|
||||
// 0x00 probably means more data.
|
||||
|
||||
// Set timestamps for retrieving recorded data for the current day
|
||||
|
||||
cal.set(year + 2000, month, day, hour, 30, 0);
|
||||
int ts_to = (int)(cal.getTimeInMillis() / 1000);
|
||||
cal.set(year + 2000, month, day, 0, 0, 0);
|
||||
int ts_from = (int)(cal.getTimeInMillis() / 1000);
|
||||
|
||||
CasioGBX100ActivitySample sum = support.getSumWithinRange(ts_from, ts_to);
|
||||
|
||||
int caloriesToday = sum.getCalories();
|
||||
int stepsToday = sum.getSteps();
|
||||
|
||||
// Set timestamp to currently fetched data for fetching historic data
|
||||
cal.set(year + 2000, month, day, hour, 30, 0);
|
||||
|
||||
if(data[17] == 0x00 && data.length > 18) {
|
||||
LOG.info("We got historic step count data.");
|
||||
int index = 18;
|
||||
boolean inPacket = false;
|
||||
int packetIndex = 0;
|
||||
int packetLength = 0;
|
||||
int type = 0;
|
||||
while(index < data.length) {
|
||||
if(!inPacket) {
|
||||
type = data[index];
|
||||
packetLength = ((data[index + 1] & 0xff) | ((data[index + 2] & 0xff) << 8));
|
||||
packetIndex = 0;
|
||||
inPacket = true;
|
||||
index = index + 3;
|
||||
LOG.debug("Decoding packet with type: " + type + " and length: " + packetLength);
|
||||
}
|
||||
int count = ((data[index] & 0xff) | ((data[index + 1] & 0xff) << 8));
|
||||
if(count == 0xfffe)
|
||||
count = 0;
|
||||
LOG.debug("Got count " + count);
|
||||
|
||||
index = index+2;
|
||||
if(index >= data.length) {
|
||||
LOG.debug("End of packet.");
|
||||
}
|
||||
if(type == CasioConstants.CASIO_CONVOY_DATATYPE_STEPS) {
|
||||
cal.add(Calendar.HOUR, -1);
|
||||
int ts = (int)(cal.getTimeInMillis() / 1000);
|
||||
stepCountData.add(new CasioGBX100ActivitySample());
|
||||
stepCountData.get(packetIndex/2).setSteps(count);
|
||||
stepCountData.get(packetIndex/2).setTimestamp(ts);
|
||||
if(count > 0) {
|
||||
stepCountData.get(packetIndex / 2).setRawKind(ActivityKind.TYPE_ACTIVITY);
|
||||
} else {
|
||||
stepCountData.get(packetIndex / 2).setRawKind(ActivityKind.TYPE_NOT_MEASURED);
|
||||
}
|
||||
if(ts > ts_from && ts < ts_to) {
|
||||
stepsToday += count;
|
||||
}
|
||||
} else if(type == CasioConstants.CASIO_CONVOY_DATATYPE_CALORIES) {
|
||||
if(stepCountData.get(packetIndex/2).getSteps() > 0) {
|
||||
// The last packet might contain an invalid calory count
|
||||
// of 255, but only if the steps are also invalid.
|
||||
stepCountData.get(packetIndex / 2).setCalories(count);
|
||||
int ts = stepCountData.get(packetIndex / 2).getTimestamp();
|
||||
if (ts > ts_from && ts < ts_to) {
|
||||
caloriesToday += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
packetIndex = packetIndex + 2;
|
||||
if(packetIndex >= packetLength)
|
||||
inPacket = false;
|
||||
}
|
||||
}
|
||||
|
||||
// This generates an artificial "now" timestamp for the current
|
||||
// activity based on the existing data. This timestamp will be overwritten
|
||||
// by the next fetch operation with the actual value.
|
||||
int steps = stepCount - stepsToday;
|
||||
int cals = calories - caloriesToday;
|
||||
|
||||
// For a yet unknown reason, the sum calculated by the watch is sometimes lower than
|
||||
// the sum calculated by us. I suspect it is just refreshed at a later time!?
|
||||
|
||||
if(steps > 0 && cals > 0) {
|
||||
|
||||
cal.set(year + 2000, month, day, hour, 30, 0);
|
||||
int ts = (int) (cal.getTimeInMillis() / 1000);
|
||||
|
||||
LOG.debug("Artificial timestamp: " + cals + " calories and " + steps + " steps");
|
||||
CasioGBX100ActivitySample sample = new CasioGBX100ActivitySample();
|
||||
sample.setSteps(steps);
|
||||
sample.setCalories(cals);
|
||||
sample.setTimestamp(ts);
|
||||
if (steps > 0)
|
||||
sample.setRawKind(ActivityKind.TYPE_ACTIVITY);
|
||||
else
|
||||
sample.setRawKind(ActivityKind.TYPE_NOT_MEASURED);
|
||||
stepCountData.add(0, sample);
|
||||
}
|
||||
|
||||
support.stepCountDataFetched(stepCount, calories, stepCountData);
|
||||
}
|
||||
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, 80, getContext());
|
||||
|
||||
writeStepCountAck();
|
||||
return true;
|
||||
} else {
|
||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||
|
||||
UUID characteristicUUID = characteristic.getUuid();
|
||||
byte[] data = characteristic.getValue();
|
||||
|
||||
if (data.length == 0)
|
||||
return true;
|
||||
|
||||
if (characteristicUUID.equals(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID)) {
|
||||
if(data[0] == 0x00) {
|
||||
LOG.debug("Request sent successfully");
|
||||
} else if(data[0] == 0x04) {
|
||||
LOG.debug("Read step count operation finished");
|
||||
enableRequiredNotifications(false);
|
||||
operationFinished();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.onCharacteristicWrite(gatt, characteristic, status);
|
||||
}
|
||||
}
|
@ -4,25 +4,23 @@ import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.PlainAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.CasioGBX100DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.BcdUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOLIGHT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_KEY_VIBRATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_OPERATING_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION;
|
||||
|
||||
public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100DeviceSupport> {
|
||||
@ -36,6 +34,12 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
|
||||
this.mFirstConnect = firstconnect;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prePerform() throws IOException {
|
||||
super.prePerform();
|
||||
getDevice().setBusyTask("GetConfigurationOperation starting..."); // mark as busy quickly to avoid interruptions from the outside
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPerform() throws IOException {
|
||||
byte[] command = new byte[1];
|
||||
@ -49,6 +53,7 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
|
||||
@Override
|
||||
protected void operationFinished() {
|
||||
operationStatus = OperationStatus.FINISHED;
|
||||
unsetBusy();
|
||||
if (getDevice() != null) {
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("finished operation");
|
||||
@ -62,6 +67,19 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
|
||||
support.onGetConfigurationFinished();
|
||||
}
|
||||
|
||||
private void requestBasicSettings() {
|
||||
byte[] command = new byte[1];
|
||||
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC");
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("getConfiguration");
|
||||
builder.setGattCallback(this);
|
||||
support.writeAllFeaturesRequest(builder, command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.info("Error requesting Casio configuration");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
||||
BluetoothGattCharacteristic characteristic) {
|
||||
@ -72,18 +90,18 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
|
||||
return true;
|
||||
|
||||
if (characteristicUUID.equals(CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID)) {
|
||||
if(data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_USER_PROFILE")) {
|
||||
boolean female = ((data[1] & 0x01) == 0x01) ;
|
||||
if (data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_USER_PROFILE")) {
|
||||
boolean female = ((data[1] & 0x01) == 0x01);
|
||||
boolean right = ((data[1] & 0x02) == 0x02);
|
||||
byte[] compData = new byte[data.length];
|
||||
for(int i=0; i<data.length; i++) {
|
||||
compData[i] = (byte)(~data[i]);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
compData[i] = (byte) (~data[i]);
|
||||
}
|
||||
int height = BcdUtil.fromBcd8(compData[2]) + BcdUtil.fromBcd8(compData[3]) * 100;
|
||||
int weight = BcdUtil.fromBcd8(compData[4]) + BcdUtil.fromBcd8(compData[5]) * 100;
|
||||
int year = BcdUtil.fromBcd8(compData[6]) + BcdUtil.fromBcd8(compData[7]) * 100;
|
||||
int month = BcdUtil.fromBcd8(compData[8]);
|
||||
int day = BcdUtil.fromBcd8(compData[9]) - 1;
|
||||
int day = BcdUtil.fromBcd8(compData[9]);
|
||||
|
||||
// Store only the device-specific settings on first-connect
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||
@ -92,22 +110,42 @@ public class GetConfigurationOperation extends AbstractBTLEOperation<CasioGBX100
|
||||
editor.putString(PREF_WEARLOCATION, right ? "right" : "left");
|
||||
editor.apply();
|
||||
|
||||
requestBasicSettings();
|
||||
|
||||
return true;
|
||||
} else if (data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC")) {
|
||||
boolean timeformat = ((data[1] & 0x01) == 0x01);
|
||||
boolean autolight = ((data[1] & 0x04) == 0x00);
|
||||
boolean key_vibration = (data[10] == 0x01);
|
||||
boolean operating_sounds = ((data[1] & 0x02) == 0x00);
|
||||
|
||||
// Store only the device-specific settings on first-connect
|
||||
SharedPreferences prefs = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
editor.putBoolean(PREF_AUTOLIGHT, autolight);
|
||||
editor.putBoolean(PREF_KEY_VIBRATION, key_vibration);
|
||||
editor.putBoolean(PREF_OPERATING_SOUNDS, operating_sounds);
|
||||
editor.apply();
|
||||
|
||||
|
||||
|
||||
LOG.info("GetConfigurationOperation finished");
|
||||
operationFinished();
|
||||
|
||||
// Retrieve all settings from the watch, this overwrites the profile
|
||||
// on first connect, overwrite the watch settings
|
||||
if(!mFirstConnect) {
|
||||
if (!mFirstConnect) {
|
||||
|
||||
} else {
|
||||
support.syncProfile();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
|
||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,18 +3,16 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.casio.operations;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.SharedPreferences;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.casio.CasioConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
@ -22,8 +20,12 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.casio.CasioGBX100DeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.operations.OperationStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.BcdUtil;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_AUTOLIGHT;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_KEY_VIBRATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_OPERATING_SOUNDS;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.model.ActivityUser.GENDER_MALE;
|
||||
|
||||
@ -38,6 +40,12 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prePerform() throws IOException {
|
||||
super.prePerform();
|
||||
getDevice().setBusyTask("SetConfigurationOperation starting..."); // mark as busy quickly to avoid interruptions from the outside
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPerform() throws IOException {
|
||||
byte[] command = new byte[1];
|
||||
@ -103,7 +111,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
data[6] = BcdUtil.toBcd8(year % 100);
|
||||
data[7] = BcdUtil.toBcd8((year - (year % 100)) / 100);
|
||||
data[8] = BcdUtil.toBcd8(month);
|
||||
data[9] = BcdUtil.toBcd8(day + 1);
|
||||
data[9] = BcdUtil.toBcd8(day);
|
||||
}
|
||||
|
||||
for(int i=2; i<data.length; i++) {
|
||||
@ -160,6 +168,54 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
data[10] = (byte)((time >> 8) & 0xff);
|
||||
}
|
||||
|
||||
if(Arrays.equals(oldData, data)) {
|
||||
LOG.info("No configuration update required");
|
||||
requestBasicSettings();
|
||||
} else {
|
||||
// Basic settings will be requested in Gatt callback
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("setConfiguration");
|
||||
builder.setGattCallback(this);
|
||||
support.writeAllFeatures(builder, data);
|
||||
builder.queue(getQueue());
|
||||
} catch (IOException e) {
|
||||
LOG.info("Error writing configuration to Casio watch");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if(data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC")) {
|
||||
SharedPreferences sharedPreferences = GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress());
|
||||
GBPrefs gbPrefs = new GBPrefs(new Prefs(GBApplication.getDeviceSpecificSharedPrefs(getDevice().getAddress())));
|
||||
|
||||
String timeformat = gbPrefs.getTimeFormat();
|
||||
|
||||
if(timeformat.equals(getContext().getString(R.string.p_timeformat_24h))) {
|
||||
data[1] |= 0x01;
|
||||
} else {
|
||||
data[1] &= ~0x01;
|
||||
}
|
||||
|
||||
boolean autolight = sharedPreferences.getBoolean(PREF_AUTOLIGHT, false);
|
||||
if(autolight) {
|
||||
data[1] &= ~0x04;
|
||||
} else {
|
||||
data[1] |= 0x04;
|
||||
}
|
||||
|
||||
boolean key_vibration = sharedPreferences.getBoolean(PREF_KEY_VIBRATION, true);
|
||||
if (key_vibration) {
|
||||
data[10] = 1;
|
||||
} else {
|
||||
data[10] = 0;
|
||||
}
|
||||
|
||||
boolean operating_sounds = sharedPreferences.getBoolean(PREF_OPERATING_SOUNDS, false);
|
||||
if(operating_sounds) {
|
||||
data[1] &= ~0x02;
|
||||
} else {
|
||||
data[1] |= 0x02;
|
||||
}
|
||||
|
||||
if(Arrays.equals(oldData, data)) {
|
||||
LOG.info("No configuration update required");
|
||||
operationFinished();
|
||||
@ -186,6 +242,7 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
protected void operationFinished() {
|
||||
LOG.info("SetConfigurationOperation finished");
|
||||
|
||||
unsetBusy();
|
||||
operationStatus = OperationStatus.FINISHED;
|
||||
if (getDevice() != null) {
|
||||
try {
|
||||
@ -199,6 +256,19 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
}
|
||||
}
|
||||
|
||||
private void requestBasicSettings() {
|
||||
byte[] command = new byte[1];
|
||||
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC");
|
||||
try {
|
||||
TransactionBuilder builder = performInitialized("getConfiguration");
|
||||
builder.setGattCallback(this);
|
||||
support.writeAllFeaturesRequest(builder, command);
|
||||
builder.queue(getQueue());
|
||||
} catch(IOException e) {
|
||||
LOG.info("Error requesting Casio configuration");
|
||||
}
|
||||
}
|
||||
|
||||
private void requestTargetSettings() {
|
||||
byte[] command = new byte[1];
|
||||
command[0] = CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_TARGET_VALUE");
|
||||
@ -227,6 +297,10 @@ public class SetConfigurationOperation extends AbstractBTLEOperation<CasioGBX10
|
||||
return true;
|
||||
}
|
||||
if(data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_TARGET_VALUE")) {
|
||||
requestBasicSettings();
|
||||
return true;
|
||||
}
|
||||
if(data[0] == CasioConstants.characteristicToByte.get("CASIO_SETTING_FOR_BASIC")) {
|
||||
operationFinished();
|
||||
return true;
|
||||
}
|
||||
|
@ -1098,4 +1098,9 @@
|
||||
<item quantity="many">%d hours</item>
|
||||
<item quantity="other">%d hours</item>
|
||||
</plurals>
|
||||
<string name="prefs_autolight">Automatic light</string>
|
||||
<string name="prefs_key_vibration">Key Vibration</string>
|
||||
<string name="prefs_operating_sounds">Operating Sounds</string>
|
||||
<string name="prefs_fake_ring_duration">Fake continuous ringing</string>
|
||||
<string name="prefs_autoremove_message">Automatically remove SMS notifications</string>
|
||||
</resources>
|
||||
|
8
app/src/main/res/xml/devicesettings_autolight.xml
Normal file
8
app/src/main/res/xml/devicesettings_autolight.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_wb_sunny"
|
||||
android:key="autolight"
|
||||
android:title="@string/prefs_autolight" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_block"
|
||||
android:key="autoremove_message"
|
||||
android:title="@string/prefs_autoremove_message" />
|
||||
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_rotate_left"
|
||||
android:key="fake_ring_duration"
|
||||
android:title="@string/prefs_fake_ring_duration" />
|
||||
</androidx.preference.PreferenceScreen>
|
8
app/src/main/res/xml/devicesettings_key_vibration.xml
Normal file
8
app/src/main/res/xml/devicesettings_key_vibration.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_vibration"
|
||||
android:key="key_vibration"
|
||||
android:title="@string/prefs_key_vibration" />
|
||||
</androidx.preference.PreferenceScreen>
|
8
app/src/main/res/xml/devicesettings_operating_sounds.xml
Normal file
8
app/src/main/res/xml/devicesettings_operating_sounds.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_radio"
|
||||
android:key="operating_sounds"
|
||||
android:title="@string/prefs_operating_sounds" />
|
||||
</androidx.preference.PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user