Fix + cleanup time setting and calendar sending #441

This commit is contained in:
cpfeiffer 2016-12-01 22:49:58 +01:00
parent dbe90d7ae3
commit da297ecd8b
3 changed files with 38 additions and 65 deletions

View File

@ -18,10 +18,10 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
@ -182,8 +182,15 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
return builder; return builder;
} }
public byte[] getTimeBytes(Calendar calendar) { public byte[] getTimeBytes(Calendar calendar, TimeUnit precision) {
byte[] bytes = BLETypeConversions.shortCalendarToRawBytes(calendar, true); byte[] bytes;
if (precision == TimeUnit.MINUTES) {
bytes = BLETypeConversions.shortCalendarToRawBytes(calendar, true);
} else if (precision == TimeUnit.SECONDS) {
bytes = BLETypeConversions.calendarToRawBytes(calendar, true);
} else {
throw new IllegalArgumentException("Unsupported precision, only MINUTES and SECONDS are supported till now");
}
byte[] tail = new byte[] { 0, BLETypeConversions.mapTimeZone(calendar.getTimeZone()) }; // 0 = adjust reason bitflags? or DST offset?? , timezone byte[] tail = new byte[] { 0, BLETypeConversions.mapTimeZone(calendar.getTimeZone()) }; // 0 = adjust reason bitflags? or DST offset?? , timezone
// byte[] tail = new byte[] { 0x2 }; // reason // byte[] tail = new byte[] { 0x2 }; // reason
byte[] all = BLETypeConversions.join(bytes, tail); byte[] all = BLETypeConversions.join(bytes, tail);
@ -197,8 +204,9 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
public MiBand2Support setCurrentTimeWithService(TransactionBuilder builder) { public MiBand2Support setCurrentTimeWithService(TransactionBuilder builder) {
GregorianCalendar now = BLETypeConversions.createCalendar(); GregorianCalendar now = BLETypeConversions.createCalendar();
byte[] bytes = getTimeBytes(now); byte[] bytes = getTimeBytes(now, TimeUnit.SECONDS);
builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME), bytes); builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME), bytes);
// byte[] localtime = BLETypeConversions.calendarToLocalTimeBytes(now); // byte[] localtime = BLETypeConversions.calendarToLocalTimeBytes(now);
// builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_LOCAL_TIME_INFORMATION), localtime); // builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_LOCAL_TIME_INFORMATION), localtime);
// builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME), new byte[] {0x2, 0x00}); // builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_CURRENT_TIME), new byte[] {0x2, 0x00});
@ -577,46 +585,13 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
public void onSetTime() { public void onSetTime() {
try { try {
TransactionBuilder builder = performInitialized("Set date and time"); TransactionBuilder builder = performInitialized("Set date and time");
setCurrentTime(builder); setCurrentTimeWithService(builder);
//TODO: once we have a common strategy for sending events (e.g. EventHandler), remove this call from here. Meanwhile it does no harm.
sendCalendarEvents(builder);
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException ex) { } catch (IOException ex) {
LOG.error("Unable to set time on MI device", ex); LOG.error("Unable to set time on MI device", ex);
} }
//TODO: once we have a common strategy for sending events (e.g. EventHandler), remove this call from here. Meanwhile it does no harm.
sendCalendarEvents();
}
/**
* Sets the current time to the Mi device using the given builder.
*
* @param builder
*/
private MiBand2Support setCurrentTime(TransactionBuilder builder) {
Calendar now = GregorianCalendar.getInstance();
Date date = now.getTime();
LOG.info("Sending current time to Mi Band: " + DateTimeUtils.formatDate(date) + " (" + date.toGMTString() + ")");
byte[] nowBytes = MiBandDateConverter.calendarToRawBytes(now);
byte[] time = new byte[]{
nowBytes[0],
nowBytes[1],
nowBytes[2],
nowBytes[3],
nowBytes[4],
nowBytes[5],
(byte) 0x0f,
(byte) 0x0f,
(byte) 0x0f,
(byte) 0x0f,
(byte) 0x0f,
(byte) 0x0f
};
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_DATE_TIME);
if (characteristic != null) {
builder.write(characteristic, time);
} else {
LOG.info("Unable to set time -- characteristic not available");
}
return this;
} }
@Override @Override
@ -1209,36 +1184,33 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
/** /**
* Fetch the events from the android device calendars and set the alarms on the miband. * Fetch the events from the android device calendars and set the alarms on the miband.
* @param builder
*/ */
private void sendCalendarEvents() { private MiBand2Support sendCalendarEvents(TransactionBuilder builder) {
try { BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3);
TransactionBuilder builder = performInitialized("Send upcoming events");
BluetoothGattCharacteristic characteristic = getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3);
Prefs prefs = GBApplication.getPrefs(); Prefs prefs = GBApplication.getPrefs();
int availableSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0); int availableSlots = prefs.getInt(MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR, 0);
if (availableSlots > 0) { if (availableSlots > 0) {
CalendarEvents upcomingEvents = new CalendarEvents(); CalendarEvents upcomingEvents = new CalendarEvents();
List<CalendarEvents.CalendarEvent> mEvents = upcomingEvents.getCalendarEventList(getContext()); List<CalendarEvents.CalendarEvent> mEvents = upcomingEvents.getCalendarEventList(getContext());
int iteration = 0; int iteration = 0;
for (CalendarEvents.CalendarEvent mEvt : mEvents) { for (CalendarEvents.CalendarEvent mEvt : mEvents) {
if (iteration >= availableSlots || iteration > 2) { if (iteration >= availableSlots || iteration > 2) {
break; break;
}
int slotToUse = 2 - iteration;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(mEvt.getBegin());
Alarm alarm = GBAlarm.createSingleShot(slotToUse, false, calendar);
queueAlarm(alarm, builder, characteristic);
iteration++;
} }
builder.queue(getQueue()); int slotToUse = 2 - iteration;
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(mEvt.getBegin());
Alarm alarm = GBAlarm.createSingleShot(slotToUse, false, calendar);
queueAlarm(alarm, builder, characteristic);
iteration++;
} }
} catch (IOException ex) { builder.queue(getQueue());
LOG.error("Unable to send Events to MI device", ex);
} }
return this;
} }
@Override @Override

View File

@ -15,6 +15,7 @@ import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.Logging;
@ -73,7 +74,7 @@ public class FetchActivityOperation extends AbstractMiBand2Operation {
BluetoothGattCharacteristic characteristicActivityData = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_ACTIVITY_DATA); BluetoothGattCharacteristic characteristicActivityData = getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_ACTIVITY_DATA);
GregorianCalendar sinceWhen = getLastSuccessfulSynchronizedTime(); GregorianCalendar sinceWhen = getLastSuccessfulSynchronizedTime();
builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE, 0x01 }, getSupport().getTimeBytes(sinceWhen))); builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE, 0x01 }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
builder.notify(characteristicActivityData, true); builder.notify(characteristicActivityData, true);
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_ACTIVITY_DATA }); builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_ACTIVITY_DATA });

View File

@ -98,7 +98,7 @@ public class InitOperation extends AbstractBTLEOperation<MiBand2Support> {
} else if (value[0] == MiBand2Service.AUTH_RESPONSE && } else if (value[0] == MiBand2Service.AUTH_RESPONSE &&
value[1] == MiBand2Service.AUTH_SEND_ENCRYPTED_AUTH_NUMBER && value[1] == MiBand2Service.AUTH_SEND_ENCRYPTED_AUTH_NUMBER &&
value[2] == MiBand2Service.AUTH_SUCCESS) { value[2] == MiBand2Service.AUTH_SUCCESS) {
TransactionBuilder builder = createTransactionBuilder("Sending the encrypted random key to the band"); TransactionBuilder builder = createTransactionBuilder("Authenticated, now initialize phase 2");
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
getSupport().requestDeviceInfo(builder); getSupport().requestDeviceInfo(builder);
getSupport().phase2Initialize(builder); getSupport().phase2Initialize(builder);