diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index f9a0a697e..3f07e9250 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -70,7 +70,7 @@ public class GBDaoGenerator { addXWatchActivitySample(schema, user, device); addZeTimeActivitySample(schema, user, device); addID115ActivitySample(schema, user, device); - + addJYouActivitySample(schema, user, device); addCalendarSyncState(schema, device); addAlarms(schema, user, device); @@ -328,6 +328,19 @@ public class GBDaoGenerator { return activitySample; } + private static Entity addJYouActivitySample(Schema schema, Entity user, Entity device) { + Entity activitySample = addEntity(schema, "JYouActivitySample"); + activitySample.implementsSerializable(); + addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device); + activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE); + activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE); + activitySample.addIntProperty("caloriesBurnt"); + activitySample.addIntProperty("distanceMeters"); + activitySample.addIntProperty("activeTimeMinutes"); + addHeartRateProperties(activitySample); + return activitySample; + } + private static void addCommonActivitySampleProperties(String superClass, Entity activitySample, Entity user, Entity device) { activitySample.setSuperclass(superClass); activitySample.addImport(MAIN_PACKAGE + ".devices.SampleProvider"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java index b9e3326d5..a5259fc9f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java @@ -55,6 +55,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getContext; @@ -198,7 +199,9 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator { } public static byte getTimeMode(String deviceAddress) { - String tmode = GBApplication.getDeviceSpecificSharedPrefs(deviceAddress).getString(DeviceSettingsPreferenceConst.PREF_TIMEFORMAT, "24h"); + GBPrefs gbPrefs = new GBPrefs(new Prefs(GBApplication.getDeviceSpecificSharedPrefs(deviceAddress))); + + String tmode = gbPrefs.getTimeFormat(); if ("24h".equals(tmode)) { return HPlusConstants.ARG_TIMEMODE_24H; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java index a172fb72f..ad2e788da 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java @@ -81,6 +81,7 @@ public class AmazfitBipCoordinator extends HuamiCoordinator { public int[] getSupportedDeviceSpecificSettings(GBDevice device) { return new int[]{ R.xml.devicesettings_amazfitbip, + R.xml.devicesettings_timeformat, R.xml.devicesettings_wearlocation, R.xml.devicesettings_custom_emoji_font, R.xml.devicesettings_liftwrist_display, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java index 7b35d5a88..18ac09a69 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java @@ -85,6 +85,7 @@ public class AmazfitCorCoordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_amazfitcor, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_custom_emoji_font, R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_disconnectnotification, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor2/AmazfitCor2Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor2/AmazfitCor2Coordinator.java index 3f59b5287..4c8c68aa3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor2/AmazfitCor2Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor2/AmazfitCor2Coordinator.java @@ -87,6 +87,7 @@ public class AmazfitCor2Coordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_amazfitcor, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_custom_emoji_font, R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_disconnectnotification, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java index f58f66dd0..863079fd7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgtr/AmazfitGTRCoordinator.java @@ -90,6 +90,7 @@ public class AmazfitGTRCoordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_amazfitgtr, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_disconnectnotification, R.xml.devicesettings_expose_hr_thirdparty, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java index 1d14079c0..d88b75b7a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts/AmazfitGTSCoordinator.java @@ -90,6 +90,7 @@ public class AmazfitGTSCoordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_amazfitgtr, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_disconnectnotification, R.xml.devicesettings_expose_hr_thirdparty, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java index 7573541f5..686f1dd7c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java @@ -80,6 +80,7 @@ public class MiBand2Coordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_miband2, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_donotdisturb_withauto, R.xml.devicesettings_liftwrist_display, R.xml.devicesettings_rotatewrist_cycleinfo, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband3/MiBand3Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband3/MiBand3Coordinator.java index d2f23274a..0c8e17b00 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband3/MiBand3Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband3/MiBand3Coordinator.java @@ -104,6 +104,7 @@ public class MiBand3Coordinator extends HuamiCoordinator { return new int[]{ R.xml.devicesettings_miband3, R.xml.devicesettings_wearlocation, + R.xml.devicesettings_timeformat, R.xml.devicesettings_dateformat, R.xml.devicesettings_nightmode, R.xml.devicesettings_donotdisturb_withauto, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java index c6cf1dab4..b7a0d8c09 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband4/MiBand4Coordinator.java @@ -91,6 +91,7 @@ public class MiBand4Coordinator extends HuamiCoordinator { R.xml.devicesettings_miband3, R.xml.devicesettings_wearlocation, R.xml.devicesettings_custom_emoji_font, + R.xml.devicesettings_timeformat, R.xml.devicesettings_dateformat, R.xml.devicesettings_nightmode, R.xml.devicesettings_liftwrist_display, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java index b18c65d85..2aac395a3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouConstants.java @@ -36,12 +36,17 @@ public final class JYouConstants { public static final byte CMD_SET_SLEEP_TIME = 0x27; public static final byte CMD_SET_DND_SETTINGS = 0x39; public static final byte CMD_SET_INACTIVITY_WARNING_TIME = 0x24; + public static final byte CMD_ACTION_HEARTRATE_SWITCH = 0x0D; public static final byte CMD_ACTION_SHOW_NOTIFICATION = 0x2C; public static final byte CMD_ACTION_REBOOT_DEVICE = 0x0E; - public static final byte RECEIVE_BATTERY_LEVEL = (byte)0xF7; + public static final byte RECEIVE_HISTORY_SLEEP_COUNT = 0x32; + public static final byte RECEIVE_BLOOD_PRESSURE = (byte) 0xE8; + public static final byte RECEIVE_WATCH_MAC = (byte)0xEC; + public static final byte RECEIVE_GET_PHOTO = (byte)0xF3; public static final byte RECEIVE_DEVICE_INFO = (byte)0xF6; + public static final byte RECEIVE_BATTERY_LEVEL = (byte)0xF7; public static final byte RECEIVE_STEPS_DATA = (byte)0xF9; public static final byte RECEIVE_HEARTRATE = (byte)0xFC; @@ -54,4 +59,4 @@ public final class JYouConstants { public static final byte ICON_TWITTER = 6; public static final byte ICON_WHATSAPP = 7; public static final byte ICON_LINE = 8; -} +} \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouSampleProvider.java new file mode 100644 index 000000000..b29c02b51 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/JYouSampleProvider.java @@ -0,0 +1,70 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.jyou; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.JYouActivitySample; +import nodomain.freeyourgadget.gadgetbridge.entities.JYouActivitySampleDao; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; + +public class JYouSampleProvider extends AbstractSampleProvider { + + public static final int TYPE_ACTIVITY = -1; + private final float movementDivisor = 6000.0f; + private GBDevice mDevice; + private DaoSession mSession; + + public JYouSampleProvider(GBDevice device, DaoSession session) { + super(device, session); + + mSession = session; + mDevice = device; + } + + @Override + public int normalizeType(int rawType) { + return rawType; + } + + @Override + public int toRawActivityKind(int activityKind) { + return activityKind; + } + + @Override + public float normalizeIntensity(int rawIntensity) { + return rawIntensity/movementDivisor; + } + + @Override + public JYouActivitySample createActivitySample() { + return new JYouActivitySample(); + } + + @Override + public AbstractDao getSampleDao() { + return getSession().getJYouActivitySampleDao(); + } + + @Nullable + @Override + protected Property getRawKindSampleProperty() { + return JYouActivitySampleDao.Properties.RawKind; + } + + @NonNull + @Override + protected Property getTimestampSampleProperty() { + return JYouActivitySampleDao.Properties.Timestamp; + } + + @NonNull + @Override + protected Property getDeviceIdentifierSampleProperty() { + return JYouActivitySampleDao.Properties.DeviceId; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30/TeclastH30Coordinator.java similarity index 97% rename from app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java rename to app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30/TeclastH30Coordinator.java index 68a464af4..6b87a661e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30/TeclastH30Coordinator.java @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.devices.jyou; +package nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30; import android.annotation.TargetApi; import android.app.Activity; @@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouConstants; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/y5/Y5Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/y5/Y5Coordinator.java new file mode 100644 index 000000000..af3f262dc --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/y5/Y5Coordinator.java @@ -0,0 +1,132 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.jyou.y5; + +import android.app.Activity; +import android.content.Context; +import android.net.Uri; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import de.greenrobot.dao.query.QueryBuilder; +import nodomain.freeyourgadget.gadgetbridge.GBException; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.JYouActivitySampleDao; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +public class Y5Coordinator extends AbstractDeviceCoordinator { + @Override + protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { + Long deviceId = device.getId(); + QueryBuilder qb = session.getJYouActivitySampleDao().queryBuilder(); + qb.where(JYouActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities(); + } + + @NonNull + @Override + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + try { + String name = candidate.getDevice().getName(); + if (name != null) { + if (name.contains("Y5")) { + return DeviceType.Y5; + } + } + } catch (Exception ex) { + ex.getLocalizedMessage(); + } + return DeviceType.UNKNOWN; + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.Y5; + } + + @Nullable + @Override + public Class getPairingActivity() { + return null; + } + + @Override + public boolean supportsActivityDataFetching() { + return true; + } + + @Override + public boolean supportsActivityTracking() { + return true; + } + + @Override + public SampleProvider getSampleProvider(GBDevice device, DaoSession session) { + return new JYouSampleProvider(device, session); + } + + @Override + public InstallHandler findInstallHandler(Uri uri, Context context) { + return null; + } + + @Override + public boolean supportsScreenshots() { + return false; + } + + @Override + public int getAlarmSlotCount() { + return 3; + } + + @Override + public boolean supportsSmartWakeup(GBDevice device) { + return true; + } + + @Override + public boolean supportsHeartRateMeasurement(GBDevice device) { + return true; + } + + @Override + public String getManufacturer() { + return "Y5"; + } + + @Override + public boolean supportsAppsManagement() { + return false; + } + + @Override + public Class getAppsManagementActivity() { + return null; + } + + @Override + public boolean supportsCalendarEvents() { + return false; + } + + @Override + public boolean supportsRealtimeData() { + return true; + } + + @Override + public boolean supportsWeather() { + return false; + } + + @Override + public boolean supportsFindDevice() { + return true; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/makibeshr3/MakibesHR3Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/makibeshr3/MakibesHR3Coordinator.java index 9702b869b..528304246 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/makibeshr3/MakibesHR3Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/makibeshr3/MakibesHR3Coordinator.java @@ -35,6 +35,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.greenrobot.dao.query.QueryBuilder; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; @@ -48,6 +49,8 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getContext; @@ -75,7 +78,9 @@ public class MakibesHR3Coordinator extends AbstractDeviceCoordinator { } public static byte getTimeMode(SharedPreferences sharedPrefs) { - String timeMode = sharedPrefs.getString(DeviceSettingsPreferenceConst.PREF_TIMEFORMAT, getContext().getString(R.string.p_timeformat_24h)); + GBPrefs gbPrefs = new GBPrefs(new Prefs(sharedPrefs)); + + String timeMode = gbPrefs.getTimeFormat(); if (timeMode.equals(getContext().getString(R.string.p_timeformat_24h))) { return MakibesHR3Constants.ARG_SET_TIMEMODE_24H; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java index 8859c8bb8..8b79d1006 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java @@ -63,6 +63,7 @@ public class AppNotificationType extends HashMap { // Conversations put("eu.siacs.conversations", NotificationType.CONVERSATIONS); + put("de.pixart.messenger", NotificationType.CONVERSATIONS); // Riot put("im.vector.alpha", NotificationType.RIOT); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java index 9625f0db8..09ac3b466 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceType.java @@ -43,7 +43,6 @@ public enum DeviceType { AMAZFITBIP_LITE(17, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_bip_lite), AMAZFITGTR(18, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_gtr), AMAZFITGTS(19, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_amazfit_gts), - VIBRATISSIMO(20, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo), LIVEVIEW(30, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_liveview), HPLUS(40, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_hplus), MAKIBESF68(41, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_makibes_f68), @@ -51,6 +50,7 @@ public enum DeviceType { Q8(43, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_q8), NO1F1(50, R.drawable.ic_device_hplus, R.drawable.ic_device_hplus_disabled, R.string.devicetype_no1_f1), TECLASTH30(60, R.drawable.ic_device_h30_h10, R.drawable.ic_device_h30_h10_disabled, R.string.devicetype_teclast_h30), + Y5(61, R.drawable.ic_device_h30_h10, R.drawable.ic_device_roidmi_disabled, R.string.devicetype_y5), XWATCH(70, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_xwatch), FOSSILQHYBRID(80, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_qhybrid), ZETIME(80, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_mykronoz_zetime), @@ -64,6 +64,7 @@ public enum DeviceType { MAKIBESHR3(150, R.drawable.ic_device_default, R.drawable.ic_device_hplus_disabled, R.string.devicetype_makibes_hr3), BANGLEJS(160, R.drawable.ic_device_zetime, R.drawable.ic_device_zetime_disabled, R.string.devicetype_banglejs), MIJIA_LYWSD02(200, R.drawable.ic_device_pebble, R.drawable.ic_device_pebble_disabled, R.string.devicetype_mijia_lywsd02), + VIBRATISSIMO(300, R.drawable.ic_device_lovetoy, R.drawable.ic_device_lovetoy_disabled, R.string.devicetype_vibratissimo), TEST(1000, R.drawable.ic_device_default, R.drawable.ic_device_default_disabled, R.string.devicetype_test); private final int key; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java index b30bf3db8..95ac4695d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupportFactory.java @@ -45,7 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband3.MiBand import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.miband4.MiBand4Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.id115.ID115Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.BFH16DeviceSupport; -import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30Support; +import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30.TeclastH30Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.makibeshr3.MakibesHR3DeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport; @@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSuppo import nodomain.freeyourgadget.gadgetbridge.service.devices.roidmi.RoidmiSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.vibratissimo.VibratissimoSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.watch9.Watch9DeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.y5.Y5Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch.XWatchSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.zetime.ZeTimeDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -203,6 +204,9 @@ public class DeviceSupportFactory { case ROIDMI3: deviceSupport = new ServiceDeviceSupport(new RoidmiSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; + case Y5: + deviceSupport = new ServiceDeviceSupport(new Y5Support(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); + break; case CASIOGB6900: deviceSupport = new ServiceDeviceSupport(new CasioGB6900DeviceSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING)); break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index b664d11bc..09835e5cd 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -130,6 +130,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol; import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; import nodomain.freeyourgadget.gadgetbridge.util.NotificationUtils; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; @@ -1700,6 +1701,9 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { case MiBandConst.PREF_SWIPE_UNLOCK: setBandScreenUnlock(builder); break; + case DeviceSettingsPreferenceConst.PREF_TIMEFORMAT: + setTimeFormat(builder); + break; case DeviceSettingsPreferenceConst.PREF_DATEFORMAT: setDateFormat(builder); break; @@ -1952,9 +1956,11 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { } private HuamiSupport setTimeFormat(TransactionBuilder builder) { - boolean is24Format = DateFormat.is24HourFormat(getContext()); - LOG.info("Setting 24h time format to " + is24Format); - if (is24Format) { + GBPrefs gbPrefs = new GBPrefs(new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()))); + String timeFormat = gbPrefs.getTimeFormat(); + + LOG.info("Setting time format to " + timeFormat); + if (timeFormat.equals("24h")) { builder.write(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_3_CONFIGURATION), HuamiService.DATEFORMAT_TIME_24_HOURS); } else { builder.write(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_3_CONFIGURATION), HuamiService.DATEFORMAT_TIME_12_HOURS); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouDataRecord.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouDataRecord.java new file mode 100644 index 000000000..ec9f08999 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouDataRecord.java @@ -0,0 +1,65 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.jyou; + +/* + * @author Pavel Elagin <elagin.pasha@gmail.com> + */ + +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; + +public class JYouDataRecord { + public final static int TYPE_UNKNOWN = 0; + public final static int TYPE_SLEEP = 100; + public final static int TYPE_DAY_SUMMARY = 101; + public final static int TYPE_DAY_SLOT = 102; + public final static int TYPE_REALTIME = 103; + + public int type = TYPE_UNKNOWN; + public int activityKind = ActivityKind.TYPE_UNKNOWN; + + /** + * Time of this record in seconds + */ + public int timestamp; + + /** + * Raw data as sent from the device + */ + public byte[] rawData; + + protected JYouDataRecord(){ + + } + + protected JYouDataRecord(byte[] data, int type){ + this.rawData = data; + this.type = type; + } + + public byte[] getRawData() { + + return rawData; + } + + public class RecordInterval { + /** + * Start time of this interval in seconds + */ + public int timestampFrom; + + /** + * End time of this interval in seconds + */ + public int timestampTo; + + /** + * Type of activity {@link ActivityKind} + */ + public int activityKind; + + RecordInterval(int timestampFrom, int timestampTo, int activityKind) { + this.timestampFrom = timestampFrom; + this.timestampTo = timestampTo; + this.activityKind = activityKind; + } + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouSupport.java similarity index 72% rename from app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java rename to app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouSupport.java index 368966e15..5f83a4c52 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/JYouSupport.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.widget.Toast; import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -50,29 +49,32 @@ import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; -public class TeclastH30Support extends AbstractBTLEDeviceSupport { +public class JYouSupport extends AbstractBTLEDeviceSupport { - private static final Logger LOG = LoggerFactory.getLogger(TeclastH30Support.class); + private Logger logger; - public BluetoothGattCharacteristic ctrlCharacteristic = null; - public BluetoothGattCharacteristic measureCharacteristic = null; + protected BluetoothGattCharacteristic ctrlCharacteristic = null; - private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo(); - private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo(); + protected final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo(); + protected final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo(); - public TeclastH30Support() { - super(LOG); + public JYouSupport(Logger logger) { + super(logger); + this.logger = logger; + if (logger == null) { + throw new IllegalArgumentException("logger must not be null"); + } addSupportedService(JYouConstants.UUID_SERVICE_JYOU); } @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { - LOG.info("Initializing"); + logger.info("Initializing"); gbDevice.setState(GBDevice.State.INITIALIZING); gbDevice.sendDeviceUpdateIntent(getContext()); - measureCharacteristic = getCharacteristic(JYouConstants.UUID_CHARACTERISTIC_MEASURE); + BluetoothGattCharacteristic measureCharacteristic = getCharacteristic(JYouConstants.UUID_CHARACTERISTIC_MEASURE); ctrlCharacteristic = getCharacteristic(JYouConstants.UUID_CHARACTERISTIC_CONTROL); builder.setGattCallback(this); @@ -83,7 +85,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { gbDevice.setState(GBDevice.State.INITIALIZED); gbDevice.sendDeviceUpdateIntent(getContext()); - LOG.info("Initialization Done"); + logger.info("Initialization Done"); return builder; } @@ -91,41 +93,10 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - if (super.onCharacteristicChanged(gatt, characteristic)) { - return true; - } - - UUID characteristicUUID = characteristic.getUuid(); - byte[] data = characteristic.getValue(); - if (data.length == 0) - return true; - - switch (data[0]) { - case JYouConstants.RECEIVE_DEVICE_INFO: - int fwVerNum = data[4] & 0xFF; - versionCmd.fwVersion = (fwVerNum / 100) + "." + ((fwVerNum % 100) / 10) + "." + ((fwVerNum % 100) % 10); - handleGBDeviceEvent(versionCmd); - LOG.info("Firmware version is: " + versionCmd.fwVersion); - return true; - case JYouConstants.RECEIVE_BATTERY_LEVEL: - batteryCmd.level = data[8]; - handleGBDeviceEvent(batteryCmd); - LOG.info("Battery level is: " + batteryCmd.level); - return true; - case JYouConstants.RECEIVE_STEPS_DATA: - int steps = ByteBuffer.wrap(data, 5, 4).getInt(); - LOG.info("Number of walked steps: " + steps); - return true; - case JYouConstants.RECEIVE_HEARTRATE: - LOG.info("Current heart rate: " + data[8]); - return true; - default: - LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + String.format("0x%1x ...", data[0])); - return true; - } + return super.onCharacteristicChanged(gatt, characteristic); } - private void syncDateAndTime(TransactionBuilder builder) { + protected void syncDateAndTime(TransactionBuilder builder) { Calendar cal = Calendar.getInstance(); String strYear = String.valueOf(cal.get(Calendar.YEAR)); byte year1 = (byte)Integer.parseInt(strYear.substring(0, 2)); @@ -144,45 +115,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { )); } - private void syncSettings(TransactionBuilder builder) { - syncDateAndTime(builder); - - // TODO: unhardcode and separate stuff - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_HEARTRATE_WARNING_VALUE, 0, 152 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_TARGET_STEPS, 0, 10000 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_GET_STEP_COUNT, 0, 0 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_GET_SLEEP_TIME, 0, 0 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_NOON_TIME, 12 * 60 * 60, 14 * 60 * 60 // 12:00 - 14:00 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_SLEEP_TIME, 21 * 60 * 60, 8 * 60 * 60 // 21:00 - 08:00 - )); - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_INACTIVITY_WARNING_TIME, 0, 0 - )); - - // do not disturb and a couple more features - byte dndStartHour = 22; - byte dndStartMin = 0; - byte dndEndHour = 8; - byte dndEndMin = 0; - boolean dndToggle = false; - boolean vibrationToggle = true; - boolean wakeOnRaiseToggle = true; - builder.write(ctrlCharacteristic, commandWithChecksum( - JYouConstants.CMD_SET_DND_SETTINGS, - (dndStartHour << 24) | (dndStartMin << 16) | (dndEndHour << 8) | dndEndMin, - ((dndToggle ? 0 : 1) << 2) | ((vibrationToggle ? 1 : 0) << 1) | (wakeOnRaiseToggle ? 1 : 0) - )); + protected void syncSettings(TransactionBuilder builder) { } private void showNotification(byte icon, String title, String message) { @@ -217,9 +150,9 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { } builder.write(ctrlCharacteristic, currentPacket); } - builder.queue(getQueue()); + performConnected(builder.getTransaction()); } catch (IOException e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @@ -286,10 +219,10 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { alarms.get(i).getEnabled() ? cal.get(Calendar.MINUTE) : -1 )); } - builder.queue(getQueue()); + performConnected(builder.getTransaction()); GB.toast(getContext(), "Alarm settings applied - do note that the current device does not support day specification", Toast.LENGTH_LONG, GB.INFO); } catch(IOException e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @@ -298,18 +231,16 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { try { TransactionBuilder builder = performInitialized("SetTime"); syncDateAndTime(builder); - builder.queue(getQueue()); + performConnected(builder.getTransaction()); } catch(IOException e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @Override public void onSetCallState(CallSpec callSpec) { - switch (callSpec.command) { - case CallSpec.CALL_INCOMING: - showNotification(JYouConstants.ICON_CALL, callSpec.name, callSpec.number); - break; + if(callSpec.command == CallSpec.CALL_INCOMING) { + showNotification(JYouConstants.ICON_CALL, callSpec.name, callSpec.number); } } @@ -375,9 +306,9 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { builder.write(ctrlCharacteristic, commandWithChecksum( JYouConstants.CMD_ACTION_REBOOT_DEVICE, 0, 0 )); - builder.queue(getQueue()); + performConnected(builder.getTransaction()); } catch(Exception e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @@ -388,15 +319,14 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { builder.write(ctrlCharacteristic, commandWithChecksum( JYouConstants.CMD_ACTION_HEARTRATE_SWITCH, 0, 1 )); - builder.queue(getQueue()); + performConnected(builder.getTransaction()); } catch(Exception e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @Override public void onEnableRealtimeHeartRateMeasurement(boolean enable) { - // TODO: test try { TransactionBuilder builder = performInitialized("RealTimeHeartMeasurement"); builder.write(ctrlCharacteristic, commandWithChecksum( @@ -404,7 +334,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { )); builder.queue(getQueue()); } catch(Exception e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } } @@ -466,7 +396,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { } - private byte[] commandWithChecksum(byte cmd, int argSlot1, int argSlot2) + protected byte[] commandWithChecksum(byte cmd, int argSlot1, int argSlot2) { ByteBuffer buf = ByteBuffer.allocate(10); buf.put(cmd); @@ -505,7 +435,7 @@ public class TeclastH30Support extends AbstractBTLEDeviceSupport { } } } catch (UnsupportedEncodingException e) { - LOG.warn(e.getMessage()); + logger.warn(e.getMessage()); } return null; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/RealtimeSamplesSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/RealtimeSamplesSupport.java new file mode 100644 index 000000000..c75d0d19f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/RealtimeSamplesSupport.java @@ -0,0 +1,95 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.jyou; + +import java.util.Timer; +import java.util.TimerTask; + +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; + +public abstract class RealtimeSamplesSupport { + private final long delay; + private final long period; + + protected int steps; + protected int heartrateBpm; + private int lastSteps; + // subclasses may add more + + private Timer realtimeStorageTimer; + + public RealtimeSamplesSupport(long delay, long period) { + this.delay = delay; + this.period = period; + } + + public synchronized void start() { + if (isRunning()) { + return; // already running + } + realtimeStorageTimer = new Timer("JYou Realtime Storage Timer"); + realtimeStorageTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + triggerCurrentSample(); + } + }, delay, period); + } + + public synchronized void stop() { + if (realtimeStorageTimer != null) { + realtimeStorageTimer.cancel(); + realtimeStorageTimer.purge(); + realtimeStorageTimer = null; + } + } + + public synchronized boolean isRunning() { + return realtimeStorageTimer != null; + } + + public synchronized void setSteps(int stepsPerMinute) { + this.steps = stepsPerMinute; + } + + /** + * Returns the number of steps recorded since the last measurements. If no + * steps are available yet, ActivitySample.NOT_MEASURED is returned. + * @return + */ + public synchronized int getSteps() { + if (steps == ActivitySample.NOT_MEASURED) { + return ActivitySample.NOT_MEASURED; + } + if (lastSteps == 0) { + return ActivitySample.NOT_MEASURED; // wait until we have a delta between two samples + } + int delta = steps - lastSteps; + if (delta < 0) { + return 0; + } + return delta; + } + + public void setHeartrateBpm(int hrBpm) { + this.heartrateBpm = hrBpm; + } + + public int getHeartrateBpm() { + return heartrateBpm; + } + + public void triggerCurrentSample() { + doCurrentSample(); + resetCurrentValues(); + } + + protected synchronized void resetCurrentValues() { + if (steps >= lastSteps) { + lastSteps = steps; + } + steps = ActivitySample.NOT_MEASURED; + heartrateBpm = ActivitySample.NOT_MEASURED; + } + + protected abstract void doCurrentSample(); +} + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30/TeclastH30Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30/TeclastH30Support.java new file mode 100644 index 000000000..69c6f942f --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/TeclastH30/TeclastH30Support.java @@ -0,0 +1,121 @@ +/* Copyright (C) 2017-2019 Andreas Shimokawa, Carsten Pfeiffer, Sami Alaoui, + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.TeclastH30; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouConstants; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.JYouSupport; + +public class TeclastH30Support extends JYouSupport { + + private static final Logger LOG = LoggerFactory.getLogger(TeclastH30Support.class); + + public TeclastH30Support() { + super(LOG); + addSupportedService(JYouConstants.UUID_SERVICE_JYOU); + } + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + if (super.onCharacteristicChanged(gatt, characteristic)) { + return true; + } + + UUID characteristicUUID = characteristic.getUuid(); + byte[] data = characteristic.getValue(); + if (data.length == 0) + return true; + + switch (data[0]) { + case JYouConstants.RECEIVE_DEVICE_INFO: + int fwVerNum = data[4] & 0xFF; + versionCmd.fwVersion = (fwVerNum / 100) + "." + ((fwVerNum % 100) / 10) + "." + ((fwVerNum % 100) % 10); + handleGBDeviceEvent(versionCmd); + LOG.info("Firmware version is: " + versionCmd.fwVersion); + return true; + case JYouConstants.RECEIVE_BATTERY_LEVEL: + batteryCmd.level = data[8]; + handleGBDeviceEvent(batteryCmd); + LOG.info("Battery level is: " + batteryCmd.level); + return true; + case JYouConstants.RECEIVE_STEPS_DATA: + int steps = ByteBuffer.wrap(data, 5, 4).getInt(); + LOG.info("Number of walked steps: " + steps); + return true; + case JYouConstants.RECEIVE_HEARTRATE: + LOG.info("Current heart rate: " + data[8]); + return true; + default: + LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + String.format("0x%1x ...", data[0])); + return true; + } + } + + @Override + protected void syncSettings(TransactionBuilder builder) { + syncDateAndTime(builder); + + // TODO: unhardcode and separate stuff + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_HEARTRATE_WARNING_VALUE, 0, 152 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_TARGET_STEPS, 0, 10000 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_GET_STEP_COUNT, 0, 0 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_GET_SLEEP_TIME, 0, 0 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_NOON_TIME, 12 * 60 * 60, 14 * 60 * 60 // 12:00 - 14:00 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_SLEEP_TIME, 21 * 60 * 60, 8 * 60 * 60 // 21:00 - 08:00 + )); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_INACTIVITY_WARNING_TIME, 0, 0 + )); + + // do not disturb and a couple more features + byte dndStartHour = 22; + byte dndStartMin = 0; + byte dndEndHour = 8; + byte dndEndMin = 0; + boolean dndToggle = false; + boolean vibrationToggle = true; + boolean wakeOnRaiseToggle = true; + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_DND_SETTINGS, + (dndStartHour << 24) | (dndStartMin << 16) | (dndEndHour << 8) | dndEndMin, + ((dndToggle ? 0 : 1) << 2) | ((vibrationToggle ? 1 : 0) << 1) | (wakeOnRaiseToggle ? 1 : 0) + )); + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/y5/Y5Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/y5/Y5Support.java new file mode 100644 index 000000000..96ef0d41a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/jyou/y5/Y5Support.java @@ -0,0 +1,233 @@ +/* Copyright (C) 2017-2019 Andreas Shimokawa, Carsten Pfeiffer, Sami Alaoui, + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.y5; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.Intent; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.JYouSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.JYouActivitySample; +import nodomain.freeyourgadget.gadgetbridge.entities.User; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.JYouSupport; +import nodomain.freeyourgadget.gadgetbridge.service.devices.jyou.RealtimeSamplesSupport; + +public class Y5Support extends JYouSupport { + private static final Logger LOG = LoggerFactory.getLogger(Y5Support.class); + + private RealtimeSamplesSupport realtimeSamplesSupport; + + + public Y5Support() { + super(LOG); + addSupportedService(JYouConstants.UUID_SERVICE_JYOU); + } + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + if (super.onCharacteristicChanged(gatt, characteristic)) { + return true; + } + + UUID characteristicUUID = characteristic.getUuid(); + byte[] data = characteristic.getValue(); + if (data.length == 0) + return true; + + switch (data[0]) { + case JYouConstants.RECEIVE_HISTORY_SLEEP_COUNT: + LOG.info("onCharacteristicChanged: " + data[0]); + return true; + case JYouConstants.RECEIVE_BLOOD_PRESSURE: + int heartRate = data[2]; + int bloodPressureHigh = data[3]; + int bloodPressureLow = data[4]; + int bloodOxygen = data[5]; + int Fatigue = data[6]; + LOG.info("RECEIVE_BLOOD_PRESSURE: Heart rate: " + heartRate + " Pressure high: " + bloodPressureHigh+ " pressure low: " + bloodPressureLow); + return true; + case JYouConstants.RECEIVE_DEVICE_INFO: + int model = data[7]; + int fwVerNum = data[4] & 0xFF; + versionCmd.fwVersion = (fwVerNum / 100) + "." + ((fwVerNum % 100) / 10) + "." + ((fwVerNum % 100) % 10); + handleGBDeviceEvent(versionCmd); + LOG.info("Firmware version is: " + versionCmd.fwVersion); + return true; + case JYouConstants.RECEIVE_BATTERY_LEVEL: + batteryCmd.level = data[8]; + handleGBDeviceEvent(batteryCmd); + LOG.info("Battery level is: " + batteryCmd.level); + return true; + case JYouConstants.RECEIVE_STEPS_DATA: + int steps = ByteBuffer.wrap(data, 5, 4).getInt(); + LOG.info("Number of walked steps: " + steps); + handleRealtimeSteps(steps); + return true; + case JYouConstants.RECEIVE_HEARTRATE: + handleHeartrate(data[8]); + return true; + case JYouConstants.RECEIVE_WATCH_MAC: + return true; + case JYouConstants.RECEIVE_GET_PHOTO: + return true; + default: + LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + String.format("0x%1x ...", data[0])); + return true; + } + } + + private void handleRealtimeSteps(int value) { + //todo Call on connect the device + if (LOG.isDebugEnabled()) { + LOG.debug("realtime steps: " + value); + } + getRealtimeSamplesSupport().setSteps(value); + } + + private void handleHeartrate(int value) { + if (LOG.isDebugEnabled()) { + LOG.debug("heart rate: " + value); + } + RealtimeSamplesSupport realtimeSamplesSupport = getRealtimeSamplesSupport(); + realtimeSamplesSupport.setHeartrateBpm(value); + if (!realtimeSamplesSupport.isRunning()) { + // single shot measurement, manually invoke storage and result publishing + realtimeSamplesSupport.triggerCurrentSample(); + } + } + + public JYouActivitySample createActivitySample(Device device, User user, int timestampInSeconds, SampleProvider provider) { + JYouActivitySample sample = new JYouActivitySample(); + sample.setDevice(device); + sample.setUser(user); + sample.setTimestamp(timestampInSeconds); + sample.setProvider(provider); + return sample; + } + + private void enableRealtimeSamplesTimer(boolean enable) { + if (enable) { + getRealtimeSamplesSupport().start(); + } else { + if (realtimeSamplesSupport != null) { + realtimeSamplesSupport.stop(); + } + } + } + + private RealtimeSamplesSupport getRealtimeSamplesSupport() { + if (realtimeSamplesSupport == null) { + realtimeSamplesSupport = new RealtimeSamplesSupport(1000, 1000) { + @Override + public void doCurrentSample() { + + try (DBHandler handler = GBApplication.acquireDB()) { + DaoSession session = handler.getDaoSession(); + int ts = (int) (System.currentTimeMillis() / 1000); + JYouSampleProvider provider = new JYouSampleProvider(gbDevice, session); + JYouActivitySample sample = createActivitySample(DBHelper.getDevice(getDevice(), session), DBHelper.getUser(session), ts, provider); + sample.setHeartRate(getHeartrateBpm()); + sample.setRawIntensity(ActivitySample.NOT_MEASURED); + sample.setRawKind(JYouSampleProvider.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that? + + provider.addGBActivitySample(sample); + + // set the steps only afterwards, since realtime steps are also recorded + // in the regular samples and we must not count them twice + // Note: we know that the DAO sample is never committed again, so we simply + // change the value here in memory. + sample.setSteps(getSteps()); + if(steps > 1){ + LOG.debug("Have steps: " + getSteps()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("realtime sample: " + sample); + } + + Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES) + .putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample); + LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); + + } catch (Exception e) { + LOG.warn("Unable to acquire db for saving realtime samples", e); + } + } + }; + } + return realtimeSamplesSupport; + } + + @Override + protected void syncSettings(TransactionBuilder builder) { + syncDateAndTime(builder); + } + + @Override + public void dispose() { + LOG.info("Dispose"); + super.dispose(); + } + + @Override + public void onHeartRateTest() { + try { + TransactionBuilder builder = performInitialized("HeartRateTest"); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_SET_HEARTRATE_AUTO, 0, 0 + + )); + performConnected(builder.getTransaction()); + } catch(Exception e) { + LOG.warn(e.getMessage()); + } + } + + @Override + public void onEnableRealtimeHeartRateMeasurement(boolean enable) { + try { + TransactionBuilder builder = performInitialized("RealTimeHeartMeasurement"); + builder.write(ctrlCharacteristic, commandWithChecksum( + JYouConstants.CMD_ACTION_HEARTRATE_SWITCH, 0, enable ? 1 : 0 + )); + performConnected(builder.getTransaction()); + enableRealtimeSamplesTimer(enable); + } catch (Exception e) { + LOG.warn(e.getMessage()); + } + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java index e997d1018..c613ab9b6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java @@ -13,6 +13,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.FileInputStream; import java.io.IOException; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; @@ -24,6 +25,7 @@ import java.util.TimeZone; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.Widget; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.HRConfigActivity; +import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationHRConfiguration; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; @@ -34,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.foss import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest.TimeConfigItem; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileCloseRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.authentication.VerifyPrivateKeyRequest; @@ -49,6 +52,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicControlRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.music.MusicInfoSetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationFilterPutHRRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImage; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.NotificationImagePutRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.notification.PlayNotificationHRRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidget; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.widget.CustomWidgetElement; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.utils.StringUtils; @@ -64,9 +70,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { CustomWidget[] widgets = new CustomWidget[0]; + NotificationHRConfiguration[] notificationConfigurations; + private MusicSpec currentSpec = null; int imageNameIndex = 0; + private byte jsonIndex = 0; public FossilHRWatchAdapter(QHybridSupport deviceSupport) { super(deviceSupport); @@ -86,21 +95,43 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { // icons - // queueWrite(new NotificationFilterPutHRRequest(new NotificationHRConfiguration[]{ - // new NotificationHRConfiguration("com.whatsapp", -1), - // new NotificationHRConfiguration("asdasdasdasdasd", -1), - // // new NotificationHRConfiguration("twitter", -1), - // }, this)); + loadNotificationConfigurations(); + // queueWrite(new NotificationFilterPutHRRequest(this.notificationConfigurations,this)); - // queueWrite(new PlayNotificationRequest("com.whatsapp", "WhatsAp", "wHATSaPP", this)); - // queueWrite(new PlayNotificationRequest("twitterrrr", "Twitterr", "tWITTER", this));queueWrite(new NotificationFilterPutRequest( - // new NotificationConfiguration[]{ - // new NotificationConfiguration((short) -1, (short) -1, "generic", "", false, PlayNotificationRequest.VibrationType.SINGLE_LONG, 0) - // }, + String[] appNames = {"instagram", "snapchat", "line", "whatsapp"}; + String[] paths = { + "/storage/emulated/0/Q/images/icInstagram.icon", + "/storage/emulated/0/Q/images/icSnapchat.icon", + "/storage/emulated/0/Q/images/icLine.icon", + "/storage/emulated/0/Q/images/icWhatsapp.icon" + }; + /*NotificationHRConfiguration[] configs = new NotificationHRConfiguration[4]; + NotificationImage[] images = new NotificationImage[4]; - queueWrite(new NotificationFilterPutHRRequest(new NotificationHRConfiguration[]{ - new NotificationHRConfiguration("generic", 0) - },this)); + + try { + for(int i = 0; i < 4; i++){ + FileInputStream fis = new FileInputStream(paths[i]); + byte[] imageData = new byte[fis.available()]; + fis.read(imageData); + fis.close(); + configs[i] = new NotificationHRConfiguration(appNames[i], i); + images[i] = new NotificationImage(appNames[i], imageData); + } + queueWrite(new NotificationImagePutRequest(images, this)); + queueWrite(new NotificationFilterPutHRRequest(configs, this)); + } catch (Exception e) { + e.printStackTrace(); + } + + for(String appName : appNames){ + queueWrite(new PlayNotificationHRRequest( + appName, + appName.toUpperCase(), + "this is some strange message", + this + )); + }*/ syncSettings(); @@ -112,30 +143,15 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { renderWidgets(); // dunno if there is any point in doing this at start since when no watch is connected the QHybridSupport will not receive any intents anyway - /*try { - queueWrite(new AssetFilePutRequest(new AssetImage[]{ - AssetImageFactory.createAssetImage("0D58BD24", new byte[]{(byte) 0x18, (byte) 0x18, (byte) 0x1D, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x12, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x0E, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x0D, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x0D, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x0E, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x0F, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x11, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x04, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x07, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x0B, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x0D, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x1D, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}, 0, 0, 0), - AssetImageFactory.createAssetImage("AD365776", new byte[]{(byte) 0x18, (byte) 0x18, (byte) 0x1D, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x0B, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x07, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x08, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0A, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0C, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0D, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x04, (byte) 0x03, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x04, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x07, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x05, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x1D, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}, 0, 0, 0), - AssetImageFactory.createAssetImage("C3F69363", new byte[]{(byte) 0x18, (byte) 0x18, (byte) 0x1E, (byte) 0x00, (byte) 0x0C, (byte) 0x01, (byte) 0x09, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x0E, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x0E, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x0B, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x00, (byte) 0x0D, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x09, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x0F, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x11, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x12, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x16, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}, 0, 0, 0), - AssetImageFactory.createAssetImage("7251C82B", new byte[]{(byte) 0x18, (byte) 0x18, (byte) 0x3B, (byte) 0x0C, (byte) 0x02, (byte) 0x0D, (byte) 0x16, (byte) 0x0C, (byte) 0x02, (byte) 0x07, (byte) 0x16, (byte) 0x0C, (byte) 0x02, (byte) 0x03, (byte) 0x15, (byte) 0x0C, (byte) 0x01, (byte) 0x0A, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0A, (byte) 0x14, (byte) 0x0C, (byte) 0x04, (byte) 0x03, (byte) 0x13, (byte) 0x0C, (byte) 0x01, (byte) 0x09, (byte) 0x01, (byte) 0x03, (byte) 0x02, (byte) 0x0A, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x09, (byte) 0x0F, (byte) 0x0C, (byte) 0x02, (byte) 0x0D, (byte) 0x01, (byte) 0x09, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x0C, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x09, (byte) 0x02, (byte) 0x0D, (byte) 0x08, (byte) 0x0C, (byte) 0x01, (byte) 0x0A, (byte) 0x07, (byte) 0x03, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x0C, (byte) 0x01, (byte) 0x06, (byte) 0x07, (byte) 0x03, (byte) 0x01, (byte) 0x0A, (byte) 0x05, (byte) 0x0C, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x09, (byte) 0x01, (byte) 0x0D, (byte) 0x04, (byte) 0x0C, (byte) 0x01, (byte) 0x0D, (byte) 0x01, (byte) 0x09, (byte) 0x01, (byte) 0x0A, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x06, (byte) 0x07, (byte) 0x0C, (byte) 0x01, (byte) 0x0A, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0D, (byte) 0x08, (byte) 0x0C, (byte) 0x01, (byte) 0x0D, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0A, (byte) 0x09, (byte) 0x0C, (byte) 0x01, (byte) 0x09, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x09, (byte) 0x06, (byte) 0x0C, (byte) 0x01, (byte) 0x09, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x09, (byte) 0x0B, (byte) 0x0C, (byte) 0x01, (byte) 0x0D, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0D, (byte) 0x05, (byte) 0x0C, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0D, (byte) 0x0D, (byte) 0x0C, (byte) 0x01, (byte) 0x07, (byte) 0x01, (byte) 0x03, (byte) 0x06, (byte) 0x0C, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x0E, (byte) 0x0C, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x0C, (byte) 0x02, (byte) 0x09, (byte) 0x02, (byte) 0x0C, (byte) 0x01, (byte) 0x07, (byte) 0x01, (byte) 0x03, (byte) 0x0D, (byte) 0x0C, (byte) 0x01, (byte) 0x0D, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x06, (byte) 0x01, (byte) 0x0D, (byte) 0x01, (byte) 0x07, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x01, (byte) 0x0D, (byte) 0x01, (byte) 0x06, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x0D, (byte) 0x0C, (byte) 0x0C, (byte) 0x01, (byte) 0x09, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x02, (byte) 0x03, (byte) 0x02, (byte) 0x06, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x09, (byte) 0x0C, (byte) 0x0C, (byte) 0x01, (byte) 0x06, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x0D, (byte) 0x02, (byte) 0x0C, (byte) 0x01, (byte) 0x0D, (byte) 0x03, (byte) 0x03, (byte) 0x01, (byte) 0x06, (byte) 0x0C, (byte) 0x0C, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x0A, (byte) 0x06, (byte) 0x0C, (byte) 0x01, (byte) 0x0A, (byte) 0x02, (byte) 0x03, (byte) 0x0C, (byte) 0x0C, (byte) 0x01, (byte) 0x06, (byte) 0x0A, (byte) 0x0C, (byte) 0x01, (byte) 0x06, (byte) 0x4E, (byte) 0x0C, (byte) 0xFF, (byte) 0xFF}, 0, 0, 0), - }, this)); - } catch (IOException e) { - e.printStackTrace(); - }*/ - - /*queueWrite(new ImagesSetRequest( - new AssetImage[]{ - AssetImageFactory.createAssetImage("0D58BD24", null, 0, 60, 1), - AssetImageFactory.createAssetImage("AD365776", null, 90, 60, 1), - AssetImageFactory.createAssetImage("C3F69363", null, 180, 60, 1), - AssetImageFactory.createAssetImage("7251C82B", null, 270, 60, 1), - }, - this - )); -*/ queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED)); } + private void loadNotificationConfigurations(){ + this.notificationConfigurations = new NotificationHRConfiguration[]{ + new NotificationHRConfiguration("generic", 0), + }; + } + private void loadWidgets() { CustomWidget ethWidget = new CustomWidget(0, 63); ethWidget.addElement(new CustomWidgetElement(CustomWidgetElement.WidgetElementType.TYPE_TEXT, "date", "-", CustomWidgetElement.X_CENTER, CustomWidgetElement.Y_UPPER_HALF)); @@ -306,6 +322,12 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { String sender = notificationSpec.sender; if (sender == null) sender = notificationSpec.sourceName; try { + for (NotificationHRConfiguration configuration : this.notificationConfigurations){ + if(configuration.getPackageName().equals(notificationSpec.sourceAppId)){ + queueWrite(new PlayNotificationRequest(notificationSpec.sourceAppId, notificationSpec.sourceName, notificationSpec.body, this)); + return true; + } + } queueWrite(new PlayNotificationRequest("generic", notificationSpec.sourceName, notificationSpec.body, this)); }catch (Exception e){ e.printStackTrace(); @@ -437,4 +459,8 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { public void setCommuteMenuMessage(String message, boolean finished) { queueWrite(new SetCommuteMenuMessage(message, finished, this)); } + + public byte getJsonIndex() { + return jsonIndex++; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/buttons/ButtonConfigurationPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/buttons/ButtonConfigurationPutRequest.java index 043a63eeb..8e6f77b85 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/buttons/ButtonConfigurationPutRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/buttons/ButtonConfigurationPutRequest.java @@ -7,12 +7,13 @@ import org.json.JSONException; import org.json.JSONObject; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.json.JsonPutRequest; import nodomain.freeyourgadget.gadgetbridge.util.GB; public class ButtonConfigurationPutRequest extends JsonPutRequest { - public ButtonConfigurationPutRequest(String[] menuItems, FossilWatchAdapter adapter) { - super((short) 0x0500, createObject(menuItems), adapter); + public ButtonConfigurationPutRequest(String[] menuItems, FossilHRWatchAdapter adapter) { + super(createObject(menuItems), adapter); } private static JSONObject createObject(String[] menuItems) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/AssetFilePutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/AssetFilePutRequest.java index 893a8cd49..dd2935a25 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/AssetFilePutRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/AssetFilePutRequest.java @@ -11,14 +11,14 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.utils.String public class AssetFilePutRequest extends FilePutRequest { public AssetFilePutRequest(AssetFile[] files, FossilWatchAdapter adapter) throws IOException { - super((short) 0x0701, prepareFileData(files), adapter); + super((short) 0x0700, prepareFileData(files), adapter); } public AssetFilePutRequest(AssetFile file, FossilWatchAdapter adapter) throws IOException { - super((short) 0x0701, prepareFileData(file), adapter); + super((short) 0x0700, prepareFileData(file), adapter); } public AssetFilePutRequest(AssetFile file, int subHandle, FossilWatchAdapter adapter) throws IOException { - super((short) (0x0701 | subHandle), prepareFileData(file), adapter); + super((short) (0x0700 | subHandle), prepareFileData(file), adapter); } private static byte[] prepareFileData(AssetFile[] files) throws IOException { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/image/ImagesSetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/image/ImagesSetRequest.java index e7abf0050..bf854b85c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/image/ImagesSetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/image/ImagesSetRequest.java @@ -5,11 +5,12 @@ import org.json.JSONException; import org.json.JSONObject; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.json.JsonPutRequest; public class ImagesSetRequest extends JsonPutRequest { - public ImagesSetRequest(AssetImage[] images, FossilWatchAdapter adapter) { - super((short) 0x0503, prepareObject(images), adapter); + public ImagesSetRequest(AssetImage[] images, FossilHRWatchAdapter adapter) { + super(prepareObject(images), adapter); } private static JSONObject prepareObject(AssetImage[] images){ diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java index 5359355cf..40edc79c8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/json/JsonPutRequest.java @@ -3,11 +3,12 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fo import org.json.JSONObject; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FilePutRawRequest; public class JsonPutRequest extends FilePutRawRequest { - public JsonPutRequest(short handle, JSONObject object, FossilWatchAdapter adapter) { - super(handle, object.toString().getBytes(), adapter); + public JsonPutRequest(JSONObject object, FossilHRWatchAdapter adapter) { + super((short)(0x0500 | adapter.getJsonIndex()), object.toString().getBytes(), adapter); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/menu/SetCommuteMenuMessage.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/menu/SetCommuteMenuMessage.java index 4366e186e..8c6533eac 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/menu/SetCommuteMenuMessage.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/menu/SetCommuteMenuMessage.java @@ -4,11 +4,12 @@ import org.json.JSONException; import org.json.JSONObject; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.json.JsonPutRequest; public class SetCommuteMenuMessage extends JsonPutRequest { - public SetCommuteMenuMessage(String message, boolean finished, FossilWatchAdapter adapter) { - super((short) 0x0500, createObject(message, finished), adapter); + public SetCommuteMenuMessage(String message, boolean finished, FossilHRWatchAdapter adapter) { + super(createObject(message, finished), adapter); } private static JSONObject createObject(String message, boolean finished) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java index 5553cd8e4..d911b274f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/widget/WidgetsPutRequest.java @@ -5,12 +5,13 @@ import org.json.JSONException; import org.json.JSONObject; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.FilePutRawRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.json.JsonPutRequest; public class WidgetsPutRequest extends JsonPutRequest { - public WidgetsPutRequest(Widget[] widgets, FossilWatchAdapter adapter) { - super((short) 0x0501, prepareFile(widgets), adapter); + public WidgetsPutRequest(Widget[] widgets, FossilHRWatchAdapter adapter) { + super(prepareFile(widgets), adapter); } private static JSONObject prepareFile(Widget[] widgets){ diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java index ae0352a84..202f41095 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java @@ -67,6 +67,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; /** @@ -1682,7 +1683,9 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { } private void setTimeFormate(TransactionBuilder builder) { - String timeFormat = GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()).getString(DeviceSettingsPreferenceConst.PREF_TIMEFORMAT, "24h"); + GBPrefs gbPrefs = new GBPrefs(new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()))); + + String timeFormat = gbPrefs.getTimeFormat(); int type = 1; if ("am/pm".equals(timeFormat)) { type = 2; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java index 4ac3037d4..05d6562b8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/DeviceHelper.java @@ -60,8 +60,9 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2HRXCoor import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband3.MiBand3Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband4.MiBand4Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.id115.ID115Coordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30.TeclastH30Coordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.jyou.y5.Y5Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.jyou.BFH16DeviceCoordinator; -import nodomain.freeyourgadget.gadgetbridge.devices.jyou.TeclastH30Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.liveview.LiveviewCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; @@ -235,6 +236,7 @@ public class DeviceHelper { result.add(new Watch9DeviceCoordinator()); result.add(new Roidmi1Coordinator()); result.add(new Roidmi3Coordinator()); + result.add(new Y5Coordinator()); result.add(new CasioGB6900DeviceCoordinator()); result.add(new BFH16DeviceCoordinator()); result.add(new MijiaLywsd02Coordinator()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java index 13b8867c5..68bd29427 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java @@ -17,9 +17,14 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.util; +import android.text.format.DateFormat; + import java.text.ParseException; import java.util.Date; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; + public class GBPrefs { public static final String PACKAGE_BLACKLIST = "package_blacklist"; public static final String PACKAGE_PEBBLEMSG_BLACKLIST = "package_pebblemsg_blacklist"; @@ -81,4 +86,17 @@ public class GBPrefs { public int getUserGender() { return 0; } + + public String getTimeFormat() { + String timeFormat = mPrefs.getString(DeviceSettingsPreferenceConst.PREF_TIMEFORMAT, "auto"); + if ("auto".equals(timeFormat)) { + if (DateFormat.is24HourFormat(GBApplication.getContext())) { + timeFormat = "24h"; + } else { + timeFormat = "am/pm"; + } + } + + return timeFormat; + } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 386325036..6f3ffb9de 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -365,11 +365,13 @@ + @string/automatic @string/timeformat_24h @string/timeformat_am_pm + @string/p_timeformat_auto @string/p_timeformat_24h @string/p_timeformat_am_pm diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b8530ecf8..be131d35a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -684,6 +684,7 @@ Watch 9 Roidmi Roidmi 3 + Y5 Casio GB-6900 Mi Scale 2 BFH-16 diff --git a/app/src/main/res/values/values.xml b/app/src/main/res/values/values.xml index a9170a503..6c8f51113 100644 --- a/app/src/main/res/values/values.xml +++ b/app/src/main/res/values/values.xml @@ -43,6 +43,7 @@ metric imperial + auto 24h am/pm diff --git a/app/src/main/res/xml/devicesettings_timeformat.xml b/app/src/main/res/xml/devicesettings_timeformat.xml index 837fb5891..b733bf040 100644 --- a/app/src/main/res/xml/devicesettings_timeformat.xml +++ b/app/src/main/res/xml/devicesettings_timeformat.xml @@ -1,7 +1,7 @@ $DIR"10-MainScreen.png" + +adb shell input tap 455 355 +sleep 0.5 +adb shell screencap -p > $DIR"20-ActivityAndSleep.png" + +adb shell input tap 240 210 +read -p "slightly adjust label on chart and press Enter" +adb shell screencap -p > $DIR"30-Sleep.png" + +adb shell input tap 420 210 +read -p "slightly adjust label on chart and press Enter" +adb shell screencap -p > $DIR"40-SleepPerWeek.png" + +#switch to month +adb shell input tap 670 100 +sleep 0.5 +adb shell input tap 670 1080 +sleep 0.5 +adb shell input keyevent 111 +read -p "slightly adjust label on chart and press Enter" + +adb shell screencap -p > $DIR"41-SleepPerMonth.png" + + +adb shell input tap 590 210 +sleep 0.5 +adb shell screencap -p > $DIR"51-StepsPerMonth.png" + +#switch back to week +adb shell input tap 670 100 +sleep 0.5 +adb shell input tap 670 1080 +sleep 0.5 +adb shell input keyevent 111 +sleep 1 + +adb shell screencap -p > $DIR"50-StepsPerWeek.png" + +adb shell input tap 590 210 +sleep 0.5 +adb shell screencap -p > $DIR"60-SpeedZones.png" + +#Go back to main screen +adb shell input keyevent 111 + +#disable demo mode +adb shell am broadcast -a com.android.systemui.demo -e command exit +adb shell settings put global sysui_demo_allowed 0 diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1-MainScreen.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1-MainScreen.png deleted file mode 100644 index 4bfd41fb8..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/1-MainScreen.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/10-MainScreen.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/10-MainScreen.png new file mode 100644 index 000000000..c39df0307 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/10-MainScreen.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2-ActivityAndSleep.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2-ActivityAndSleep.png deleted file mode 100644 index 4b30f2e57..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/2-ActivityAndSleep.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/20-ActivityAndSleep.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/20-ActivityAndSleep.png new file mode 100644 index 000000000..e0d7ba73e Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/20-ActivityAndSleep.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/3-SleepPerWeek.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/3-SleepPerWeek.png deleted file mode 100644 index e11cc01d0..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/3-SleepPerWeek.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/30-Sleep.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/30-Sleep.png new file mode 100644 index 000000000..4edb72898 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/30-Sleep.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/4-StepsPerWeek.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/4-StepsPerWeek.png deleted file mode 100644 index 452a931a1..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/4-StepsPerWeek.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/40-SleepPerWeek.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/40-SleepPerWeek.png new file mode 100644 index 000000000..5007712ff Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/40-SleepPerWeek.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/41-SleepPerMonth.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/41-SleepPerMonth.png new file mode 100644 index 000000000..78ab88bde Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/41-SleepPerMonth.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/5-SpeedZones.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/5-SpeedZones.png deleted file mode 100644 index 8a4e30673..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/5-SpeedZones.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/50-StepsPerWeek.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/50-StepsPerWeek.png new file mode 100644 index 000000000..8a7670c2c Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/50-StepsPerWeek.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/51-StepsPerMonth.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/51-StepsPerMonth.png new file mode 100644 index 000000000..1a3a74af8 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/51-StepsPerMonth.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/6-LiveActivity.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/6-LiveActivity.png deleted file mode 100644 index bfcc71aa2..000000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/6-LiveActivity.png and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/60-SpeedZones.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/60-SpeedZones.png new file mode 100644 index 000000000..9a9689ba4 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/60-SpeedZones.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/70-LiveActivity.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/70-LiveActivity.png new file mode 100644 index 000000000..1eaedecbf Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/70-LiveActivity.png differ