Moyoung: Make fixed MTU device-specific

This commit is contained in:
Arjan Schrijver 2024-08-25 22:01:23 +02:00
parent a46c4fa8de
commit e444ed67b9
7 changed files with 41 additions and 26 deletions

View File

@ -208,4 +208,8 @@ public abstract class AbstractMoyoungDeviceCoordinator extends AbstractDeviceCoo
public MoyoungSetting[] getSupportedSettings() { public MoyoungSetting[] getSupportedSettings() {
return MOYOUNG_SETTINGS; return MOYOUNG_SETTINGS;
} }
public int getMtu() {
return 20;
}
} }

View File

@ -55,4 +55,9 @@ public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
public String getManufacturer() { public String getManufacturer() {
return "Colmi"; return "Colmi";
} }
@Override
public int getMtu() {
return 508;
}
} }

View File

@ -57,13 +57,13 @@ public class FetchDataOperation extends AbstractBTLEOperation<MoyoungDeviceSuppo
@Override @Override
protected void doPerform() throws IOException { protected void doPerform() throws IOException {
TransactionBuilder builder = performInitialized("FetchDataOperation"); TransactionBuilder builder = performInitialized("FetchDataOperation");
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_SLEEP }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_SLEEP }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_SLEEP, new byte[0])); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_SLEEP, new byte[0]));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_YESTERDAY_STEPS }));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_STEPS })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_SYNC_PAST_SLEEP_AND_STEP, new byte[] { MoyoungConstants.ARG_SYNC_DAY_BEFORE_YESTERDAY_STEPS }));
builder.read(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_STEPS)); builder.read(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_STEPS));
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { }));
builder.queue(getQueue()); builder.queue(getQueue());
updateProgressAndCheckFinish(); updateProgressAndCheckFinish();

View File

@ -130,11 +130,15 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private Handler idleUpdateHandler = new Handler(); private Handler idleUpdateHandler = new Handler();
public static final int MTU = 20; // TODO: there seems to be some way to change this value...? private int mtu = 20;
private MoyoungPacketIn packetIn = new MoyoungPacketIn(); private MoyoungPacketIn packetIn = new MoyoungPacketIn();
private boolean realTimeHeartRate; private boolean realTimeHeartRate;
public int getMtu() {
return this.mtu;
}
public MoyoungDeviceSupport() { public MoyoungDeviceSupport() {
super(LOG); super(LOG);
batteryCmd.level = ActivitySample.NOT_MEASURED; batteryCmd.level = ActivitySample.NOT_MEASURED;
@ -159,6 +163,8 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
@Override @Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) { protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
mtu = ((AbstractMoyoungDeviceCoordinator) getDevice().getDeviceCoordinator()).getMtu();
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext())); builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
builder.notify(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN), true); builder.notify(getCharacteristic(MoyoungConstants.UUID_CHARACTERISTIC_DATA_IN), true);
deviceInfoProfile.requestDeviceInfo(builder); deviceInfoProfile.requestDeviceInfo(builder);
@ -172,7 +178,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext())); 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... // TODO: I would prefer this to be done when the alarms screen is open, not on initialization...
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_QUERY_ALARM_CLOCK, new byte[0])); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_QUERY_ALARM_CLOCK, new byte[0]));
return builder; return builder;
} }
@ -197,7 +203,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
{ {
MoyoungPacketOut packetOut = new MoyoungPacketOut(packet); MoyoungPacketOut packetOut = new MoyoungPacketOut(packet);
byte[] fragment = new byte[MTU]; byte[] fragment = new byte[Math.min(packet.length, mtu)];
while(packetOut.getFragment(fragment)) while(packetOut.getFragment(fragment))
{ {
builder.write(getTargetCharacteristicForPacketType(packet[4]), fragment.clone()); builder.write(getTargetCharacteristicForPacketType(packet[4]), fragment.clone());
@ -485,7 +491,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
byte[] payload = new byte[str.length + 1]; byte[] payload = new byte[str.length + 1];
payload[0] = type; payload[0] = type;
System.arraycopy(str, 0, payload, 1, str.length); System.arraycopy(str, 0, payload, 1, str.length);
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SEND_MESSAGE, payload)); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SEND_MESSAGE, payload));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error sending notification: ", e); LOG.error("Error sending notification: ", e);
@ -518,7 +524,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
ByteBuffer buffer = ByteBuffer.allocate(5); ByteBuffer buffer = ByteBuffer.allocate(5);
buffer.putInt(MoyoungConstants.LocalTimeToWatchTime(new Date())); // The watch is hardcoded to GMT+8 internally... buffer.putInt(MoyoungConstants.LocalTimeToWatchTime(new Date())); // The watch is hardcoded to GMT+8 internally...
buffer.put((byte)8); // I guess this means GMT+8 but changing it has no effect at all (it was hardcoded in the original app too) buffer.put((byte)8); // I guess this means GMT+8 but changing it has no effect at all (it was hardcoded in the original app too)
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SYNC_TIME, buffer.array())); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SYNC_TIME, buffer.array()));
} }
@Override @Override
@ -615,7 +621,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
else else
repeat = 2; repeat = 2;
buffer.put(repeat); buffer.put(repeat);
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SET_ALARM_CLOCK, buffer.array())); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SET_ALARM_CLOCK, buffer.array()));
} }
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
@ -1034,7 +1040,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
try { try {
TransactionBuilder builder = performInitialized("shutdown"); TransactionBuilder builder = performInitialized("shutdown");
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SHUTDOWN, new byte[] { -1 })); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SHUTDOWN, new byte[] { -1 }));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error sending reset command: ", e); LOG.error("Error sending reset command: ", e);
@ -1045,7 +1051,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
{ {
try { try {
TransactionBuilder builder = performInitialized("onHeartRateTest"); TransactionBuilder builder = performInitialized("onHeartRateTest");
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE, new byte[] { start ? (byte)0 : (byte)-1 })); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_TRIGGER_MEASURE_HEARTRATE, new byte[] { start ? (byte)0 : (byte)-1 }));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error sending heart rate test command: ", e); LOG.error("Error sending heart rate test command: ", e);
@ -1085,7 +1091,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
{ {
try { try {
TransactionBuilder builder = performInitialized("onFindDevice"); TransactionBuilder builder = performInitialized("onFindDevice");
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_FIND_MY_WATCH, new byte[0])); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_FIND_MY_WATCH, new byte[0]));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error while finding device: ", e); LOG.error("Error while finding device: ", e);
@ -1123,7 +1129,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
private <T> void sendSetting(TransactionBuilder builder, MoyoungSetting<T> setting, T newValue) private <T> void sendSetting(TransactionBuilder builder, MoyoungSetting<T> setting, T newValue)
{ {
sendPacket(builder, MoyoungPacketOut.buildPacket(setting.cmdSet, setting.encode(newValue))); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, setting.cmdSet, setting.encode(newValue)));
} }
private <T> void sendSetting(MoyoungSetting<T> setting, T newValue) private <T> void sendSetting(MoyoungSetting<T> setting, T newValue)
@ -1146,7 +1152,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
try { try {
TransactionBuilder builder = performInitialized("querySetting"); TransactionBuilder builder = performInitialized("querySetting");
sendPacket(builder, MoyoungPacketOut.buildPacket(setting.cmdQuery, new byte[0])); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, setting.cmdQuery, new byte[0]));
builder.queue(getQueue()); builder.queue(getQueue());
queriedSettings.add(setting); queriedSettings.add(setting);
} catch (IOException e) { } catch (IOException e) {
@ -1485,10 +1491,10 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
packetWeatherToday.putShort(weatherToday.pm25); packetWeatherToday.putShort(weatherToday.pm25);
packetWeatherToday.put(weatherToday.lunar_or_festival.getBytes("unicodebigunmarked")); packetWeatherToday.put(weatherToday.lunar_or_festival.getBytes("unicodebigunmarked"));
packetWeatherToday.put(weatherToday.city.getBytes("unicodebigunmarked")); packetWeatherToday.put(weatherToday.city.getBytes("unicodebigunmarked"));
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SET_WEATHER_TODAY, packetWeatherToday.array())); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SET_WEATHER_TODAY, packetWeatherToday.array()));
ByteBuffer packetWeatherForecast = ByteBuffer.allocate(6 * 3); ByteBuffer packetWeatherForecast = ByteBuffer.allocate(7 * 3);
for(int i = 0; i < 6; i++) for(int i = 0; i < 7; i++)
{ {
MoyoungWeatherForecast forecast; MoyoungWeatherForecast forecast;
if (weatherSpec.forecasts.size() > i) if (weatherSpec.forecasts.size() > i)
@ -1499,7 +1505,7 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
packetWeatherForecast.put(forecast.minTemp); packetWeatherForecast.put(forecast.minTemp);
packetWeatherForecast.put(forecast.maxTemp); packetWeatherForecast.put(forecast.maxTemp);
} }
sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_SET_WEATHER_FUTURE, packetWeatherForecast.array())); sendPacket(builder, MoyoungPacketOut.buildPacket(mtu, MoyoungConstants.CMD_SET_WEATHER_FUTURE, packetWeatherForecast.array()));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {

View File

@ -59,12 +59,12 @@ public class MoyoungPacketOut extends MoyoungPacket {
* @param payload The packet payload * @param payload The packet payload
* @return The encoded packet * @return The encoded packet
*/ */
public static byte[] buildPacket(byte packetType, @NonNull byte[] payload) public static byte[] buildPacket(int mtu, byte packetType, @NonNull byte[] payload)
{ {
byte[] packet = new byte[payload.length + 5]; byte[] packet = new byte[payload.length + 5];
packet[0] = (byte)0xFE; packet[0] = (byte)0xFE;
packet[1] = (byte)0xEA; packet[1] = (byte)0xEA;
if (MoyoungDeviceSupport.MTU == 20) if (mtu == 20)
{ {
packet[2] = 16; packet[2] = 16;
packet[3] = (byte)(packet.length & 0xFF); packet[3] = (byte)(packet.length & 0xFF);

View File

@ -68,7 +68,7 @@ public class QuerySettingsOperation extends AbstractBTLEOperation<MoyoungDeviceS
if (setting.cmdQuery == -1) if (setting.cmdQuery == -1)
continue; continue;
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(setting.cmdQuery, new byte[0])); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), setting.cmdQuery, new byte[0]));
} }
builder.queue(getQueue()); builder.queue(getQueue());
} }

View File

@ -136,7 +136,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
private void queryMoreData() { private void queryMoreData() {
try { try {
TransactionBuilder builder = performInitialized("TrainingFinishedDataOperation"); TransactionBuilder builder = performInitialized("TrainingFinishedDataOperation");
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_QUERY_LAST_DYNAMIC_RATE, new byte[0])); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_LAST_DYNAMIC_RATE, new byte[0]));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error fetching training data: ", e); LOG.error("Error fetching training data: ", e);
@ -192,7 +192,7 @@ public class TrainingFinishedDataOperation extends AbstractBTLEOperation<Moyoung
try { try {
TransactionBuilder builder = performInitialized("TrainingFinishedDataOperation fetch training type"); TransactionBuilder builder = performInitialized("TrainingFinishedDataOperation fetch training type");
getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { })); getSupport().sendPacket(builder, MoyoungPacketOut.buildPacket(getSupport().getMtu(), MoyoungConstants.CMD_QUERY_MOVEMENT_HEART_RATE, new byte[] { }));
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException e) { } catch (IOException e) {
LOG.error("Error fetching training data: ", e); LOG.error("Error fetching training data: ", e);