Moyoung: Address review comments and improve code style

This commit is contained in:
Arjan Schrijver
2025-06-11 23:28:04 +02:00
parent 09ac4d3884
commit 4543376bdc
38 changed files with 308 additions and 420 deletions
@@ -26,9 +26,12 @@ import androidx.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.greenrobot.dao.query.QueryBuilder;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
@@ -57,6 +60,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungBloodPressureSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungHeartRateSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSpo2SampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungStressSampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
@@ -90,19 +94,22 @@ public abstract class AbstractMoyoungDeviceCoordinator extends AbstractBLEDevice
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
Long deviceId = device.getId();
QueryBuilder<?> qb;
final Long deviceId = device.getId();
qb = session.getMoyoungActivitySampleDao().queryBuilder();
qb.where(MoyoungActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
qb = session.getMoyoungHeartRateSampleDao().queryBuilder();
qb.where(MoyoungHeartRateSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
qb = session.getMoyoungSpo2SampleDao().queryBuilder();
qb.where(MoyoungSpo2SampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
qb = session.getMoyoungBloodPressureSampleDao().queryBuilder();
qb.where(MoyoungBloodPressureSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
qb = session.getMoyoungStressSampleDao().queryBuilder();
qb.where(MoyoungStressSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
final Map<AbstractDao<?, ?>, Property> daoMap = new HashMap<>() {{
put(session.getMoyoungActivitySampleDao(), MoyoungActivitySampleDao.Properties.DeviceId);
put(session.getMoyoungHeartRateSampleDao(), MoyoungHeartRateSampleDao.Properties.DeviceId);
put(session.getMoyoungSpo2SampleDao(), MoyoungSpo2SampleDao.Properties.DeviceId);
put(session.getMoyoungBloodPressureSampleDao(), MoyoungBloodPressureSampleDao.Properties.DeviceId);
put(session.getMoyoungSleepStageSampleDao(), MoyoungSleepStageSampleDao.Properties.DeviceId);
put(session.getMoyoungStressSampleDao(), MoyoungStressSampleDao.Properties.DeviceId);
}};
for (final Map.Entry<AbstractDao<?, ?>, Property> e : daoMap.entrySet()) {
e.getKey().queryBuilder()
.where(e.getValue().eq(deviceId))
.buildDelete().executeDeleteWithoutDetachingEntities();
}
}
@Override
@@ -27,8 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class AdvanWatchSE1AICoordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AdvanWatchSE1AICoordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("^SE1$");
@@ -26,11 +26,9 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
public class C20Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(C20Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("C20");
return Pattern.compile("^C20$");
}
@Override
@@ -27,11 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(ColmiI28UltraCoordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("i28 Ultra");
return Pattern.compile("^i28 Ultra$");
}
@Override
@@ -27,8 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class ColmiV72Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(ColmiV72Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("^V72$");
@@ -27,8 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class ColmiV89Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(ColmiV89Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("V89\\.?");
@@ -27,11 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class FireBolttTalkCoordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(FireBolttTalkCoordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("FireBoltt 080");
return Pattern.compile("^FireBoltt 080$");
}
@Override
@@ -26,11 +26,9 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
public class KT80Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(KT80Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("KT80");
return Pattern.compile("^KT80$");
}
@Override
@@ -27,11 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class KsixVentureCoordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(KsixVentureCoordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("KSIX VENTURE");
return Pattern.compile("^KSIX VENTURE$");
}
@Override
@@ -26,11 +26,9 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
public class MisirunC17Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MisirunC17Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("C17");
return Pattern.compile("^C17$");
}
@Override
@@ -371,24 +371,22 @@ public class MoyoungConstants {
public static final TimeZone WATCH_INTERNAL_TIME_ZONE = TimeZone.getTimeZone("GMT+8");
public static int LocalTimeToWatchTime(Date localTime)
{
public static int LocalTimeToWatchTime(Date localTime) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
simpleDateFormat.setTimeZone(TimeZone.getDefault());
String format = simpleDateFormat.format(localTime);
simpleDateFormat.setTimeZone(WATCH_INTERNAL_TIME_ZONE);
try {
return (int)(simpleDateFormat.parse(format).getTime() / 1000);
return (int) (simpleDateFormat.parse(format).getTime() / 1000);
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
public static Date WatchTimeToLocalTime(int watchTime)
{
public static Date WatchTimeToLocalTime(int watchTime) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
simpleDateFormat.setTimeZone(WATCH_INTERNAL_TIME_ZONE);
String format = simpleDateFormat.format(new Date((long)watchTime * 1000));
String format = simpleDateFormat.format(new Date((long) watchTime * 1000));
simpleDateFormat.setTimeZone(TimeZone.getDefault());
try {
return simpleDateFormat.parse(format);
@@ -412,10 +410,8 @@ public class MoyoungConstants {
public static final byte NOTIFICATION_TYPE_MESSAGE_KAKAO = 10;
public static final byte NOTIFICATION_TYPE_MESSAGE_OTHER = 11;
public static byte notificationType(NotificationType type)
{
switch(type)
{
public static byte notificationType(NotificationType type) {
switch (type) {
case FACEBOOK:
case FACEBOOK_MESSENGER:
return NOTIFICATION_TYPE_MESSAGE_FACEBOOK;
@@ -33,16 +33,15 @@ public class MoyoungWeatherForecast {
this.maxTemp = maxTemp;
}
public MoyoungWeatherForecast(WeatherSpec.Daily forecast)
{
public MoyoungWeatherForecast(WeatherSpec.Daily forecast) {
conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(forecast.conditionCode);
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
minTemp = (byte)WeatherUtils.celsiusToFahrenheit(forecast.minTemp - 273); // Kelvin -> Fahrenheit
maxTemp = (byte)WeatherUtils.celsiusToFahrenheit(forecast.maxTemp - 273); // Kelvin -> Fahrenheit
minTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.minTemp - 273); // Kelvin -> Fahrenheit
maxTemp = (byte) WeatherUtils.celsiusToFahrenheit(forecast.maxTemp - 273); // Kelvin -> Fahrenheit
} else {
minTemp = (byte)(forecast.minTemp - 273); // Kelvin -> Celcius
maxTemp = (byte)(forecast.maxTemp - 273); // Kelvin -> Celcius
minTemp = (byte) (forecast.minTemp - 273); // Kelvin -> Celcius
maxTemp = (byte) (forecast.maxTemp - 273); // Kelvin -> Celcius
}
}
}
@@ -19,6 +19,9 @@ package nodomain.freeyourgadget.gadgetbridge.devices.moyoung;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lineageos.weather.util.WeatherUtils;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@@ -27,6 +30,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
public class MoyoungWeatherToday {
private static final Logger LOG = LoggerFactory.getLogger(MoyoungWeatherToday.class);
public final byte conditionId;
public final byte currentTemp;
public final Short pm25; // (*)
@@ -34,25 +39,30 @@ public class MoyoungWeatherToday {
public final String city; // (*)
public MoyoungWeatherToday(byte conditionId, byte currentTemp, @Nullable Short pm25, @NonNull String lunar_or_festival, @NonNull String city) {
if (lunar_or_festival.length() != 4)
throw new IllegalArgumentException("lunar_or_festival");
if (city.length() != 4)
throw new IllegalArgumentException("city");
if (lunar_or_festival.length() == 4) {
this.lunar_or_festival = lunar_or_festival;
} else {
LOG.warn("lunar_or_festival should be 4 bytes, not {}, ignoring", lunar_or_festival.length());
this.lunar_or_festival = StringUtils.pad("", 4);
}
if (city.length() == 4) {
this.city = city;
} else {
LOG.warn("city should be 4 bytes, not {}, ignoring", city.length());
this.city = StringUtils.pad("", 4);
}
this.conditionId = conditionId;
this.currentTemp = currentTemp;
this.pm25 = pm25;
this.lunar_or_festival = lunar_or_festival;
this.city = city;
}
public MoyoungWeatherToday(WeatherSpec weatherSpec)
{
public MoyoungWeatherToday(WeatherSpec weatherSpec) {
conditionId = MoyoungConstants.openWeatherConditionToMoyoungConditionId(weatherSpec.currentConditionCode);
String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric));
if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) {
currentTemp = (byte)WeatherUtils.celsiusToFahrenheit(weatherSpec.currentTemp - 273); // Kelvin -> Fahrenheit
currentTemp = (byte) WeatherUtils.celsiusToFahrenheit(weatherSpec.currentTemp - 273); // Kelvin -> Fahrenheit
} else {
currentTemp = (byte)(weatherSpec.currentTemp - 273); // Kelvin -> Celcius
currentTemp = (byte) (weatherSpec.currentTemp - 273); // Kelvin -> Celcius
}
pm25 = null;
lunar_or_festival = StringUtils.pad("", 4);
@@ -26,11 +26,9 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
public class R50ProCoordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(R50ProCoordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("R50Pro");
return Pattern.compile("^R50Pro$");
}
@Override
@@ -27,11 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class RainbuvvyT97Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(RainbuvvyT97Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("T97");
return Pattern.compile("^T97$");
}
@Override
@@ -27,11 +27,9 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class ViranC29Coordinator extends AbstractMoyoungDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(ViranC29Coordinator.class);
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("C29");
return Pattern.compile("^C29$");
}
@Override
@@ -267,19 +267,19 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
/**
* Set the activity kind from NOT_MEASURED to new_raw_activity_kind on the given range
* @param timestamp_from the start timestamp
* @param timestamp_to the end timestamp
*
* @param timestamp_from the start timestamp
* @param timestamp_to the end timestamp
* @param new_raw_activity_kind the activity kind to set
*/
public void updateActivityInRange(int timestamp_from, int timestamp_to, int new_raw_activity_kind)
{
public void updateActivityInRange(int timestamp_from, int timestamp_to, int new_raw_activity_kind) {
// greenDAO does not provide a bulk update functionality, and manual update fails because
// of no primary key
Property timestampProperty = getTimestampSampleProperty();
Device dbDevice = DBHelper.findDevice(getDevice(), getSession());
if (dbDevice == null)
throw new IllegalStateException();
throw new IllegalStateException("No device found");
Property deviceProperty = getDeviceIdentifierSampleProperty();
/*QueryBuilder<MoyoungActivitySample> qb = getSampleDao().queryBuilder();
@@ -294,7 +294,7 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
}*/
String tablename = getSampleDao().getTablename();
String baseSql = SqlUtils.createSqlUpdate(tablename, new String[] { getRawKindSampleProperty().columnName }, new String[] { });
String baseSql = SqlUtils.createSqlUpdate(tablename, new String[]{getRawKindSampleProperty().columnName}, new String[]{});
StringBuilder builder = new StringBuilder(baseSql);
List<Object> values = new ArrayList<>();
@@ -17,8 +17,8 @@
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public enum MoyoungEnumDeviceVersion implements MoyoungEnum {
CHINESE_EDITION((byte)0),
INTERNATIONAL_EDITION((byte)1);
CHINESE_EDITION((byte) 0),
INTERNATIONAL_EDITION((byte) 1);
public final byte value;
@@ -17,8 +17,8 @@
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public enum MoyoungEnumDominantHand implements MoyoungEnum {
LEFT_HAND((byte)0),
RIGHT_HAND((byte)1);
LEFT_HAND((byte) 0),
RIGHT_HAND((byte) 1);
public final byte value;
@@ -17,31 +17,31 @@
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public enum MoyoungEnumLanguage implements MoyoungEnum {
LANGUAGE_ENGLISH((byte)0),
LANGUAGE_CHINESE((byte)1),
LANGUAGE_JAPANESE((byte)2),
LANGUAGE_KOREAN((byte)3),
LANGUAGE_GERMAN((byte)4),
LANGUAGE_FRENCH((byte)5),
LANGUAGE_SPANISH((byte)6),
LANGUAGE_ARABIC((byte)7),
LANGUAGE_RUSSIAN((byte)8),
LANGUAGE_TRADITIONAL((byte)9),
LANGUAGE_UKRAINIAN((byte)10),
LANGUAGE_ITALIAN((byte)11),
LANGUAGE_PORTUGUESE((byte)12),
LANGUAGE_DUTCH((byte)13),
LANGUAGE_POLISH((byte)14),
LANGUAGE_SWEDISH((byte)15),
LANGUAGE_FINNISH((byte)16),
LANGUAGE_DANISH((byte)17),
LANGUAGE_NORWEGIAN((byte)18),
LANGUAGE_HUNGARIAN((byte)19),
LANGUAGE_CZECH((byte)20),
LANGUAGE_BULGARIAN((byte)21),
LANGUAGE_ROMANIAN((byte)22),
LANGUAGE_SLOVAK_LANGUAGE((byte)23),
LANGUAGE_LATVIAN((byte)24);
LANGUAGE_ENGLISH((byte) 0),
LANGUAGE_CHINESE((byte) 1),
LANGUAGE_JAPANESE((byte) 2),
LANGUAGE_KOREAN((byte) 3),
LANGUAGE_GERMAN((byte) 4),
LANGUAGE_FRENCH((byte) 5),
LANGUAGE_SPANISH((byte) 6),
LANGUAGE_ARABIC((byte) 7),
LANGUAGE_RUSSIAN((byte) 8),
LANGUAGE_TRADITIONAL((byte) 9),
LANGUAGE_UKRAINIAN((byte) 10),
LANGUAGE_ITALIAN((byte) 11),
LANGUAGE_PORTUGUESE((byte) 12),
LANGUAGE_DUTCH((byte) 13),
LANGUAGE_POLISH((byte) 14),
LANGUAGE_SWEDISH((byte) 15),
LANGUAGE_FINNISH((byte) 16),
LANGUAGE_DANISH((byte) 17),
LANGUAGE_NORWEGIAN((byte) 18),
LANGUAGE_HUNGARIAN((byte) 19),
LANGUAGE_CZECH((byte) 20),
LANGUAGE_BULGARIAN((byte) 21),
LANGUAGE_ROMANIAN((byte) 22),
LANGUAGE_SLOVAK_LANGUAGE((byte) 23),
LANGUAGE_LATVIAN((byte) 24);
public final byte value;
@@ -17,8 +17,8 @@
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public enum MoyoungEnumMetricSystem implements MoyoungEnum {
METRIC_SYSTEM((byte)0),
IMPERIAL_SYSTEM((byte)1);
METRIC_SYSTEM((byte) 0),
IMPERIAL_SYSTEM((byte) 1);
public final byte value;
@@ -17,8 +17,8 @@
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public enum MoyoungEnumTimeSystem implements MoyoungEnum {
TIME_SYSTEM_12((byte)0),
TIME_SYSTEM_24((byte)1);
TIME_SYSTEM_12((byte) 0),
TIME_SYSTEM_24((byte) 1);
public final byte value;
@@ -28,5 +28,6 @@ public abstract class MoyoungSetting<T> {
}
public abstract byte[] encode(T value);
public abstract T decode(byte[] data);
}
@@ -23,7 +23,7 @@ public class MoyoungSettingBool extends MoyoungSetting<Boolean> {
@Override
public byte[] encode(Boolean value) {
return new byte[] { value ? (byte)1 : (byte)0 };
return new byte[]{value ? (byte) 1 : (byte) 0};
}
@Override
@@ -23,7 +23,7 @@ public class MoyoungSettingByte extends MoyoungSetting<Byte> {
@Override
public byte[] encode(Byte value) {
return new byte[] { value };
return new byte[]{value};
}
@Override
@@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings;
public class MoyoungSettingEnum<T extends Enum <?> & MoyoungEnum> extends MoyoungSetting<T> {
public class MoyoungSettingEnum<T extends Enum<?> & MoyoungEnum> extends MoyoungSetting<T> {
protected final Class<T> clazz;
public MoyoungSettingEnum(String name, byte cmdQuery, byte cmdSet, Class<T> clazz) {
@@ -24,8 +24,7 @@ public class MoyoungSettingEnum<T extends Enum <?> & MoyoungEnum> extends Moyoun
this.clazz = clazz;
}
public T findByValue(byte value)
{
public T findByValue(byte value) {
for (T e : clazz.getEnumConstants()) {
if (e.value() == value) {
return e;
@@ -37,7 +36,7 @@ public class MoyoungSettingEnum<T extends Enum <?> & MoyoungEnum> extends Moyoun
@Override
public byte[] encode(T value) {
return new byte[] { value.value() };
return new byte[]{value.value()};
}
@Override
@@ -27,7 +27,7 @@ public class MoyoungSettingInt extends MoyoungSetting<Integer> {
@Override
public byte[] encode(Integer value) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.order(ByteOrder.BIG_ENDIAN); // <- this is what happens when somebody in China designs a communication protocol
buffer.order(ByteOrder.BIG_ENDIAN);
buffer.putInt(value);
return buffer.array();
}
@@ -37,7 +37,7 @@ public class MoyoungSettingInt extends MoyoungSetting<Integer> {
if (data.length != 4)
throw new IllegalArgumentException("Wrong data length, should be 4, was " + data.length);
ByteBuffer buffer = ByteBuffer.wrap(data);
buffer.order(ByteOrder.LITTLE_ENDIAN); // <- yes, it's different here
buffer.order(ByteOrder.LITTLE_ENDIAN); // <- yes, it's different here since that's how the protocol is designed
return buffer.getInt();
}
}
@@ -36,8 +36,8 @@ public class MoyoungSettingLanguage extends MoyoungSettingEnum<MoyoungEnumLangua
if (data.length < 5)
throw new IllegalArgumentException("Wrong data length, should be at least 5, was " + data.length);
byte[] current = new byte[] { data[0] };
byte[] supported = new byte[] { data[1], data[2], data[3], data[4] };
byte[] current = new byte[]{data[0]};
byte[] supported = new byte[]{data[1], data[2], data[3], data[4]};
ByteBuffer buffer = ByteBuffer.wrap(supported);
int supportedNum = buffer.getInt();
@@ -38,11 +38,11 @@ public class MoyoungSettingRemindersToMove extends MoyoungSetting<MoyoungSetting
@Override
public String toString() {
return "RemindersToMove{" +
"period=" + period +
", steps=" + steps +
", start_h=" + start_h +
", end_h=" + end_h +
'}';
"period=" + period +
", steps=" + steps +
", start_h=" + start_h +
", end_h=" + end_h +
'}';
}
}
@@ -39,11 +39,11 @@ public class MoyoungSettingTimeRange extends MoyoungSetting<MoyoungSettingTimeRa
@Override
public String toString() {
return "TimeRange{" +
"start_h=" + start_h +
", start_m=" + start_m +
", end_h=" + end_h +
", end_m=" + end_m +
'}';
"start_h=" + start_h +
", start_m=" + start_m +
", end_h=" + end_h +
", end_m=" + end_m +
'}';
}
}
@@ -71,6 +71,6 @@ public class MoyoungSettingTimeRange extends MoyoungSetting<MoyoungSettingTimeRa
buffer.order(ByteOrder.LITTLE_ENDIAN);
short start = buffer.getShort();
short end = buffer.getShort();
return new TimeRange((byte)(start / 60), (byte)(start % 60), (byte)(end / 60), (byte)(start % 60));
return new TimeRange((byte) (start / 60), (byte) (start % 60), (byte) (end / 60), (byte) (start % 60));
}
}
@@ -24,16 +24,16 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
public class MoyoungSettingUserInfo extends MoyoungSetting<ActivityUser> {
public MoyoungSettingUserInfo(String name, byte cmdSet) {
super(name, (byte)-1, cmdSet);
super(name, (byte) -1, cmdSet);
}
@Override
public byte[] encode(ActivityUser value) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.put((byte)value.getHeightCm());
buffer.put((byte)value.getWeightKg());
buffer.put((byte)value.getAge());
buffer.put((byte)value.getGender());
buffer.put((byte) value.getHeightCm());
buffer.put((byte) value.getWeightKg());
buffer.put((byte) value.getAge());
buffer.put((byte) value.getGender());
return buffer.array();
}
@@ -35,8 +35,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.Amazfit
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.freebuds6.HuaweiFreebuds6Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatch5.HuaweiWatch5Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.huaweiwatchfit4pro.HuaweiWatchFit4ProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.AdvanWatchSE1AICoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ColmiV72Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.oppo.OppoEncoBuds2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pixel.PixelBudsACoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.polar.PolarH10DeviceCoordinator;
@@ -47,12 +45,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.garmin.bike.GarminEdge130Plu
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.fenix.GarminFenix7XProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.garmin.watches.vivoactive.GarminVivoActiveHrCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.huami.zeppos.watches.AmazfitBip6Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ColmiV89Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.FireBolttTalkCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.R50ProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.RainbuvvyT97Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ViranC29Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.KT80Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.onemoresonoflow.OneMoreSonoFlowCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.asteroidos.AsteroidOSDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.bandwpseries.BandWPSeriesDeviceCoordinator;
@@ -270,10 +262,18 @@ import nodomain.freeyourgadget.gadgetbridge.devices.mijia_lywsd.MijiaXmwsdj04Coo
import nodomain.freeyourgadget.gadgetbridge.devices.miscale.MiCompositionScaleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miscale.MiSmartScaleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moondrop.MoondropSpaceTravelCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.AdvanWatchSE1AICoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.C20Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ColmiI28UltraCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ColmiV72Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ColmiV89Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.FireBolttTalkCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.KsixVentureCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.KT80Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.MisirunC17Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.R50ProCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.RainbuvvyT97Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.ViranC29Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.nothing.CmfBudsPro2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.nothing.Ear1Coordinator;
@@ -58,14 +58,14 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
@Override
protected void doPerform() throws IOException {
TransactionBuilder builder = performInitialized("FetchDataOperation");
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[]{MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP}));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[]{MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP}));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_SLEEP, new byte[0]));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_STEPS }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[]{MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS}));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[]{MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_STEPS}));
builder.read(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_STEPS));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1, new byte[] { 0x00 }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[]{}));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1, new byte[]{0x00}));
builder.queue(getQueue());
updateProgressAndCheckFinish();
@@ -73,12 +73,9 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
@Override
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value, int status) {
if (!isOperationRunning())
{
if (!isOperationRunning()) {
LOG.error("onCharacteristicRead but operation is not running!");
}
else
{
} else {
UUID charUuid = characteristic.getUuid();
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_STEPS) && status == BluetoothGatt.GATT_SUCCESS) {
LOG.info("TODAY STEPS data: {}", Logging.formatBytes(value));
@@ -93,15 +90,11 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
if (!isOperationRunning())
{
if (!isOperationRunning()) {
LOG.error("onCharacteristicChanged but operation is not running!");
}
else
{
} else {
UUID charUuid = characteristic.getUuid();
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN))
{
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN)) {
if (packetIn.putFragment(value)) {
Pair<Byte, byte[]> packet = MoyoungPacketIn.parsePacket(packetIn.getPacket());
packetIn = new MoyoungPacketIn();
@@ -143,20 +136,17 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
receivedSteps[2] = true;
decodeSteps(2, data);
return true;
}
else if (dataType == MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS) {
} else if (dataType == MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS) {
LOG.info("YESTERDAY STEPS data: {}", Logging.formatBytes(data));
receivedSteps[1] = true;
decodeSteps(1, data);
return true;
}
else if (dataType == MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP) {
} else if (dataType == MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP) {
LOG.info("2 DAYS AGO SLEEP data: {}", Logging.formatBytes(data));
receivedSleep[2] = true;
decodeSleep(2 - daysAgoOffset, data);
return true;
}
else if (dataType == MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP) {
} else if (dataType == MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP) {
LOG.info("YESTERDAY SLEEP data: {}", Logging.formatBytes(data));
receivedSleep[1] = true;
decodeSleep(1 - daysAgoOffset, data);
@@ -170,27 +160,23 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
return false;
}
private void decodeSteps(int daysAgo, byte[] data)
{
private void decodeSteps(int daysAgo, byte[] data) {
getSupport().handleStepsHistory(daysAgo, data, false);
updateProgressAndCheckFinish();
}
private void decodeSleep(int daysAgo, byte[] data)
{
private void decodeSleep(int daysAgo, byte[] data) {
getSupport().handleSleepHistory(daysAgo, data);
updateProgressAndCheckFinish();
}
private void decodeTrainingData(byte[] data)
{
private void decodeTrainingData(byte[] data) {
getSupport().handleTrainingData(data);
receivedTrainingData = true;
updateProgressAndCheckFinish();
}
private void updateProgressAndCheckFinish()
{
private void updateProgressAndCheckFinish() {
int count_steps = 0;
int count_sleep = 0;
int count_training = 0;
@@ -151,7 +151,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private final Set<CalendarEvent> lastSync = new HashSet<>();
public int getMtu() {
return super.getMTU()-3;
return super.getMTU() - 3;
}
public MoyoungDeviceSupport() {
@@ -188,7 +188,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
final int mtu = ((AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator()).getMtu();
builder.requestMtu(mtu+3); // Add 3 bytes for the BLE overhead
builder.requestMtu(mtu + 3); // Add 3 bytes for the BLE overhead
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
builder.notify(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN), true);
@@ -215,8 +215,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
idleUpdateHandler.removeCallbacks(updateIdleStepsRunnable);
}
private BluetoothGattCharacteristic getTargetCharacteristicForPacketType(byte packetType)
{
private BluetoothGattCharacteristic getTargetCharacteristicForPacketType(byte packetType) {
if (packetType == 1)
return getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_DATA_SPECIAL_1);
else if (packetType == 2)
@@ -225,13 +224,11 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_DATA_OUT);
}
public void sendPacket(TransactionBuilder builder, byte[] packet)
{
public void sendPacket(TransactionBuilder builder, byte[] packet) {
MoyoungPacketOut packetOut = new MoyoungPacketOut(packet);
byte[] fragment = new byte[Math.min(packet.length, getMtu())];
while(packetOut.getFragment(fragment))
{
while (packetOut.getFragment(fragment)) {
builder.write(getTargetCharacteristicForPacketType(packet[4]), fragment.clone());
}
}
@@ -239,14 +236,12 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
UUID charUuid = characteristic.getUuid();
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_STEPS))
{
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_STEPS)) {
LOG.info("Update step count: {}", Logging.formatBytes(value));
handleStepsHistory(0, value, true);
return true;
}
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN))
{
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN)) {
if (packetIn.putFragment(value)) {
Pair<Byte, byte[]> packet = MoyoungPacketIn.parsePacket(packetIn.getPacket());
packetIn = new MoyoungPacketIn();
@@ -265,8 +260,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return super.onCharacteristicChanged(gatt, characteristic, value);
}
private boolean handlePacket(byte packetType, byte[] payload)
{
private boolean handlePacket(byte packetType, byte[] payload) {
if (packetType == MoyoungConstants.CMD_RETURN_PRINCIPAL_SCREEN) { // 83
LOG.info("Return to a principal screen...");
if (takePhotoActive) {
@@ -276,8 +270,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE)
{
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE) {
int heartRate = payload[0] & 0xff;
LOG.info("Measure heart rate finished: {} BPM", heartRate);
@@ -303,8 +296,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_OXYGEN)
{
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_OXYGEN) {
int percent = payload[0] & 0xff;
LOG.info("Measure blood oxygen finished: {}%", percent);
@@ -327,8 +319,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_PRESSURE)
{
if (packetType == MoyoungConstants.CMD_TRIGGER_MEASURE_BLOOD_PRESSURE) {
int dataUnknown = payload[0] & 0xff;
int data1 = payload[1] & 0xff;
int data2 = payload[2] & 0xff;
@@ -374,8 +365,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_LAST_DYNAMIC_RATE)
{
if (packetType == MoyoungConstants.CMD_QUERY_LAST_DYNAMIC_RATE) {
// Training on the watch just finished and it wants us to fetch the details
LOG.info("Starting training fetch");
try {
@@ -386,66 +376,56 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1)
{
if (packetType == MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1) {
handleHeartRateHistory(payload);
return true;
}
if (packetType == MoyoungConstants.CMD_NOTIFY_PHONE_OPERATION)
{
if (packetType == MoyoungConstants.CMD_NOTIFY_PHONE_OPERATION) {
byte operation = payload[0];
if (operation == MoyoungConstants.ARG_OPERATION_PLAY_PAUSE)
{
if (operation == MoyoungConstants.ARG_OPERATION_PLAY_PAUSE) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.PLAYPAUSE;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_PREV_SONG)
{
if (operation == MoyoungConstants.ARG_OPERATION_PREV_SONG) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.PREVIOUS;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_NEXT_SONG)
{
if (operation == MoyoungConstants.ARG_OPERATION_NEXT_SONG) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.NEXT;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_DROP_INCOMING_CALL)
{
if (operation == MoyoungConstants.ARG_OPERATION_DROP_INCOMING_CALL) {
GBDeviceEventCallControl callCmd = new GBDeviceEventCallControl();
callCmd.event = GBDeviceEventCallControl.Event.REJECT;
evaluateGBDeviceEvent(callCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_VOLUME_UP)
{
if (operation == MoyoungConstants.ARG_OPERATION_VOLUME_UP) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.VOLUMEUP;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_VOLUME_DOWN)
{
if (operation == MoyoungConstants.ARG_OPERATION_VOLUME_DOWN) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.VOLUMEDOWN;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_PLAY)
{
if (operation == MoyoungConstants.ARG_OPERATION_PLAY) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.PLAY;
evaluateGBDeviceEvent(musicCmd);
return true;
}
if (operation == MoyoungConstants.ARG_OPERATION_PAUSE)
{
if (operation == MoyoungConstants.ARG_OPERATION_PAUSE) {
GBDeviceEventMusicControl musicCmd = new GBDeviceEventMusicControl();
musicCmd.event = GBDeviceEventMusicControl.Event.PAUSE;
evaluateGBDeviceEvent(musicCmd);
@@ -463,8 +443,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_NOTIFY_WEATHER_CHANGE)
{
if (packetType == MoyoungConstants.CMD_NOTIFY_WEATHER_CHANGE) {
LOG.info("Will transmit cached weather (if any) since the watch asks for it");
if (Weather.getInstance().getWeatherSpec() != null) {
final ArrayList<WeatherSpec> specs = new ArrayList<>(Weather.getInstance().getWeatherSpecs());
@@ -473,10 +452,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
for (MoyoungSetting setting : queriedSettings)
{
if (setting.cmdQuery == packetType)
{
for (MoyoungSetting setting : queriedSettings) {
if (setting.cmdQuery == packetType) {
Object value = setting.decode(payload);
onReadConfigurationDone(setting, value, payload);
queriedSettings.remove(setting);
@@ -484,41 +461,35 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
if (packetType == MoyoungConstants.CMD_QUERY_ALARM_CLOCK || (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_QUERY_ALARMS))
{
if (packetType == MoyoungConstants.CMD_QUERY_ALARM_CLOCK || (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_QUERY_ALARMS)) {
handleGetAlarmsResponse(payload);
return true;
}
if (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_STRESS_PACKET)
{
if (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_STRESS_PACKET) {
handleStressPacket(payload);
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_POWER_SAVING)
{
if (packetType == MoyoungConstants.CMD_QUERY_POWER_SAVING) {
LOG.info("Power saving set to: {}", payload[0] == 0x01);
onReadConfigurationDone(getSetting("POWER_SAVING"), payload[0], null);
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_DISPLAY_WATCH_FACE)
{
if (packetType == MoyoungConstants.CMD_QUERY_DISPLAY_WATCH_FACE) {
LOG.info("Watchface changed on watch to nr {}", payload[0]);
onReadConfigurationDone(getSetting("DISPLAY_WATCH_FACE"), payload[0], null);
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_QUICK_VIEW)
{
if (packetType == MoyoungConstants.CMD_QUERY_QUICK_VIEW) {
LOG.info("AOD or Lift Wrist toggle changed to: {}", payload[0] == 0x00 ? "enabled" : "disabled");
onReadConfigurationDone(getSetting("QUICK_VIEW"), payload[0], null);
return true;
}
if (packetType == MoyoungConstants.CMD_QUERY_DO_NOT_DISTURB_TIME)
{
if (packetType == MoyoungConstants.CMD_QUERY_DO_NOT_DISTURB_TIME) {
LOG.info("DND setting changed to: {}", payload[0]);
if (payload.length > 4)
onReadConfigurationDone(getSetting("DO_NOT_DISTURB_TIME"), payload, null);
@@ -527,14 +498,12 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
if (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_QUERY_STOCKS)
{
if (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_QUERY_STOCKS) {
LOG.info("Stocks queried from watch");
return true;
}
if (packetType == MoyoungConstants.CMD_FIND_MY_PHONE)
{
if (packetType == MoyoungConstants.CMD_FIND_MY_PHONE) {
LOG.info("Find my phone started on watch");
GBDeviceEventFindPhone findPhoneEvent = new GBDeviceEventFindPhone();
findPhoneEvent.event = findMyPhoneActive ? GBDeviceEventFindPhone.Event.STOP : GBDeviceEventFindPhone.Event.START;
@@ -549,8 +518,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private void broadcastSample(MoyoungActivitySample sample) {
Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample)
.putExtra(DeviceService.EXTRA_TIMESTAMP, sample.getTimestamp());
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample)
.putExtra(DeviceService.EXTRA_TIMESTAMP, sample.getTimestamp());
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
}
@@ -574,7 +543,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private void handleBatteryInfo(BatteryInfo info) {
LOG.warn("Battery info: {}", info);
batteryCmd.level = (short) info.getPercentCharged();
if (batteryCmd.state == BatteryState.UNKNOWN) batteryCmd.state = BatteryState.BATTERY_NORMAL;
if (batteryCmd.state == BatteryState.UNKNOWN)
batteryCmd.state = BatteryState.BATTERY_NORMAL;
handleGBDeviceEvent(batteryCmd);
}
@@ -593,8 +563,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return true;
}
private void sendNotification(byte type, String text)
{
private void sendNotification(byte type, String text) {
try {
TransactionBuilder builder = performInitialized("sendNotification");
byte[] str = text.getBytes();
@@ -660,7 +629,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private void setTime(TransactionBuilder builder) {
ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.putInt(MoyoungConstants.LocalTimeToWatchTime(new Date())); // The watch is hardcoded to GMT+8 internally...
buffer.put((byte)8); // I guess this means GMT+8 but changing it has no effect at all (it was hardcoded in the original app too)
buffer.put((byte) 8); // I guess this means GMT+8 but changing it has no effect at all (it was hardcoded in the original app too)
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SYNC_TIME, buffer.array()));
}
@@ -754,8 +723,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
private void handleGetAlarmsResponse(byte[] payload)
{
private void handleGetAlarmsResponse(byte[] payload) {
boolean payloadV2 = false;
if (payload.length % 8 == 3) {
payloadV2 = true;
@@ -784,14 +752,14 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
alarmsInPacket = payload.length / 8;
}
for (int i=0; i<alarmsInPacket; i++) {
for (int i = 0; i < alarmsInPacket; i++) {
byte[] alarm = new byte[8];
buffer.get(alarm);
saveAlarmFromPayload(alarm);
}
AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator();
for (int i=alarmsInPacket; i<=coordinator.getAlarmSlotCount(getDevice()); i++) {
for (int i = alarmsInPacket; i <= coordinator.getAlarmSlotCount(getDevice()); i++) {
nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm();
alarm.setUnused(true);
AlarmUtils.mergeOneshotToDeviceAlarms(getDevice(), alarm, i);
@@ -834,7 +802,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator();
try {
TransactionBuilder builder = performInitialized("onSetAlarms");
for(int i = 0; i < coordinator.getAlarmSlotCount(getDevice()); i++) {
for (int i = 0; i < coordinator.getAlarmSlotCount(getDevice()); i++) {
Alarm alarm = alarms.get(i);
if (alarm.getUnused()) {
byte[] packet = new byte[]{MoyoungConstants.ARG_ADVANCED_SET_ALARM, MoyoungConstants.ARG_ALARM_DELETE, (byte) i};
@@ -844,8 +812,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte)i);
buffer.put(alarm.getEnabled() ? (byte)1 : (byte)0);
buffer.put((byte) i);
buffer.put(alarm.getEnabled() ? (byte) 1 : (byte) 0);
byte repetition = 0;
if (alarm.getRepetition(Alarm.ALARM_SUN))
repetition |= 1;
@@ -869,19 +837,16 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
else
repeat = 2;
buffer.put(repeat);
buffer.put((byte)alarm.getHour());
buffer.put((byte)alarm.getMinute());
if (repetition == 0)
{
buffer.put((byte) alarm.getHour());
buffer.put((byte) alarm.getMinute());
if (repetition == 0) {
// TODO: it would be possible to set an "once" alarm on a set day, but Gadgetbridge does not seem to support that
Calendar calendar = AlarmUtils.toCalendar(alarm);
buffer.put((byte)(((calendar.get(Calendar.YEAR) - 2015) << 4) + calendar.get(Calendar.MONTH) + 1));
buffer.put((byte)calendar.get(Calendar.DAY_OF_MONTH));
}
else
{
buffer.put((byte)0);
buffer.put((byte)0);
buffer.put((byte) (((calendar.get(Calendar.YEAR) - 2015) << 4) + calendar.get(Calendar.MONTH) + 1));
buffer.put((byte) calendar.get(Calendar.DAY_OF_MONTH));
} else {
buffer.put((byte) 0);
buffer.put((byte) 0);
}
buffer.put(repetition);
// Older packet type
@@ -968,7 +933,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
final TimeZone localTZ = Calendar.getInstance().getTimeZone();
try {
TransactionBuilder builder = performInitialized("sendWorldClocks");
for (byte i=1; i<getDevice().getDeviceCoordinator().getWorldClocksSlotCount(); i++) {
for (byte i = 1; i <= getDevice().getDeviceCoordinator().getWorldClocksSlotCount(); i++) {
LOG.info("Deleting world clock {}", i);
ByteBuffer payload = ByteBuffer.allocate(3);
payload.put((byte) 0x00);
@@ -1043,12 +1008,12 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
try {
TransactionBuilder builder = performInitialized("sendCalendar");
byte[] payload = new byte[]{
MoyoungConstants.ARG_ADVANCED_SET_CALENDAR,
MoyoungConstants.ARG_CALENDAR_CLEAR
MoyoungConstants.ARG_ADVANCED_SET_CALENDAR,
MoyoungConstants.ARG_CALENDAR_CLEAR
};
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_ADVANCED_QUERY, payload));
int itemNr = 0;
for(CalendarEvent event : sortedEventList) {
for (CalendarEvent event : sortedEventList) {
byte[] title = event.getTitle().getBytes();
Calendar start = Calendar.getInstance();
start.setTimeInMillis(event.getBegin());
@@ -1101,16 +1066,14 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public void onFetchRecordedData(int dataTypes) {
if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0)
{
if ((dataTypes & RecordedDataTypes.TYPE_ACTIVITY) != 0) {
try {
new FetchDataOperation(this).perform();
} catch (IOException e) {
LOG.error("Error fetching data: ", e);
}
}
if ((dataTypes & RecordedDataTypes.TYPE_GPS_TRACKS) != 0)
{
if ((dataTypes & RecordedDataTypes.TYPE_GPS_TRACKS) != 0) {
LOG.info("Fetching workouts from watch");
try {
new FetchWorkoutsV2Operation(this).perform();
@@ -1120,8 +1083,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
try {
TransactionBuilder builder = performInitialized("fetchStress");
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_ADVANCED_QUERY, new byte[] { MoyoungConstants.ARG_ADVANCED_STRESS_PACKET, 0x03, 0x00 }));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_ADVANCED_QUERY, new byte[] { MoyoungConstants.ARG_ADVANCED_STRESS_PACKET, 0x03, 0x01 }));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_ADVANCED_QUERY, new byte[]{MoyoungConstants.ARG_ADVANCED_STRESS_PACKET, 0x03, 0x00}));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_ADVANCED_QUERY, new byte[]{MoyoungConstants.ARG_ADVANCED_STRESS_PACKET, 0x03, 0x01}));
builder.queue(getQueue());
} catch (IOException e) {
LOG.error("Error while sending stress sync request: ", e);
@@ -1139,13 +1102,11 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
};
private void updateIdleSteps()
{
private void updateIdleSteps() {
// The steps value hasn't changed for a while, so the user is not moving
// Store this information in the database to improve the averaging over long periods of time
if (!getDevice().isConnected())
{
if (!getDevice().isConnected()) {
LOG.warn("updateIdleSteps but device not connected?!");
return;
}
@@ -1156,7 +1117,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
MoyoungActivitySampleProvider provider = new MoyoungActivitySampleProvider(getDevice(), dbHandler.getDaoSession());
int currentSampleTimestamp = (int)(Calendar.getInstance().getTimeInMillis() / 1000);
int currentSampleTimestamp = (int) (Calendar.getInstance().getTimeInMillis() / 1000);
MoyoungActivitySample sample = new MoyoungActivitySample();
sample.setDevice(device);
@@ -1194,9 +1155,9 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
cal.set(Calendar.SECOND, 0);
LOG.info("Received HR history packet: index={}, daysAgo={}, startHour={}", packetIndex, daysAgo, startHour);
int index = 1;
for (int hour=startHour; hour<startHour+6; hour++) {
for (int hour = startHour; hour < startHour + 6; hour++) {
cal.set(Calendar.HOUR_OF_DAY, hour);
for (int minute=0; minute<60; minute+=5) {
for (int minute = 0; minute < 60; minute += 5) {
cal.set(Calendar.MINUTE, minute);
int hr = data[index] & 0xff;
if (HeartRateUtils.getInstance().isValidHeartRateValue(hr) && cal.getTimeInMillis() < System.currentTimeMillis()) {
@@ -1233,7 +1194,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
try {
TransactionBuilder builder = performInitialized("FetchHROperation");
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1, new byte[]{(byte) (packetIndex+1)}));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_QUERY_PAST_HEART_RATE_1, new byte[]{(byte) (packetIndex + 1)}));
builder.queue(getQueue());
} catch (IOException e) {
LOG.error("Failed sending HR history request packet: ", e);
@@ -1241,8 +1202,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
public void handleStepsHistory(int daysAgo, byte[] data, boolean isRealtime) {
if (data.length != 9)
throw new IllegalArgumentException();
if (data.length != 9) {
LOG.error("steps payload should have 9 bytes, not {}", data.length);
return;
}
byte[] bArr2 = new byte[3];
System.arraycopy(data, 0, bArr2, 0, 3);
@@ -1261,8 +1224,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
MoyoungActivitySampleProvider provider = new MoyoungActivitySampleProvider(getDevice(), dbHandler.getDaoSession());
Calendar thisSample = Calendar.getInstance();
if (daysAgo != 0)
{
if (daysAgo != 0) {
thisSample.add(Calendar.DATE, -daysAgo);
thisSample.set(Calendar.HOUR_OF_DAY, 23);
thisSample.set(Calendar.MINUTE, 59);
@@ -1282,8 +1244,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
int previousSteps = 0;
int previousDistance = 0;
int previousCalories = 0;
for (MoyoungActivitySample sample : provider.getAllActivitySamples(startOfDayTimestamp, thisSampleTimestamp))
{
for (MoyoungActivitySample sample : provider.getAllActivitySamples(startOfDayTimestamp, thisSampleTimestamp)) {
if (sample.getSteps() != ActivitySample.NOT_MEASURED)
previousSteps += sample.getSteps();
if (sample.getDistanceMeters() != ActivitySample.NOT_MEASURED)
@@ -1296,12 +1257,9 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
int newDistance = distance - previousDistance;
int newCalories = calories - previousCalories;
if (newSteps < 0 || newDistance < 0 || newCalories < 0)
{
if (newSteps < 0 || newDistance < 0 || newCalories < 0) {
LOG.warn("Ignoring a sample that would generate negative values: steps += {}, distance +={}, calories += {}", newSteps, newDistance, newCalories);
}
else if (newSteps != 0 || newDistance != 0 || newCalories != 0 || daysAgo == 0)
{
} else if (newSteps != 0 || newDistance != 0 || newCalories != 0 || daysAgo == 0) {
MoyoungActivitySample sample = new MoyoungActivitySample();
sample.setDevice(device);
sample.setUser(user);
@@ -1315,8 +1273,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
sample.setCaloriesBurnt(newCalories);
provider.addGBActivitySample(sample);
if (isRealtime)
{
if (isRealtime) {
idleUpdateHandler.removeCallbacks(updateIdleStepsRunnable);
idleUpdateHandler.postDelayed(updateIdleStepsRunnable, IDLE_STEPS_INTERVAL);
broadcastSample(sample);
@@ -1331,11 +1288,11 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
public void handleSleepHistory(int daysAgo, byte[] data)
{
if (data.length % 3 != 0)
throw new IllegalArgumentException();
public void handleSleepHistory(int daysAgo, byte[] data) {
if (data.length % 3 != 0) {
LOG.error("sleep payload should be dividable by 3, but received {} bytes", data.length);
return;
}
try (DBHandler dbHandler = GBApplication.acquireDB()) {
MoyoungSleepStageSampleProvider provider = new MoyoungSleepStageSampleProvider(getDevice(), dbHandler.getDaoSession());
@@ -1344,11 +1301,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
List<MoyoungSleepStageSample> samples = new ArrayList<>();
for(int i = 0; i < data.length / 3; i++)
{
int type = data[3*i];
int start_h = data[3*i + 1];
int start_m = data[3*i + 2];
for (int i = 0; i < data.length / 3; i++) {
int type = data[3 * i];
int start_h = data[3 * i + 1];
int start_m = data[3 * i + 2];
LOG.info("sleep[daysago={}][i={}] type={}, start_h={}, start_m={}", daysAgo, i, type, start_h, start_m);
@@ -1382,8 +1338,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
}
}
public void handleTrainingData(byte[] data)
{
public void handleTrainingData(byte[] data) {
int protocolVersion = 0;
int trainingBytesLength = 24;
if (data.length % 24 == 0) {
@@ -1397,7 +1352,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return;
}
for(int i = 0; i < data.length / trainingBytesLength; i++) {
for (int i = 0; i < data.length / trainingBytesLength; i++) {
if (protocolVersion == 1 && ArrayUtils.isAllZeros(data, trainingBytesLength * i, trainingBytesLength)) {
LOG.info("Skipping empty workout details packet");
continue;
@@ -1448,16 +1403,13 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
QueryBuilder<BaseActivitySummary> qb = summaryDao.queryBuilder();
qb.where(BaseActivitySummaryDao.Properties.DeviceId.eq(device.getId()))
.where(BaseActivitySummaryDao.Properties.StartTime.eq(startTime))
.where(BaseActivitySummaryDao.Properties.EndTime.eq(endTime));
.where(BaseActivitySummaryDao.Properties.StartTime.eq(startTime))
.where(BaseActivitySummaryDao.Properties.EndTime.eq(endTime));
boolean alreadyHaveThisSample = qb.count() > 0;
if (alreadyHaveThisSample)
{
if (alreadyHaveThisSample) {
LOG.info("Already had this training sample, ignoring");
}
else
{
} else {
BaseActivitySummary summary = new BaseActivitySummary();
summary.setDevice(device);
@@ -1475,7 +1427,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
summaryDao.insert(summary);
// NOTE: The type format from device maps directly to the database format
provider.updateActivityInRange((int)(startTime.getTime() / 1000), (int)(endTime.getTime() / 1000), type);
provider.updateActivityInRange((int) (startTime.getTime() / 1000), (int) (endTime.getTime() / 1000), type);
}
} catch (Exception ex) {
LOG.error("Error saving samples: ", ex);
@@ -1487,23 +1439,22 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public void onReset(int flags) {
// TODO: this shuts down the watch, rather than rebooting it - perhaps add a new operation type?
// TODO: this shuts down the watch, rather than rebooting it
// (reboot is not supported, btw)
try {
TransactionBuilder builder = performInitialized("shutdown");
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SHUTDOWN, new byte[] { -1 }));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_SHUTDOWN, new byte[]{-1}));
builder.queue(getQueue());
} catch (IOException e) {
LOG.error("Error sending reset command: ", e);
}
}
private void triggerHeartRateTest(boolean start)
{
private void triggerHeartRateTest(boolean start) {
try {
TransactionBuilder builder = performInitialized("onHeartRateTest");
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE, new byte[] { start ? (byte)0 : (byte)-1 }));
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE, new byte[]{start ? (byte) 0 : (byte) -1}));
builder.queue(getQueue());
} catch (IOException e) {
LOG.error("Error sending heart rate test command: ", e);
@@ -1557,8 +1508,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override
public void onFindDevice(boolean start) {
if (start)
{
if (start) {
try {
TransactionBuilder builder = performInitialized("onFindDevice");
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), MoyoungConstants.CMD_FIND_MY_WATCH, new byte[0]));
@@ -1573,8 +1523,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@SuppressWarnings("unchecked")
private <T extends MoyoungSetting> T getSetting(String id) {
AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator();
for(MoyoungSetting setting : coordinator.getSupportedSettings())
{
for (MoyoungSetting setting : coordinator.getSupportedSettings()) {
if (setting.name.equals(id))
return (T) setting;
}
@@ -1594,13 +1543,11 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
return cal;
}
private <T> void sendSetting(TransactionBuilder builder, MoyoungSetting<T> setting, T newValue)
{
private <T> void sendSetting(TransactionBuilder builder, MoyoungSetting<T> setting, T newValue) {
sendPacket(builder, MoyoungPacketOut.buildPacket(getMtu(), setting.cmdSet, setting.encode(newValue)));
}
private <T> void sendSetting(MoyoungSetting<T> setting, T newValue)
{
private <T> void sendSetting(MoyoungSetting<T> setting, T newValue) {
try {
TransactionBuilder builder = performInitialized("sendSetting");
sendSetting(builder, setting, newValue);
@@ -1612,8 +1559,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private final Set<MoyoungSetting> queriedSettings = new HashSet<>();
private void querySetting(MoyoungSetting setting)
{
private void querySetting(MoyoungSetting setting) {
if (queriedSettings.contains(setting))
return;
@@ -1652,11 +1598,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_24;
else if (timeSystemPref.equals(getContext().getString(R.string.p_timeformat_am_pm)))
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_12;
else if (DateFormat.is24HourFormat(GBApplication.getContext()))
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_24;
else
if (DateFormat.is24HourFormat(GBApplication.getContext()))
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_24;
else
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_12;
timeSystem = MoyoungEnumTimeSystem.TIME_SYSTEM_12;
sendSetting(getSetting("TIME_SYSTEM"), timeSystem);
break;
@@ -1732,7 +1677,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
case MoyoungConstants.PREF_MOYOUNG_DEVICE_VERSION:
String versionPref = prefs.getString(MoyoungConstants.PREF_MOYOUNG_DEVICE_VERSION,
String.valueOf(MoyoungEnumDeviceVersion.INTERNATIONAL_EDITION.value()));
String.valueOf(MoyoungEnumDeviceVersion.INTERNATIONAL_EDITION.value()));
byte versionNum = Byte.parseByte(versionPref);
MoyoungSettingEnum<MoyoungEnumDeviceVersion> versionSetting = getSetting("DEVICE_VERSION");
sendSetting(versionSetting, versionSetting.findByValue(versionNum));
@@ -1755,10 +1700,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
MoyoungSettingTimeRange.TimeRange doNotDisturb;
if (doNotDisturbEnabled)
doNotDisturb = new MoyoungSettingTimeRange.TimeRange(
(byte) doNotDisturbStart.get(Calendar.HOUR_OF_DAY), (byte) doNotDisturbStart.get(Calendar.MINUTE),
(byte) doNotDisturbEnd.get(Calendar.HOUR_OF_DAY), (byte) doNotDisturbEnd.get(Calendar.MINUTE));
(byte) doNotDisturbStart.get(Calendar.HOUR_OF_DAY), (byte) doNotDisturbStart.get(Calendar.MINUTE),
(byte) doNotDisturbEnd.get(Calendar.HOUR_OF_DAY), (byte) doNotDisturbEnd.get(Calendar.MINUTE));
else
doNotDisturb = new MoyoungSettingTimeRange.TimeRange((byte)0, (byte)0, (byte)0, (byte)0);
doNotDisturb = new MoyoungSettingTimeRange.TimeRange((byte) 0, (byte) 0, (byte) 0, (byte) 0);
sendSetting(getSetting("DO_NOT_DISTURB_TIME"), doNotDisturb);
break;
@@ -1776,10 +1721,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
MoyoungSettingTimeRange.TimeRange quickViewTime;
if (quickViewEnabled && quickViewScheduled)
quickViewTime = new MoyoungSettingTimeRange.TimeRange(
(byte) quickViewStart.get(Calendar.HOUR_OF_DAY), (byte) quickViewStart.get(Calendar.MINUTE),
(byte) quickViewEnd.get(Calendar.HOUR_OF_DAY), (byte) quickViewEnd.get(Calendar.MINUTE));
(byte) quickViewStart.get(Calendar.HOUR_OF_DAY), (byte) quickViewStart.get(Calendar.MINUTE),
(byte) quickViewEnd.get(Calendar.HOUR_OF_DAY), (byte) quickViewEnd.get(Calendar.MINUTE));
else
quickViewTime = new MoyoungSettingTimeRange.TimeRange((byte)0, (byte)0, (byte)0, (byte)0);
quickViewTime = new MoyoungSettingTimeRange.TimeRange((byte) 0, (byte) 0, (byte) 0, (byte) 0);
sendSetting(getSetting("QUICK_VIEW"), quickViewEnabled);
sendSetting(getSetting("QUICK_VIEW_TIME"), quickViewTime);
@@ -1804,7 +1749,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
byte sedentaryStart = (byte) prefs.getInt(DeviceSettingsPreferenceConst.PREF_INACTIVITY_START, 10);
byte sedentaryEnd = (byte) prefs.getInt(DeviceSettingsPreferenceConst.PREF_INACTIVITY_END, 22);
sendSetting(getSetting("REMINDERS_TO_MOVE_PERIOD"),
new MoyoungSettingRemindersToMove.RemindersToMove(sedentaryPeriod, sedentarySteps, sedentaryStart, sedentaryEnd));
new MoyoungSettingRemindersToMove.RemindersToMove(sedentaryPeriod, sedentarySteps, sedentaryStart, sedentaryEnd));
break;
case "sync_calendar":
@@ -1891,8 +1836,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
// evaluateGBDeviceEvent(configReadEvent);
}
public void onReadConfigurationDone(MoyoungSetting setting, Object value, byte[] data)
{
public void onReadConfigurationDone(MoyoungSetting setting, Object value, byte[] data) {
LOG.info("CONFIG {} = {}", setting.name, value);
Prefs prefs = getDevicePrefs();
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences();
@@ -1956,7 +1900,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
case "DO_NOT_DISTURB_TIME":
MoyoungSettingTimeRange.TimeRange doNotDisturb = (MoyoungSettingTimeRange.TimeRange) value;
if (doNotDisturb.start_h == 0 && doNotDisturb.start_m == 0 &&
doNotDisturb.end_h == 0 && doNotDisturb.end_m == 0)
doNotDisturb.end_h == 0 && doNotDisturb.end_m == 0)
eventUpdatePreferences.withPreference(
DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB,
DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_OFF
@@ -1988,10 +1932,9 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
case "QUICK_VIEW_TIME":
boolean quickViewEnabled2 = !prefs.getString(DeviceSettingsPreferenceConst.PREF_ACTIVATE_DISPLAY_ON_LIFT, getContext().getString(R.string.p_off)).equals(getContext().getString(R.string.p_off));
MoyoungSettingTimeRange.TimeRange quickViewTime = (MoyoungSettingTimeRange.TimeRange) value;
if (quickViewEnabled2)
{
if (quickViewEnabled2) {
if (quickViewTime.start_h == 0 && quickViewTime.start_m == 0 &&
quickViewTime.end_h == 0 && quickViewTime.end_m == 0)
quickViewTime.end_h == 0 && quickViewTime.end_m == 0)
eventUpdatePreferences.withPreference(
DeviceSettingsPreferenceConst.PREF_ACTIVATE_DISPLAY_ON_LIFT,
getContext().getString(R.string.p_on)
@@ -2046,7 +1989,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
// Weather today packet
MoyoungWeatherToday weatherToday = new MoyoungWeatherToday(weatherSpec);
ByteBuffer packetWeatherToday = ByteBuffer.allocate(weatherToday.pm25 != null ? 21 : 19);
packetWeatherToday.put(weatherToday.pm25 != null ? (byte)1 : (byte)0);
packetWeatherToday.put(weatherToday.pm25 != null ? (byte) 1 : (byte) 0);
packetWeatherToday.put(weatherToday.conditionId);
packetWeatherToday.put(weatherToday.currentTemp);
if (weatherToday.pm25 != null)
@@ -2083,13 +2026,12 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
packetWeatherForecast.put(weatherToday.conditionId);
packetWeatherForecast.put(weatherToday.currentTemp);
packetWeatherForecast.put(weatherToday.currentTemp);
for(int i = 0; i < 7; i++)
{
for (int i = 0; i < 7; i++) {
MoyoungWeatherForecast forecast;
if (weatherSpec.forecasts.size() > i)
forecast = new MoyoungWeatherForecast(weatherSpec.forecasts.get(i));
else
forecast = new MoyoungWeatherForecast(MoyoungConstants.WEATHER_HAZE, (byte)-100, (byte)-100); // I don't think there is a way to send less (my watch shows only tomorrow anyway...)
forecast = new MoyoungWeatherForecast(MoyoungConstants.WEATHER_HAZE, (byte) -100, (byte) -100); // I don't think there is a way to send less (my watch shows only tomorrow anyway...)
packetWeatherForecast.put(forecast.conditionId);
packetWeatherForecast.put(forecast.maxTemp);
packetWeatherForecast.put(forecast.minTemp);
@@ -45,8 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.Logging;
public class MoyoungPacketIn extends MoyoungPacket {
private static final Logger LOG = LoggerFactory.getLogger(MoyoungPacketIn.class);
public MoyoungPacketIn()
{
public MoyoungPacketIn() {
}
@@ -56,10 +55,8 @@ public class MoyoungPacketIn extends MoyoungPacket {
* @param fragment The incoming fragment
* @return true if the packet is complete
*/
public boolean putFragment(byte[] fragment)
{
if (packet == null)
{
public boolean putFragment(byte[] fragment) {
if (packet == null) {
int len = parsePacketLength(fragment);
if (len < 0)
return false; // corrupted packet
@@ -67,8 +64,7 @@ public class MoyoungPacketIn extends MoyoungPacket {
}
int toCopy = Math.min(fragment.length, packet.length - position);
if (fragment.length > toCopy)
{
if (fragment.length > toCopy) {
LOG.warn("Got fragment with more data than expected!");
}
@@ -77,8 +73,7 @@ public class MoyoungPacketIn extends MoyoungPacket {
return position >= packet.length;
}
public byte[] getPacket()
{
public byte[] getPacket() {
if (packet == null || position < packet.length)
throw new IllegalStateException("Packet is not complete yet");
return packet;
@@ -86,22 +81,19 @@ public class MoyoungPacketIn extends MoyoungPacket {
/**
* Parse the packet header and return the length
*
* @param packetOrFragment The entire packet or it's first fragment
* @return The packet length, or -1 if packet is corrupted
*/
private static int parsePacketLength(@NonNull byte[] packetOrFragment)
{
if (packetOrFragment[0] != (byte)0xFE || packetOrFragment[1] != (byte)0xEA)
{
private static int parsePacketLength(@NonNull byte[] packetOrFragment) {
if (packetOrFragment[0] != (byte) 0xFE || packetOrFragment[1] != (byte) 0xEA) {
LOG.warn("Invalid packet header, ignoring! Fragment: {}", Logging.formatBytes(packetOrFragment));
return -1;
}
int len_h = 0;
if (packetOrFragment[2] != 16)
{
if ((packetOrFragment[2] & 0xFF) < 32)
{
if (packetOrFragment[2] != 16) {
if ((packetOrFragment[2] & 0xFF) < 32) {
LOG.warn("Corrupted packet, unable to parse length");
return -1;
}
@@ -114,16 +106,15 @@ public class MoyoungPacketIn extends MoyoungPacket {
/**
* Parse the packet
*
* @param packet The complete packet
* @return A pair containing the packet type and payload
*/
public static Pair<Byte, byte[]> parsePacket(@NonNull byte[] packet)
{
public static Pair<Byte, byte[]> parsePacket(@NonNull byte[] packet) {
int len = parsePacketLength(packet);
if (len < 0)
return null;
if (len != packet.length)
{
if (len != packet.length) {
LOG.warn("Invalid packet length!");
return null;
}
@@ -32,8 +32,7 @@ import androidx.annotation.NonNull;
* </pre>
*/
public class MoyoungPacketOut extends MoyoungPacket {
public MoyoungPacketOut(byte[] packet)
{
public MoyoungPacketOut(byte[] packet) {
this.packet = packet;
}
@@ -43,8 +42,7 @@ public class MoyoungPacketOut extends MoyoungPacket {
* @param fragmentBuffer The buffer to store the output in, of desired size (i.e. == MTU)
* @return true if there is more data to be sent, false otherwise
*/
public boolean getFragment(byte[] fragmentBuffer)
{
public boolean getFragment(byte[] fragmentBuffer) {
if (position >= packet.length)
return false;
int remainingToTransfer = Math.min(fragmentBuffer.length, packet.length - position);
@@ -55,24 +53,21 @@ public class MoyoungPacketOut extends MoyoungPacket {
/**
* Encode the packet
*
* @param packetType The packet type
* @param payload The packet payload
* @param payload The packet payload
* @return The encoded packet
*/
public static byte[] buildPacket(int mtu, byte packetType, @NonNull byte[] payload)
{
public static byte[] buildPacket(int mtu, byte packetType, @NonNull byte[] payload) {
byte[] packet = new byte[payload.length + 5];
packet[0] = (byte)0xFE;
packet[1] = (byte)0xEA;
if (mtu == 20)
{
packet[0] = (byte) 0xFE;
packet[1] = (byte) 0xEA;
if (mtu == 20) {
packet[2] = 16;
} else {
packet[2] = (byte) (32 + (packet.length >> 8) & 0xFF);
}
else
{
packet[2] = (byte)(32 + (packet.length >> 8) & 0xFF);
}
packet[3] = (byte)(packet.length & 0xFF);
packet[3] = (byte) (packet.length & 0xFF);
packet[4] = packetType;
System.arraycopy(payload, 0, packet, 5, payload.length);
return packet;
@@ -63,8 +63,7 @@ public class QuerySettingsOperation extends AbstractBTLEOperation<MoyoungDeviceS
protected void doPerform() throws IOException {
received = new boolean[settingsToQuery.length];
TransactionBuilder builder = performInitialized("QuerySettingsOperation");
for (MoyoungSetting setting : settingsToQuery)
{
for (MoyoungSetting setting : settingsToQuery) {
if (setting.cmdQuery == -1)
continue;
@@ -75,15 +74,11 @@ public class QuerySettingsOperation extends AbstractBTLEOperation<MoyoungDeviceS
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
if (!isOperationRunning())
{
if (!isOperationRunning()) {
LOG.error("onCharacteristicChanged but operation is not running!");
}
else
{
} else {
UUID charUuid = characteristic.getUuid();
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN))
{
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN)) {
if (packetIn.putFragment(value)) {
Pair<Byte, byte[]> packet = MoyoungPacketIn.parsePacket(packetIn.getPacket());
packetIn = new MoyoungPacketIn();
@@ -104,13 +99,11 @@ public class QuerySettingsOperation extends AbstractBTLEOperation<MoyoungDeviceS
private boolean handlePacket(byte packetType, byte[] payload) {
boolean handled = false;
boolean receivedEverything = true;
for(int i = 0; i < settingsToQuery.length; i++)
{
for (int i = 0; i < settingsToQuery.length; i++) {
MoyoungSetting setting = settingsToQuery[i];
if (setting.cmdQuery == -1)
continue;
if (setting.cmdQuery == packetType)
{
if (setting.cmdQuery == packetType) {
try {
Object value = setting.decode(payload);
LOG.info("SETTING QUERY {} = {}", setting.name, value.toString());
@@ -119,8 +112,7 @@ public class QuerySettingsOperation extends AbstractBTLEOperation<MoyoungDeviceS
}
received[i] = true;
handled = true;
}
else if (!received[i])
} else if (!received[i])
receivedEverything = false;
}
if (receivedEverything)
@@ -77,15 +77,11 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) {
if (!isOperationRunning())
{
if (!isOperationRunning()) {
LOG.error("onCharacteristicChanged but operation is not running!");
}
else
{
} else {
UUID charUuid = characteristic.getUuid();
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN))
{
if (charUuid.equals(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN)) {
if (packetIn.putFragment(value)) {
Pair<Byte, byte[]> packet = MoyoungPacketIn.parsePacket(packetIn.getPacket());
packetIn = new MoyoungPacketIn();
@@ -165,8 +161,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
MoyoungHeartRateSampleProvider provider = new MoyoungHeartRateSampleProvider(getDevice(), dbHandler.getDaoSession());
LOG.info("START DATE: {}", dateRecorded.getTime());
while (dataBuffer.hasRemaining())
{
while (dataBuffer.hasRemaining()) {
int measurement = dataBuffer.get() & 0xFF;
if (!dataBuffer.hasRemaining())
dateRecorded.setTimeInMillis(firstPacketTimeInMillis); // the last sample is captured exactly at the end of measurement
@@ -176,7 +171,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
MoyoungHeartRateSample sample = new MoyoungHeartRateSample();
sample.setDevice(device);
sample.setUser(user);
sample.setTimestamp((int)(dateRecorded.getTimeInMillis() / 1000));
sample.setTimestamp((int) (dateRecorded.getTimeInMillis() / 1000));
sample.setHeartRate(measurement != 0 ? measurement : ActivitySample.NOT_MEASURED);
provider.addSample(sample);
@@ -192,7 +187,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
try {
TransactionBuilder builder = performInitialized("TrainingFinishedDataOperation fetch training type");
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[]{}));
builder.queue(getQueue());
} catch (IOException e) {
LOG.error("Error fetching training data: ", e);
@@ -202,8 +197,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
}
}
private void handleTrainingSummaryDataPacket(byte[] payload)
{
private void handleTrainingSummaryDataPacket(byte[] payload) {
getSupport().handleTrainingData(payload);
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_training_data_finished), false, 0, getContext());