Add support for Sony WF-C500

This commit is contained in:
Zahnstocher 2024-09-17 11:37:39 +02:00
parent 86460ea7c6
commit 57c8c77305
9 changed files with 105 additions and 3 deletions

View File

@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones;
public enum SonyHeadphonesCapabilities { public enum SonyHeadphonesCapabilities {
BatterySingle, BatterySingle,
BatteryDual, BatteryDual,
BatteryDual_2,
BatteryCase, BatteryCase,
PowerOffFromPhone, PowerOffFromPhone,
AmbientSoundControl, AmbientSoundControl,

View File

@ -70,7 +70,7 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
@Override @Override
public int getBatteryCount() { public int getBatteryCount() {
if (supports(SonyHeadphonesCapabilities.BatterySingle)) { if (supports(SonyHeadphonesCapabilities.BatterySingle)) {
if (supports(SonyHeadphonesCapabilities.BatteryDual)) { if (supports(SonyHeadphonesCapabilities.BatteryDual) || supports(SonyHeadphonesCapabilities.BatteryDual_2)) {
throw new IllegalStateException("A device can't have both single and dual battery"); throw new IllegalStateException("A device can't have both single and dual battery");
} else if (supports(SonyHeadphonesCapabilities.BatteryCase)) { } else if (supports(SonyHeadphonesCapabilities.BatteryCase)) {
throw new IllegalStateException("Devices with single battery + case are not supported by the protocol"); throw new IllegalStateException("Devices with single battery + case are not supported by the protocol");
@ -87,7 +87,7 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
batteryCount += 1; batteryCount += 1;
} }
if (supports(SonyHeadphonesCapabilities.BatteryDual)) { if (supports(SonyHeadphonesCapabilities.BatteryDual) || supports(SonyHeadphonesCapabilities.BatteryDual_2)) {
batteryCount += 2; batteryCount += 2;
} }
@ -106,7 +106,7 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_tws_case, R.string.battery_case)); batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_tws_case, R.string.battery_case));
} }
if (supports(SonyHeadphonesCapabilities.BatteryDual)) { if (supports(SonyHeadphonesCapabilities.BatteryDual) || supports(SonyHeadphonesCapabilities.BatteryDual_2)) {
batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_galaxy_buds_l, R.string.left_earbud)); batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_galaxy_buds_l, R.string.left_earbud));
batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_galaxy_buds_r, R.string.right_earbud)); batteries.add(new BatteryConfig(batteries.size(), R.drawable.ic_galaxy_buds_r, R.string.right_earbud));
} }

View File

@ -0,0 +1,68 @@
/* Copyright (C) 2024 Zahnstocher
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.sony.headphones.coordinators;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
public class SonyWFC500Coordinator extends SonyHeadphonesCoordinator {
@Override
protected Pattern getSupportedDeviceName() {
return Pattern.compile(".*WF-C500.*");
}
@Override
public BatteryConfig[] getBatteryConfig(final GBDevice device) {
final BatteryConfig battery1 = new BatteryConfig(0, R.drawable.ic_galaxy_buds_l, R.string.left_earbud);
final BatteryConfig battery2 = new BatteryConfig(1, R.drawable.ic_galaxy_buds_r, R.string.right_earbud);
return new BatteryConfig[]{battery1, battery2};
}
@Override
public List<SonyHeadphonesCapabilities> getCapabilities() {
return Arrays.asList(
SonyHeadphonesCapabilities.BatteryDual_2,
SonyHeadphonesCapabilities.EqualizerSimple,
SonyHeadphonesCapabilities.EqualizerWithCustomBands,
SonyHeadphonesCapabilities.AudioUpsampling,
SonyHeadphonesCapabilities.PowerOffFromPhone
);
}
@Override
public int getDeviceNameResource() {
return R.string.devicetype_sony_wf_c500;
}
@Override
public int getDefaultIconResource() {
return R.drawable.ic_device_galaxy_buds;
}
@Override
public int getDisabledIconResource() {
return R.drawable.ic_device_galaxy_buds_disabled;
}
}

View File

@ -221,6 +221,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM3Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM3Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM4Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM4Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM5Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM5Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWFC500Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWFSP800NCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWFSP800NCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM2Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM3Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM3Coordinator;
@ -459,6 +460,7 @@ public enum DeviceType {
SONY_LINKBUDS_S(SonyLinkBudsSCoordinator.class), SONY_LINKBUDS_S(SonyLinkBudsSCoordinator.class),
SONY_WH_1000XM5(SonyWH1000XM5Coordinator.class), SONY_WH_1000XM5(SonyWH1000XM5Coordinator.class),
SONY_WF_1000XM5(SonyWF1000XM5Coordinator.class), SONY_WF_1000XM5(SonyWF1000XM5Coordinator.class),
SONY_WF_C500(SonyWFC500Coordinator.class),
SOUNDCORE_LIBERTY3_PRO(SoundcoreLiberty3ProCoordinator.class), SOUNDCORE_LIBERTY3_PRO(SoundcoreLiberty3ProCoordinator.class),
SOUNDCORE_LIBERTY4_NC(SoundcoreLiberty4NCCoordinator.class), SOUNDCORE_LIBERTY4_NC(SoundcoreLiberty4NCCoordinator.class),
SOUNDCORE_MOTION300(SoundcoreMotion300Coordinator.class), SOUNDCORE_MOTION300(SoundcoreMotion300Coordinator.class),

View File

@ -638,6 +638,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
final Map<SonyHeadphonesCapabilities, Request> capabilityRequestMap = new LinkedHashMap<SonyHeadphonesCapabilities, Request>() {{ final Map<SonyHeadphonesCapabilities, Request> capabilityRequestMap = new LinkedHashMap<SonyHeadphonesCapabilities, Request>() {{
put(SonyHeadphonesCapabilities.BatterySingle, getBattery(BatteryType.SINGLE)); put(SonyHeadphonesCapabilities.BatterySingle, getBattery(BatteryType.SINGLE));
put(SonyHeadphonesCapabilities.BatteryDual, getBattery(BatteryType.DUAL)); put(SonyHeadphonesCapabilities.BatteryDual, getBattery(BatteryType.DUAL));
put(SonyHeadphonesCapabilities.BatteryDual_2, getBattery(BatteryType.DUAL_2));
put(SonyHeadphonesCapabilities.BatteryCase, getBattery(BatteryType.CASE)); put(SonyHeadphonesCapabilities.BatteryCase, getBattery(BatteryType.CASE));
put(SonyHeadphonesCapabilities.AmbientSoundControl, getAmbientSoundControl()); put(SonyHeadphonesCapabilities.AmbientSoundControl, getAmbientSoundControl());
put(SonyHeadphonesCapabilities.AncOptimizer, getNoiseCancellingOptimizerState()); put(SonyHeadphonesCapabilities.AncOptimizer, getNoiseCancellingOptimizerState());
@ -960,6 +961,29 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
gbDeviceEventBatteryInfoRight.level = payload[4]; gbDeviceEventBatteryInfoRight.level = payload[4];
gbDeviceEventBatteryInfoRight.state = payload[5] == 1 ? BatteryState.BATTERY_CHARGING : BatteryState.BATTERY_NORMAL; gbDeviceEventBatteryInfoRight.state = payload[5] == 1 ? BatteryState.BATTERY_CHARGING : BatteryState.BATTERY_NORMAL;
batteryEvents.add(gbDeviceEventBatteryInfoRight);
}
} else if (BatteryType.DUAL_2.equals(batteryType)) {
// Dual Battery (L / R)
LOG.debug("Battery Level: L: {}, R: {}", payload[2], payload[4]);
if (payload[2] != 0) {
final GBDeviceEventBatteryInfo gbDeviceEventBatteryInfoLeft = new GBDeviceEventBatteryInfo();
gbDeviceEventBatteryInfoLeft.batteryIndex = 0;
gbDeviceEventBatteryInfoLeft.level = payload[2];
gbDeviceEventBatteryInfoLeft.state = payload[3] == 1 ? BatteryState.BATTERY_CHARGING : BatteryState.BATTERY_NORMAL;
batteryEvents.add(gbDeviceEventBatteryInfoLeft);
}
if (payload[4] != 0) {
final GBDeviceEventBatteryInfo gbDeviceEventBatteryInfoRight = new GBDeviceEventBatteryInfo();
gbDeviceEventBatteryInfoRight.batteryIndex = 1;
gbDeviceEventBatteryInfoRight.level = payload[4];
gbDeviceEventBatteryInfoRight.state = payload[5] == 1 ? BatteryState.BATTERY_CHARGING : BatteryState.BATTERY_NORMAL;
batteryEvents.add(gbDeviceEventBatteryInfoRight); batteryEvents.add(gbDeviceEventBatteryInfoRight);
} }
} }

View File

@ -19,5 +19,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.pro
public enum BatteryType { public enum BatteryType {
SINGLE, SINGLE,
DUAL, DUAL,
DUAL_2,
CASE, CASE,
} }

View File

@ -1027,6 +1027,8 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
switch (b) { switch (b) {
case 0x00: case 0x00:
return BatteryType.SINGLE; return BatteryType.SINGLE;
case 0x01:
return BatteryType.DUAL_2;
case 0x09: case 0x09:
return BatteryType.DUAL; return BatteryType.DUAL;
case 0x0a: case 0x0a:
@ -1041,6 +1043,8 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
switch (batteryType) { switch (batteryType) {
case SINGLE: case SINGLE:
return 0x00; return 0x00;
case DUAL_2:
return 0x01;
case DUAL: case DUAL:
return 0x09; return 0x09;
case CASE: case CASE:

View File

@ -1795,6 +1795,7 @@
<string name="devicetype_sony_wf_1000xm3">Sony WF-1000XM3</string> <string name="devicetype_sony_wf_1000xm3">Sony WF-1000XM3</string>
<string name="devicetype_sony_wf_1000xm4">Sony WF-1000XM4</string> <string name="devicetype_sony_wf_1000xm4">Sony WF-1000XM4</string>
<string name="devicetype_sony_wf_1000xm5">Sony WF-1000XM5</string> <string name="devicetype_sony_wf_1000xm5">Sony WF-1000XM5</string>
<string name="devicetype_sony_wf_c500">Sony WF-C500</string>
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string> <string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
<string name="devicetype_sony_linkbuds">Sony LinkBuds</string> <string name="devicetype_sony_linkbuds">Sony LinkBuds</string>
<string name="devicetype_sony_linkbuds_s">Sony LinkBuds S</string> <string name="devicetype_sony_linkbuds_s">Sony LinkBuds S</string>

View File

@ -104,6 +104,7 @@ public class SonyProtocolImplV2Test {
final Map<BatteryType, String> commands = new LinkedHashMap<BatteryType, String>() {{ final Map<BatteryType, String> commands = new LinkedHashMap<BatteryType, String>() {{
put(BatteryType.SINGLE, "22:00"); put(BatteryType.SINGLE, "22:00");
put(BatteryType.DUAL, "22:09"); put(BatteryType.DUAL, "22:09");
put(BatteryType.DUAL_2, "22:01");
put(BatteryType.CASE, "22:0a"); put(BatteryType.CASE, "22:0a");
}}; }};