Moondrop: Split ST2 into its own device coordinator and device type

This commit is contained in:
Jan64X
2026-05-02 15:20:13 +02:00
parent ce85474e0a
commit f616c3159c
7 changed files with 130 additions and 31 deletions
@@ -0,0 +1,44 @@
/* Copyright (C) 2026 Jan Petrlík
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.moondrop;
import androidx.annotation.NonNull;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop.MoondropSpaceTravel2DeviceSupport;
public class MoondropSpaceTravel2Coordinator extends MoondropSpaceTravelCoordinator {
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("Space Travel 2");
}
@Override
public int getDeviceNameResource() {
return R.string.devicetype_moondrop_space_travel_2;
}
@NonNull
@Override
public Class<? extends DeviceSupport> getDeviceSupportClass(final GBDevice device) {
return MoondropSpaceTravel2DeviceSupport.class;
}
}
@@ -38,7 +38,7 @@ public class MoondropSpaceTravelCoordinator extends AbstractBLClassicDeviceCoord
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile("^(?:Moondrop )?Space Travel(?: 2)?$");
return Pattern.compile("Moondrop Space Travel");
}
@Override
@@ -332,6 +332,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.mijia_lywsd.MijiaMhoC303Coor
import nodomain.freeyourgadget.gadgetbridge.devices.mijia_lywsd.MijiaXmwsdj04Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miscale.MiCompositionScaleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miscale.MiSmartScaleCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moondrop.MoondropSpaceTravel2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moondrop.MoondropSpaceTravelCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.AdvanWatchSE1AICoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.BlackviewR60Coordinator;
@@ -803,6 +804,7 @@ public enum DeviceType {
SOUNDCORE_Q30(SoundcoreQ30Coordinator.class),
SOUNDCORE_AEROFIT2(SoundcoreAeroFit2Coordinator.class),
MOONDROP_SPACE_TRAVEL(MoondropSpaceTravelCoordinator.class),
MOONDROP_SPACE_TRAVEL_2(MoondropSpaceTravel2Coordinator.class),
BOSE_QC35(QC35Coordinator.class),
ONEMORE_SONOFLOW(OneMoreSonoFlowCoordinator.class),
HONORBAND3(HonorBand3Coordinator.class),
@@ -0,0 +1,24 @@
/* Copyright (C) 2026 Jan Petrlík
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop;
public class MoondropSpaceTravel2DeviceSupport extends MoondropSpaceTravelDeviceSupport {
@Override
protected MoondropSpaceTravelProtocol createDeviceProtocol() {
return new MoondropSpaceTravel2Protocol(getDevice());
}
}
@@ -0,0 +1,25 @@
/* Copyright (C) 2026 Jan Petrlík
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class MoondropSpaceTravel2Protocol extends MoondropSpaceTravelProtocol {
protected MoondropSpaceTravel2Protocol(GBDevice device) {
super(device);
}
}
@@ -63,21 +63,24 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
if (packet.getPduType() != GaiaPacket.PDU_RESPONSE)
continue;
short featureId = packet.getFeatureId();
short pduId = packet.getPduId();
byte[] payload = packet.getPayload();
if (featureId == EQUALIZER_PRESET_FEATURE && pduId == EQUALIZER_PRESET_PDU_GET)
events.add(handlePacketEqualizerPreset(payload));
else if (featureId == TOUCH_ACTIONS_FEATURE && pduId == TOUCH_ACTIONS_PDU_GET)
events.add(handlePacketTouchActions(payload));
else if (featureId == AUDIO_CURATION_FEATURE && pduId == AUDIO_CURATION_PDU_GET_MODE)
events.add(handlePacketAudioCurationMode(payload));
GBDeviceEvent event = decodePacket(packet.getFeatureId(), packet.getPduId(), packet.getPayload());
if (event != null)
events.add(event);
}
return events.toArray(new GBDeviceEvent[0]);
}
protected GBDeviceEvent decodePacket(short featureId, short pduId, byte[] payload) {
if (featureId == EQUALIZER_PRESET_FEATURE && pduId == EQUALIZER_PRESET_PDU_GET)
return handlePacketEqualizerPreset(payload);
else if (featureId == TOUCH_ACTIONS_FEATURE && pduId == TOUCH_ACTIONS_PDU_GET)
return handlePacketTouchActions(payload);
else if (featureId == AUDIO_CURATION_FEATURE && pduId == AUDIO_CURATION_PDU_GET_MODE)
return handlePacketAudioCurationMode(payload);
return null;
}
private GBDeviceEvent handlePacketEqualizerPreset(byte[] payload) {
if (payload.length != EQUALIZER_PRESET_PKT_LEN)
return null;
@@ -87,21 +90,6 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GBDeviceEventUpdatePreferences(PREF_MOONDROP_EQUALIZER_PRESET, String.valueOf(preset));
}
private GBDeviceEvent handlePacketAudioCurationMode(byte[] payload) {
if (payload.length < 1)
return null;
// GET_MODE returns a 0-based slot index, SET_MODE and the UI dropdown use a
// bitmask (Normal=1, ANC=2, Transparency=4). Convert before storing the
// preference.
int slot = payload[0] & 0xff;
if (slot > 2)
return null;
int mode = 1 << slot;
return new GBDeviceEventUpdatePreferences(PREF_MOONDROP_ANC_MODE, String.valueOf(mode));
}
private GBDeviceEvent handlePacketTouchActions(byte[] payload) {
if (payload.length != TOUCH_ACTIONS_PKT_LEN)
return null;
@@ -119,6 +107,21 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GBDeviceEventUpdatePreferences(prefs);
}
private GBDeviceEvent handlePacketAudioCurationMode(byte[] payload) {
if (payload.length < 1)
return null;
// GET_MODE returns a 0-based slot index, SET_MODE and the UI dropdown use a
// bitmask (Normal=1, ANC=2, Transparency=4). Convert before storing the
// preference.
int slot = payload[0] & 0xff;
if (slot > 2)
return null;
int mode = 1 << slot;
return new GBDeviceEventUpdatePreferences(PREF_MOONDROP_ANC_MODE, String.valueOf(mode));
}
@Override
public byte[] encodeSendConfiguration(String config) {
switch (config) {
@@ -150,14 +153,14 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GaiaPacket(EQUALIZER_PRESET_FEATURE, EQUALIZER_PRESET_PDU_GET).encode();
}
public byte[] encodeGetAudioCurationMode() {
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_GET_MODE).encode();
}
public byte[] encodeGetTouchActions() {
return new GaiaPacket(TOUCH_ACTIONS_FEATURE, TOUCH_ACTIONS_PDU_GET).encode();
}
public byte[] encodeGetAudioCurationMode() {
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_GET_MODE).encode();
}
private byte[] encodeSetEqualizerPreset() {
Prefs prefs = getDevicePrefs();
byte preset = Byte.parseByte(prefs.getString(PREF_MOONDROP_EQUALIZER_PRESET, "0"));
+2 -1
View File
@@ -2142,7 +2142,8 @@
<string name="devicetype_soundcore_q30" translatable="false">Soundcore Q30</string>
<string name="devicetype_soundcore_aerofit2" translatable="false">Soundcore AeroFit 2</string>
<string name="devicetype_pixel_buds_a_series" translatable="false">Pixel Buds A-Series</string>
<string name="devicetype_moondrop_space_travel" translatable="false">Moondrop Space Travel / 2</string>
<string name="devicetype_moondrop_space_travel" translatable="false">Moondrop Space Travel</string>
<string name="devicetype_moondrop_space_travel_2" translatable="false">Moondrop Space Travel 2</string>
<string name="devicetype_binary_sensor">Binary sensor</string>
<string name="devicetype_honor_band3" translatable="false">Honor Band 3</string>
<string name="devicetype_honor_band4" translatable="false">Honor Band 4</string>