mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-02-10 15:57:00 +01:00
Moyoung: Support sending, receiving and deleting alarms
This commit is contained in:
parent
3994da1e3f
commit
3b8d5fc874
@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
|
||||||
public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
|
public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ColmiI28UltraCoordinator.class);
|
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;
|
return R.string.devicetype_colmi_i28_ultra;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DrawableRes
|
@DrawableRes
|
||||||
public int getDefaultIconResource() {
|
public int getDefaultIconResource() {
|
||||||
@ -60,4 +60,9 @@ public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
|
|||||||
public int getMtu() {
|
public int getMtu() {
|
||||||
return 508;
|
return 508;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAlarmSlotCount(GBDevice device) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
}
|
}
|
@ -213,8 +213,14 @@ public class MoyoungConstants {
|
|||||||
public static final byte CMD_ADVANCED_QUERY = (byte) 0xb9;
|
public static final byte CMD_ADVANCED_QUERY = (byte) 0xb9;
|
||||||
public static final byte CMD_DAGPT = (byte) 0xbb;
|
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_SET_CALENDAR = 0x08;
|
||||||
public static final byte ARG_ADVANCED_QUERY_STOCKS = 0x0e;
|
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_ADD_ITEM = 0x00;
|
||||||
public static final byte ARG_CALENDAR_DISABLE = 0x04;
|
public static final byte ARG_CALENDAR_DISABLE = 0x04;
|
||||||
|
@ -81,6 +81,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSett
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingTimeRange;
|
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungSettingTimeRange;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungBloodPressureSample;
|
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);
|
handleGetAlarmsResponse(payload);
|
||||||
return true;
|
return true;
|
||||||
@ -621,21 +622,68 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
|||||||
|
|
||||||
private void handleGetAlarmsResponse(byte[] payload)
|
private void handleGetAlarmsResponse(byte[] payload)
|
||||||
{
|
{
|
||||||
if (payload.length % 8 != 0)
|
boolean payloadV2 = false;
|
||||||
throw new IllegalArgumentException();
|
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<nodomain.freeyourgadget.gadgetbridge.entities.Alarm> alarms = DBHelper.getAlarms(gbDevice);
|
ByteBuffer buffer = ByteBuffer.wrap(payload);
|
||||||
int i = 0;
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
for (nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm : alarms) {
|
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(payload, 8 * i, 8);
|
int alarmsInPacket;
|
||||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
if (payloadV2) {
|
||||||
if (buffer.get() != i)
|
byte packetSubtype = buffer.get();
|
||||||
throw new IllegalArgumentException();
|
if (packetSubtype != MoyoungConstants.ARG_ADVANCED_QUERY_ALARMS) {
|
||||||
if (alarm.getPosition() != i)
|
LOG.error("Invalid packet subtype {}", packetSubtype);
|
||||||
throw new IllegalArgumentException();
|
return;
|
||||||
alarm.setEnabled(buffer.get() != 0);
|
}
|
||||||
byte repetition = buffer.get();
|
byte packetArgument = buffer.get();
|
||||||
alarm.setRepetition(AlarmUtils.createRepetitionMask(
|
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<alarmsInPacket; i++) {
|
||||||
|
byte[] alarm = new byte[8];
|
||||||
|
buffer.get(alarm);
|
||||||
|
saveAlarmFromPayload(alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator();
|
||||||
|
for (int i=alarmsInPacket; i<=coordinator.getAlarmSlotCount(getDevice()); i++) {
|
||||||
|
nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm();
|
||||||
|
alarm.setUnused(true);
|
||||||
|
AlarmUtils.mergeOneshotToDeviceAlarms(getDevice(), alarm, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Intent intent = new Intent(DeviceService.ACTION_SAVE_ALARMS);
|
||||||
|
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAlarmFromPayload(byte[] payload) {
|
||||||
|
if (payload.length != 8) {
|
||||||
|
LOG.error("Invalid alarm format");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(payload);
|
||||||
|
nodomain.freeyourgadget.gadgetbridge.entities.Alarm alarm = new nodomain.freeyourgadget.gadgetbridge.entities.Alarm();
|
||||||
|
int alarmNr = buffer.get();
|
||||||
|
alarm.setEnabled(buffer.get() != 0);
|
||||||
|
byte repetitionEnabled = buffer.get(); // not sure why they store the same info in two places
|
||||||
|
alarm.setHour(buffer.get());
|
||||||
|
alarm.setMinute(buffer.get());
|
||||||
|
byte singleShotYearAndMonth = buffer.get();
|
||||||
|
byte singleShotDay = buffer.get();
|
||||||
|
byte repetition = buffer.get();
|
||||||
|
alarm.setRepetition(AlarmUtils.createRepetitionMask(
|
||||||
(repetition & 2) != 0,
|
(repetition & 2) != 0,
|
||||||
(repetition & 4) != 0,
|
(repetition & 4) != 0,
|
||||||
(repetition & 8) != 0,
|
(repetition & 8) != 0,
|
||||||
@ -643,22 +691,22 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
|||||||
(repetition & 32) != 0,
|
(repetition & 32) != 0,
|
||||||
(repetition & 64) != 0,
|
(repetition & 64) != 0,
|
||||||
(repetition & 1) != 0));
|
(repetition & 1) != 0));
|
||||||
alarm.setHour(buffer.get());
|
AlarmUtils.mergeOneshotToDeviceAlarms(getDevice(), alarm, alarmNr);
|
||||||
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
|
@Override
|
||||||
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
public void onSetAlarms(ArrayList<? extends Alarm> alarms) {
|
||||||
|
LOG.info("Setting {} alarms on device", alarms.size());
|
||||||
|
AbstractMoyoungDeviceCoordinator coordinator = (AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator();
|
||||||
try {
|
try {
|
||||||
TransactionBuilder builder = performInitialized("onSetAlarms");
|
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);
|
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);
|
ByteBuffer buffer = ByteBuffer.allocate(8);
|
||||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
@ -679,7 +727,14 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
|||||||
repetition |= 32;
|
repetition |= 32;
|
||||||
if (alarm.getRepetition(Alarm.ALARM_SAT))
|
if (alarm.getRepetition(Alarm.ALARM_SAT))
|
||||||
repetition |= 64;
|
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.getHour());
|
||||||
buffer.put((byte)alarm.getMinute());
|
buffer.put((byte)alarm.getMinute());
|
||||||
if (repetition == 0)
|
if (repetition == 0)
|
||||||
@ -694,15 +749,16 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
|||||||
buffer.put((byte)0);
|
buffer.put((byte)0);
|
||||||
buffer.put((byte)0);
|
buffer.put((byte)0);
|
||||||
}
|
}
|
||||||
byte repeat;
|
buffer.put(repetition);
|
||||||
if (repetition == 0)
|
// Older packet type
|
||||||
repeat = 0;
|
|
||||||
else if (repetition == 127)
|
|
||||||
repeat = 1;
|
|
||||||
else
|
|
||||||
repeat = 2;
|
|
||||||
buffer.put(repeat);
|
|
||||||
sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SET_ALARM_CLOCK, buffer.array()));
|
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());
|
builder.queue(getQueue());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user