diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/ColmiI28UltraCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/ColmiI28UltraCoordinator.java index 3b9cb7778..bf2b0474e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/ColmiI28UltraCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/ColmiI28UltraCoordinator.java @@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory; import java.util.regex.Pattern; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator { private static final Logger LOG = LoggerFactory.getLogger(ColmiI28UltraCoordinator.class); @@ -38,7 +39,6 @@ public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator { return R.string.devicetype_colmi_i28_ultra; } - @Override @DrawableRes public int getDefaultIconResource() { @@ -60,4 +60,9 @@ public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator { public int getMtu() { return 508; } + + @Override + public int getAlarmSlotCount(GBDevice device) { + return 8; + } } \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java index 3f6139dd7..fbfe29e05 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/moyoung/MoyoungConstants.java @@ -213,8 +213,14 @@ public class MoyoungConstants { public static final byte CMD_ADVANCED_QUERY = (byte) 0xb9; public static final byte CMD_DAGPT = (byte) 0xbb; + public static final byte ARG_ADVANCED_SET_ALARM = 0x05; public static final byte ARG_ADVANCED_SET_CALENDAR = 0x08; public static final byte ARG_ADVANCED_QUERY_STOCKS = 0x0e; + public static final byte ARG_ADVANCED_QUERY_ALARMS = 0x15; + + public static final byte ARG_ALARM_SET = 0x00; + public static final byte ARG_ALARM_DELETE = 0x02; + public static final byte ARG_ALARM_FROM_WATCH = 0x04; public static final byte ARG_CALENDAR_ADD_ITEM = 0x00; public static final byte ARG_CALENDAR_DISABLE = 0x04; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/MoyoungDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/MoyoungDeviceSupport.java index a84857eb4..7af700581 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/MoyoungDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/moyoung/MoyoungDeviceSupport.java @@ -81,6 +81,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSett import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingTimeRange; import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary; import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungBloodPressureSample; @@ -445,7 +446,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { } } - if (packetType == MoyoungConstants.CMD_QUERY_ALARM_CLOCK) + if (packetType == MoyoungConstants.CMD_QUERY_ALARM_CLOCK || (packetType == MoyoungConstants.CMD_ADVANCED_QUERY && payload[0] == MoyoungConstants.ARG_ADVANCED_QUERY_ALARMS)) { handleGetAlarmsResponse(payload); return true; @@ -621,21 +622,68 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { private void handleGetAlarmsResponse(byte[] payload) { - if (payload.length % 8 != 0) - throw new IllegalArgumentException(); + boolean payloadV2 = false; + if (payload.length % 8 == 3) { + payloadV2 = true; + } else if (payload.length % 8 != 0) { + LOG.error("Received alarms packet with invalid size {}", payload.length); + return; + } - 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( + ByteBuffer buffer = ByteBuffer.wrap(payload); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + int alarmsInPacket; + if (payloadV2) { + byte packetSubtype = buffer.get(); + if (packetSubtype != MoyoungConstants.ARG_ADVANCED_QUERY_ALARMS) { + LOG.error("Invalid packet subtype {}", packetSubtype); + return; + } + byte packetArgument = buffer.get(); + if (packetArgument != MoyoungConstants.ARG_ALARM_FROM_WATCH) { + LOG.error("Invalid packet argument {}", packetArgument); + return; + } + alarmsInPacket = buffer.get(); + } else { + alarmsInPacket = payload.length / 8; + } + + for (int i=0; i alarms) { + LOG.info("Setting {} alarms on device", alarms.size()); + AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator(); try { TransactionBuilder builder = performInitialized("onSetAlarms"); - for(int i = 0; i < 3; i++) { + for(int i = 0; i < coordinator.getAlarmSlotCount(getDevice()); i++) { Alarm alarm = alarms.get(i); + if (alarm.getUnused()) { + byte[] packet = new byte[]{MoyoungConstants.ARG_ADVANCED_SET_ALARM, MoyoungConstants.ARG_ALARM_DELETE, (byte) i}; + sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_ADVANCED_QUERY, packet)); + continue; + } ByteBuffer buffer = ByteBuffer.allocate(8); buffer.order(ByteOrder.LITTLE_ENDIAN); @@ -679,7 +727,14 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { repetition |= 32; if (alarm.getRepetition(Alarm.ALARM_SAT)) repetition |= 64; - buffer.put(repetition); + byte repeat; + if (repetition == 0) + repeat = 0; + else if (repetition == 127) + repeat = 1; + else + repeat = 2; + buffer.put(repeat); buffer.put((byte)alarm.getHour()); buffer.put((byte)alarm.getMinute()); if (repetition == 0) @@ -694,15 +749,16 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport { 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); + buffer.put(repetition); + // Older packet type sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SET_ALARM_CLOCK, buffer.array())); + // Newer packet type + ByteBuffer bufferNewProtocol = ByteBuffer.allocate(10); + bufferNewProtocol.order(ByteOrder.LITTLE_ENDIAN); + bufferNewProtocol.put(MoyoungConstants.ARG_ADVANCED_SET_ALARM); + bufferNewProtocol.put(MoyoungConstants.ARG_ALARM_SET); + bufferNewProtocol.put(buffer.array(), 0, 8); + sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_ADVANCED_QUERY, bufferNewProtocol.array())); } builder.queue(getQueue()); } catch (IOException e) {