diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java index cdcf80b52..392dd3fa9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java @@ -193,7 +193,7 @@ public class DaFitConstants { public static final byte ARG_OPERATION_DROP_INCOMING_CALL = 3; public static final byte CMD_QUERY_ALARM_CLOCK = 33; // (?) {} -> a list of entries like below - public static final byte CMD_SET_ALARM_CLOCK = 17; // (?) {id, enable ? 1 : 0, repeat, hour, minute, i >> 8, i, repeatMode}, repeatMode is 0(SINGLE), 127(EVERYDAY), or bitmask of 1,2,4,8,16,32,64(SUNDAY-SATURDAY) is 0,1,2, i is ((year << 12) + (month << 8) + day) for repeatMode=SINGLE and 0 otherwise, repeat is 0(SINGLE),1(EVERYDAY),2(OTHER) + public static final byte CMD_SET_ALARM_CLOCK = 17; // (?) {id, enable ? 1 : 0, repeat, hour, minute, i >> 8, i, repeatMode}, repeatMode is 0(SINGLE), 127(EVERYDAY), or bitmask of 1,2,4,8,16,32,64(SUNDAY-SATURDAY) is 0,1,2, i is ((year << 12) + (month << 8) + day) where year is 2015-based, month and day start at 1 for repeatMode=SINGLE and 0 otherwise, repeat is 0(SINGLE),1(EVERYDAY),2(OTHER) // Settings public static final byte CMD_SET_USER_INFO = 18; // (?) {height, weight, age, gender}, MALE = 0, FEMALE = 1 diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java index f946aeb9a..825c069a7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -104,6 +105,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.Batter import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate.HeartRateProfile; +import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils; import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -177,6 +179,9 @@ public class DaFitDeviceSupport extends AbstractBTLEDeviceSupport { builder.notify(getCharacteristic(DaFitConstants.UUID_CHARACTERISTIC_STEPS), true); builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); + // TODO: I would prefer this to be done when the alarms screen is open, not on initialization... + sendPacket(builder, DaFitPacketOut.buildPacket(DaFitConstants.CMD_QUERY_ALARM_CLOCK, new byte[0])); + return builder; } @@ -392,6 +397,12 @@ public class DaFitDeviceSupport extends AbstractBTLEDeviceSupport { } } + if (packetType == DaFitConstants.CMD_QUERY_ALARM_CLOCK) + { + handleGetAlarmsResponse(payload); + return true; + } + LOG.warn("Unhandled packet " + packetType + ": " + Logging.formatBytes(payload)); return false; } @@ -529,9 +540,95 @@ public class DaFitDeviceSupport extends AbstractBTLEDeviceSupport { } } + private void handleGetAlarmsResponse(byte[] payload) + { + if (payload.length % 8 != 0) + throw new IllegalArgumentException(); + + List alarms = DBHelper.getAlarms(gbDevice); + int i = 0; + for (nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm : alarms) { + ByteBuffer buffer = ByteBuffer.wrap(payload, 8 * i, 8); + buffer.order(ByteOrder.LITTLE_ENDIAN); + if (buffer.get() != i) + throw new IllegalArgumentException(); + if (alarm.getPosition() != i) + throw new IllegalArgumentException(); + alarm.setEnabled(buffer.get() != 0); + byte repetition = buffer.get(); + alarm.setRepetition(AlarmUtils.createRepetitionMask( + (repetition & 2) != 0, + (repetition & 4) != 0, + (repetition & 8) != 0, + (repetition & 16) != 0, + (repetition & 32) != 0, + (repetition & 64) != 0, + (repetition & 1) != 0)); + alarm.setHour(buffer.get()); + alarm.setMinute(buffer.get()); + byte singleShotYearAndMonth = buffer.get(); + byte singleShotDay = buffer.get(); + byte repetitionEnabled = buffer.get(); // not sure why they store the same info in two places + DBHelper.store(alarm); + i++; + } + } + @Override public void onSetAlarms(ArrayList alarms) { - // TODO: set alarms + try { + TransactionBuilder builder = performInitialized("onSetAlarms"); + for(int i = 0; i < 3; i++) { + Alarm alarm = alarms.get(i); + + ByteBuffer buffer = ByteBuffer.allocate(8); + buffer.order(ByteOrder.LITTLE_ENDIAN); + buffer.put((byte)i); + buffer.put(alarm.getEnabled() ? (byte)1 : (byte)0); + byte repetition = 0; + if (alarm.getRepetition(Alarm.ALARM_SUN)) + repetition |= 1; + if (alarm.getRepetition(Alarm.ALARM_MON)) + repetition |= 2; + if (alarm.getRepetition(Alarm.ALARM_TUE)) + repetition |= 4; + if (alarm.getRepetition(Alarm.ALARM_WED)) + repetition |= 8; + if (alarm.getRepetition(Alarm.ALARM_THU)) + repetition |= 16; + if (alarm.getRepetition(Alarm.ALARM_FRI)) + repetition |= 32; + if (alarm.getRepetition(Alarm.ALARM_SAT)) + repetition |= 64; + buffer.put(repetition); + buffer.put((byte)alarm.getHour()); + buffer.put((byte)alarm.getMinute()); + if (repetition == 0) + { + // TODO: it would be possible to set an "once" alarm on a set day, but Gadgetbridge does not seem to support that + Calendar calendar = AlarmUtils.toCalendar(alarm); + buffer.put((byte)(((calendar.get(Calendar.YEAR) - 2015) << 4) + calendar.get(Calendar.MONTH) + 1)); + buffer.put((byte)calendar.get(Calendar.DAY_OF_MONTH)); + } + else + { + buffer.put((byte)0); + buffer.put((byte)0); + } + byte repeat; + if (repetition == 0) + repeat = 0; + else if (repetition == 127) + repeat = 1; + else + repeat = 2; + buffer.put(repeat); + sendPacket(builder, DaFitPacketOut.buildPacket(DaFitConstants.CMD_SET_ALARM_CLOCK, buffer.array())); + } + builder.queue(getQueue()); + } catch (IOException e) { + e.printStackTrace(); + } } @Override