mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
refactor: add protocol implementation and command variables
This commit is contained in:
-4
@@ -38,8 +38,4 @@ public abstract class AbstractSoundcoreProtocol extends GBDeviceProtocol {
|
||||
else return 0x00;
|
||||
}
|
||||
|
||||
public byte[] encodeDeviceInfoRequest() {
|
||||
return new SoundcorePacket((short) 0x0101).encode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-39
@@ -10,20 +10,24 @@ import static nodomain.freeyourgadget.gadgetbridge.util.GB.hexdump;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.AbstractSoundcoreProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcorePacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class SoundcoreAeroFitProtocol extends AbstractSoundcoreProtocol {
|
||||
public class SoundcoreAeroFitProtocol extends SoundcoreProtocolImplV1 {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreAeroFitProtocol.class);
|
||||
|
||||
private static final short CMD_GET_CONNECTED_DEVICES = (short) 0x010b;
|
||||
private static final short CMD_SET_BATTERY_LOW_TONE = (short) 0x8210;
|
||||
private static final short CMD_SET_GAMING_MODE = (short) 0x8701;
|
||||
private static final short CMD_SET_TOUCH_LOCK = (short) 0x9410;
|
||||
|
||||
private static final int battery_case = 0;
|
||||
private static final int battery_earphone_left = 1;
|
||||
private static final int battery_earphone_right = 2;
|
||||
@@ -34,8 +38,7 @@ public class SoundcoreAeroFitProtocol extends AbstractSoundcoreProtocol {
|
||||
|
||||
@Override
|
||||
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
||||
ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
SoundcorePacket packet = SoundcorePacket.decode(buf);
|
||||
SoundcorePacket packet = decodePacket(responseData);
|
||||
|
||||
if (packet == null)
|
||||
return null;
|
||||
@@ -44,21 +47,21 @@ public class SoundcoreAeroFitProtocol extends AbstractSoundcoreProtocol {
|
||||
short cmd = packet.getCommand();
|
||||
byte[] payload = packet.getPayload();
|
||||
|
||||
if (cmd == (short) 0x0101) {
|
||||
if (cmd == CMD_GET_DEVICE_INFO) {
|
||||
String firmware1 = readString(payload, 4, 5);
|
||||
String firmware2 = readString(payload, 9, 5);
|
||||
String serialNumber = readString(payload, 14, 16);
|
||||
|
||||
handleBatteryInfo(devEvts, null, payload[2], payload[3]);
|
||||
devEvts.add(buildVersionInfo(firmware1, firmware2, serialNumber));
|
||||
} else if (cmd == (short) 0x010b) {
|
||||
} else if (cmd == CMD_GET_CONNECTED_DEVICES) {
|
||||
// shows connected devices from 50 onwards
|
||||
// readString(payload, 50, 112)
|
||||
// maybe also other settings
|
||||
LOG.debug("Incoming Information about connected devices, dump: " + hexdump(responseData));
|
||||
} else if (cmd == (short) 0x0301) { // Battery Update
|
||||
} else if (cmd == CMD_NOTIFY_BATTERY_INFO) {
|
||||
handleBatteryInfo(devEvts, payload[2], payload[0], payload[1]);
|
||||
} else if (cmd == (short) 0x0401) {
|
||||
} else if (cmd == CMD_NOTIFY_CHARGING_INFO) {
|
||||
boolean leftInCase = payload[0] == 0x01;
|
||||
boolean rightInCase = payload[1] == 0x01;
|
||||
LOG.info("Left Earbud in Charging Case: " + leftInCase + ", Right Earbud in Charging Case: " + rightInCase);
|
||||
@@ -88,21 +91,21 @@ public class SoundcoreAeroFitProtocol extends AbstractSoundcoreProtocol {
|
||||
// Control
|
||||
case PREF_SOUNDCORE_CONTROL_TOUCH_DISABLED:
|
||||
boolean touchDisabled = prefs.getBoolean(PREF_SOUNDCORE_CONTROL_TOUCH_DISABLED, false);
|
||||
return new SoundcorePacket((short) 0x9410, new byte[]{encodeBoolean(touchDisabled)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_TOUCH_LOCK, touchDisabled);
|
||||
|
||||
// Miscellaneous Settings
|
||||
case PREF_SOUNDCORE_TOUCH_TONE:
|
||||
boolean touchTone = prefs.getBoolean(PREF_SOUNDCORE_TOUCH_TONE, false);
|
||||
return new SoundcorePacket((short) 0x8301, new byte[]{encodeBoolean(touchTone)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_TOUCH_TONE, touchTone);
|
||||
case PREF_SOUNDCORE_BATTERY_LOW_TONE:
|
||||
boolean batteryLowTone = prefs.getBoolean(PREF_SOUNDCORE_BATTERY_LOW_TONE, false);
|
||||
return new SoundcorePacket((short) 0x8210, new byte[]{encodeBoolean(batteryLowTone)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_BATTERY_LOW_TONE, batteryLowTone);
|
||||
case PREF_SOUNDCORE_GAMING_MODE:
|
||||
boolean gamingMode = prefs.getBoolean(PREF_SOUNDCORE_GAMING_MODE, false);
|
||||
return new SoundcorePacket((short) 0x8701, new byte[]{encodeBoolean(gamingMode)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_GAMING_MODE, gamingMode);
|
||||
case PREF_SOUNDCORE_AUTO_POWER_OFF:
|
||||
int duration = Integer.parseInt(prefs.getString(PREF_SOUNDCORE_AUTO_POWER_OFF, "3"));
|
||||
return setAutoPowerOff(duration).encode();
|
||||
return encodeAutoPowerOff(duration, (byte) 0x03);
|
||||
default:
|
||||
LOG.debug("Unsupported CONFIG: " + config);
|
||||
}
|
||||
@@ -110,29 +113,4 @@ public class SoundcoreAeroFitProtocol extends AbstractSoundcoreProtocol {
|
||||
return super.encodeSendConfiguration(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 0: No Auto Power off
|
||||
* 1: Auto Power off 10 min
|
||||
* 2: Auto Power off 20 min
|
||||
* 3: Auto Power off 30 min
|
||||
* 4: Auto Power off 60 min
|
||||
*/
|
||||
private SoundcorePacket setAutoPowerOff(int duration) {
|
||||
byte[] payload;
|
||||
|
||||
if (duration > 0)
|
||||
payload = new byte[] { (byte)0x01, (byte)(duration - 1) };
|
||||
else
|
||||
payload = new byte[] { (byte)0x00, (byte)0x03 };
|
||||
|
||||
return new SoundcorePacket((short) 0x8601, payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeFindDevice(boolean start) {
|
||||
boolean findLeft = start;
|
||||
boolean findRight = start;
|
||||
byte[] payload = new byte[]{encodeBoolean(findLeft), encodeBoolean(findRight), 0x00};
|
||||
return new SoundcorePacket((short) 0x8910, payload).encode();
|
||||
}
|
||||
}
|
||||
|
||||
+27
-111
@@ -2,12 +2,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.liberty;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.util.GB.hexdump;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -15,14 +12,21 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSett
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.AbstractSoundcoreProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcorePacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
public class SoundcoreLibertyProtocol extends SoundcoreProtocolImplV1 {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreLibertyProtocol.class);
|
||||
|
||||
private static final short CMD_GET_UNKNOWN_DATA_8D01 = (short) 0x8d01;
|
||||
private static final short CMD_GET_UNKNOWN_DATA_8205 = (short) 0x8205;
|
||||
private static final short CMD_SET_AMBIENT_SOUND_CONTROL_BUTTON_MODE = (short) 0x8206;
|
||||
private static final short CMD_SET_TOUCH_LOCK = (short) 0x8304;
|
||||
private static final short CMD_SET_WEARING_DETECTION = (short) 0x8101;
|
||||
private static final short CMD_SET_WEARING_TONE = (short) 0x8c01;
|
||||
|
||||
private static final int battery_case = 0;
|
||||
private static final int battery_earphone_left = 1;
|
||||
private static final int battery_earphone_right = 2;
|
||||
@@ -33,8 +37,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
|
||||
@Override
|
||||
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
||||
ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
SoundcorePacket packet = SoundcorePacket.decode(buf);
|
||||
SoundcorePacket packet = decodePacket(responseData);
|
||||
|
||||
if (packet == null)
|
||||
return null;
|
||||
@@ -43,7 +46,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
short cmd = packet.getCommand();
|
||||
byte[] payload = packet.getPayload();
|
||||
|
||||
if (cmd == (short) 0x0101) {
|
||||
if (cmd == CMD_GET_DEVICE_INFO) {
|
||||
int batteryLeft = payload[2] * 20;
|
||||
int batteryRight = payload[3] * 20;
|
||||
|
||||
@@ -55,15 +58,15 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
devEvts.add(buildBatteryInfo(battery_earphone_left, batteryLeft));
|
||||
devEvts.add(buildBatteryInfo(battery_earphone_right, batteryRight));
|
||||
devEvts.add(buildVersionInfo(firmware1, firmware2, serialNumber));
|
||||
} else if (cmd == (short) 0x8d01) {
|
||||
} else if (cmd == CMD_GET_UNKNOWN_DATA_8D01) {
|
||||
LOG.debug("Unknown incoming message - command: " + cmd + ", dump: " + hexdump(responseData));
|
||||
} else if (cmd == (short) 0x8205) {
|
||||
} else if (cmd == CMD_GET_UNKNOWN_DATA_8205) {
|
||||
LOG.debug("Unknown incoming message - command: " + cmd + ", dump: " + hexdump(responseData));
|
||||
} else if (cmd == (short) 0x0105) {
|
||||
} else if (cmd == CMD_GET_UNKNOWN_DATA_0105) {
|
||||
LOG.debug("Unknown incoming message - command: " + cmd + ", dump: " + hexdump(responseData));
|
||||
} else if (cmd == (short) 0x0106) { // ANC Mode Update
|
||||
decodeAudioMode(payload);
|
||||
} else if (cmd == (short) 0x0301) { // Battery Update
|
||||
} else if (cmd == CMD_NOTIFY_AUDIO_MODE) {
|
||||
decodeAdvancedAudioMode(payload);
|
||||
} else if (cmd == CMD_NOTIFY_BATTERY_INFO) {
|
||||
int batteryLeft = payload[0] * 20;
|
||||
int batteryRight = payload[1] * 20;
|
||||
int batteryCase = payload[2] * 20;
|
||||
@@ -79,40 +82,6 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
return devEvts.toArray(new GBDeviceEvent[devEvts.size()]);
|
||||
}
|
||||
|
||||
private void decodeAudioMode(byte[] payload) {
|
||||
SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
String ambient_sound_mode = "off";
|
||||
int anc_strength = 0;
|
||||
|
||||
if (payload[0] == 0x00) {
|
||||
ambient_sound_mode = "noise_cancelling";
|
||||
} else if (payload[0] == 0x01) {
|
||||
ambient_sound_mode = "ambient_sound";
|
||||
} else if (payload[0] == 0x02) {
|
||||
ambient_sound_mode = "off";
|
||||
}
|
||||
|
||||
if (payload[1] == 0x10) {
|
||||
anc_strength = 0;
|
||||
} else if (payload[1] == 0x20) {
|
||||
anc_strength = 1;
|
||||
} else if (payload[1] == 0x30) {
|
||||
anc_strength = 2;
|
||||
}
|
||||
|
||||
boolean vocal_mode = (payload[2] == 0x01);
|
||||
boolean adaptive_anc = (payload[3] == 0x01);
|
||||
boolean windnoiseReduction = (payload[4] == 0x01);
|
||||
|
||||
editor.putString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, ambient_sound_mode);
|
||||
editor.putInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, anc_strength);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, vocal_mode);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, adaptive_anc);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, windnoiseReduction);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeSendConfiguration(String config) {
|
||||
Prefs prefs = getDevicePrefs();
|
||||
@@ -125,7 +94,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE:
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING:
|
||||
case DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL:
|
||||
return encodeAudioMode();
|
||||
return encodeAdvancedAudioMode(true);
|
||||
|
||||
// Control
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_DISABLED:
|
||||
@@ -178,13 +147,13 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
// Miscellaneous Settings
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_DETECTION:
|
||||
boolean wearingDetection = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_DETECTION, false);
|
||||
return new SoundcorePacket((short) 0x8101, new byte[]{encodeBoolean(wearingDetection)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_WEARING_DETECTION, wearingDetection);
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_TONE:
|
||||
boolean wearingTone = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WEARING_TONE, false);
|
||||
return new SoundcorePacket((short) 0x8c01, new byte[]{encodeBoolean(wearingTone)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_WEARING_TONE, wearingTone);
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE:
|
||||
boolean touchTone = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE, false);
|
||||
return new SoundcorePacket((short) 0x8301, new byte[]{encodeBoolean(touchTone)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_TOUCH_TONE, touchTone);
|
||||
default:
|
||||
LOG.debug("Unsupported CONFIG: " + config);
|
||||
}
|
||||
@@ -194,66 +163,14 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
|
||||
byte[] encodeMysteryDataRequest1() {
|
||||
byte[] payload = new byte[]{0x00};
|
||||
return new SoundcorePacket((short) 0x8d01, payload).encode();
|
||||
return encodeCommand(CMD_GET_UNKNOWN_DATA_8D01, payload);
|
||||
}
|
||||
byte[] encodeMysteryDataRequest2() {
|
||||
return new SoundcorePacket((short) 0x0105).encode();
|
||||
return encodeRequest(CMD_GET_UNKNOWN_DATA_0105);
|
||||
}
|
||||
byte[] encodeMysteryDataRequest3() {
|
||||
byte[] payload = new byte[]{0x00};
|
||||
return new SoundcorePacket((short) 0x8205, payload).encode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the following settings to a payload to set the audio-mode on the headphones:
|
||||
* PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL If ANC, Transparent or neither should be active
|
||||
* PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING If the strenght of the ANC should be set manual or adaptively according to ambient noise
|
||||
* PREF_SONY_AMBIENT_SOUND_LEVEL How strong the ANC should be in manual mode
|
||||
* PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE If the Transparency should focus on vocals or should be fully transparent
|
||||
* PREF_SOUNDCORE_WIND_NOISE_REDUCTION If Transparency or ANC should reduce Wind Noise
|
||||
* @return The payload
|
||||
*/
|
||||
private byte[] encodeAudioMode() {
|
||||
Prefs prefs = getDevicePrefs();
|
||||
|
||||
byte ambient_sound_mode;
|
||||
switch (prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off")) {
|
||||
case "noise_cancelling":
|
||||
ambient_sound_mode = 0x00;
|
||||
break;
|
||||
case "ambient_sound":
|
||||
ambient_sound_mode = 0x01;
|
||||
break;
|
||||
case "off":
|
||||
ambient_sound_mode = 0x02;
|
||||
break;
|
||||
default:
|
||||
LOG.error("Invalid Ambient Mode selected");
|
||||
return null;
|
||||
}
|
||||
|
||||
byte anc_strength;
|
||||
switch (prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0)) {
|
||||
case 0:
|
||||
anc_strength = 0x10;
|
||||
break;
|
||||
case 1:
|
||||
anc_strength = 0x20;
|
||||
break;
|
||||
case 2:
|
||||
anc_strength = 0x30;
|
||||
break;
|
||||
default:
|
||||
LOG.error("Invalid ANC Strength selected");
|
||||
return null;
|
||||
}
|
||||
|
||||
byte adaptive_anc = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true));
|
||||
byte vocal_mode = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false));
|
||||
byte windnoise_reduction = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false));
|
||||
|
||||
byte[] payload = new byte[]{ambient_sound_mode, anc_strength, vocal_mode, adaptive_anc, windnoise_reduction, 0x01};
|
||||
return new SoundcorePacket((short) 0x8106, payload).encode();
|
||||
return encodeCommand(CMD_GET_UNKNOWN_DATA_8205, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,7 +197,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
return null;
|
||||
}
|
||||
payload = new byte[]{0x00, action.getCode(), enabled_byte};
|
||||
return new SoundcorePacket((short) 0x8304, payload).encode();
|
||||
return encodeCommand(CMD_SET_TOUCH_LOCK, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,8 +224,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
LOG.error("Invalid Tap action");
|
||||
return null;
|
||||
}
|
||||
byte[] payload = new byte[] {encodeBoolean(right), action.getCode(), function_byte};
|
||||
return new SoundcorePacket((short) 0x8104, payload).encode();
|
||||
return encodeControlFunctionMessage(right, action.getCode(), function_byte);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,7 +234,7 @@ public class SoundcoreLibertyProtocol extends AbstractSoundcoreProtocol {
|
||||
private byte[] encodeControlAmbientModeMessage(boolean anc, boolean transparency, boolean normal) {
|
||||
// Original app does not allow only one true flag. Unsure if Earbuds accept this state.
|
||||
byte ambientModes = (byte) (4 * (normal?1:0) + 2 * (transparency?1:0) + (anc?1:0));
|
||||
return new SoundcorePacket((short) 0x8206, new byte[] {ambientModes}).encode();
|
||||
return encodeCommand(CMD_SET_AMBIENT_SOUND_CONTROL_BUTTON_MODE, new byte[] {ambientModes});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -38,12 +38,15 @@ import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1.CMD_GET_DEVICE_INFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1.CMD_NOTIFY_BATTERY_INFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1.CMD_NOTIFY_CHARGING_INFO;
|
||||
import static nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1.CMD_SET_AUTO_POWER_OFF;
|
||||
|
||||
public class SoundcoreMotion300Protocol extends GBDeviceProtocol {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreMotion300Protocol.class);
|
||||
|
||||
// Some of these commands are not used right now, they serve as documentation
|
||||
private static final short CMD_GET_DEVICE_INFO = (short)0x0101;
|
||||
private static final short CMD_GET_LDAC_MODE = (short)0x7f01;
|
||||
private static final short CMD_GET_BUTTON_BRIGHTNESS = (short)0x9310;
|
||||
private static final short CMD_GET_EQUALIZER = (short)0x8902;
|
||||
@@ -51,14 +54,11 @@ public class SoundcoreMotion300Protocol extends GBDeviceProtocol {
|
||||
|
||||
private static final short CMD_SET_VOICE_PROMPTS = (short)0x9001;
|
||||
private static final short CMD_SET_BUTTON_BRIGHTNESS = (short)0x9210;
|
||||
private static final short CMD_SET_AUTO_POWER_OFF = (short)0x8601;
|
||||
private static final short CMD_SET_LDAC_MODE = (short)0xff01;
|
||||
private static final short CMD_SET_ADAPTIVE_DIRECTION = (short)0x8a02;
|
||||
private static final short CMD_SET_EQUALIZER_PRESET = (short)0x8b02;
|
||||
private static final short CMD_SET_EQUALIZER_CUSTOM = (short)0x8d02;
|
||||
|
||||
private static final short CMD_NOTIFY_BATTERY_INFO = (short)0x0301;
|
||||
private static final short CMD_NOTIFY_CHARGING_INFO = (short)0x0401;
|
||||
private static final short CMD_NOTIFY_VOLUME_INFO = (short)0x0901;
|
||||
private static final short CMD_NOTIFY_PLAYBACK_INFO = (short)0x2101;
|
||||
private static final short CMD_NOTIFY_BASS_MODE = (short)0x8e02;
|
||||
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.AbstractSoundcoreProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcorePacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public abstract class SoundcoreProtocolImplV1 extends AbstractSoundcoreProtocol {
|
||||
public static final short CMD_GET_DEVICE_INFO = (short) 0x0101;
|
||||
public static final short CMD_GET_UNKNOWN_DATA_0105 = (short) 0x0105;
|
||||
|
||||
public static final short CMD_NOTIFY_BATTERY_INFO = (short) 0x0301;
|
||||
public static final short CMD_NOTIFY_CHARGING_INFO = (short) 0x0401;
|
||||
public static final short CMD_NOTIFY_AUDIO_MODE = (short) 0x0106;
|
||||
|
||||
public static final short CMD_SET_AUDIO_MODE = (short) 0x8106;
|
||||
public static final short CMD_SET_CONTROL_FUNCTION = (short) 0x8104;
|
||||
public static final short CMD_SET_TOUCH_TONE = (short) 0x8301;
|
||||
public static final short CMD_SET_AUTO_POWER_OFF = (short) 0x8601;
|
||||
public static final short CMD_SET_FIND_DEVICE = (short) 0x8910;
|
||||
public static final short CMD_ENABLE_PAIRING_MODE = (short) 0x850b;
|
||||
|
||||
protected SoundcoreProtocolImplV1(final GBDevice device) {
|
||||
super(device);
|
||||
}
|
||||
|
||||
protected SoundcorePacket decodePacket(final byte[] responseData) {
|
||||
return SoundcorePacket.decode(ByteBuffer.wrap(responseData));
|
||||
}
|
||||
|
||||
protected byte[] encodeRequest(final short command) {
|
||||
return new SoundcorePacket(command).encode();
|
||||
}
|
||||
|
||||
protected byte[] encodeCommand(final short command, final byte[] payload) {
|
||||
return new SoundcorePacket(command, payload).encode();
|
||||
}
|
||||
|
||||
protected byte[] encodeBooleanCommand(final short command, final boolean enabled) {
|
||||
return encodeCommand(command, new byte[]{encodeBoolean(enabled)});
|
||||
}
|
||||
|
||||
public byte[] encodeDeviceInfoRequest() {
|
||||
return encodeRequest(CMD_GET_DEVICE_INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeFindDevice(final boolean start) {
|
||||
return encodeCommand(CMD_SET_FIND_DEVICE, new byte[]{
|
||||
encodeBoolean(start),
|
||||
encodeBoolean(start),
|
||||
0x00
|
||||
});
|
||||
}
|
||||
|
||||
protected byte[] encodePairingMode() {
|
||||
return encodeCommand(CMD_ENABLE_PAIRING_MODE, new byte[]{0x00, (byte) 0x90});
|
||||
}
|
||||
|
||||
protected byte[] encodeAutoPowerOff(final int duration, final byte disabledDuration) {
|
||||
final byte[] payload;
|
||||
|
||||
if (duration > 0) {
|
||||
payload = new byte[]{0x01, (byte) (duration - 1)};
|
||||
} else {
|
||||
payload = new byte[]{0x00, disabledDuration};
|
||||
}
|
||||
|
||||
return encodeCommand(CMD_SET_AUTO_POWER_OFF, payload);
|
||||
}
|
||||
|
||||
protected byte[] encodeControlFunctionMessage(final boolean right, final byte action, final byte function) {
|
||||
return encodeCommand(CMD_SET_CONTROL_FUNCTION, new byte[]{encodeBoolean(right), action, function});
|
||||
}
|
||||
|
||||
protected byte[] encodeAdvancedAudioMode(final boolean appendStateByte) {
|
||||
final Prefs prefs = getDevicePrefs();
|
||||
final Byte ambientSoundMode = encodeAmbientSoundMode(prefs.getString(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL,
|
||||
"off"
|
||||
));
|
||||
|
||||
if (ambientSoundMode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Byte ancStrength = encodeAncStrength(prefs.getInt(
|
||||
DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL,
|
||||
0
|
||||
));
|
||||
|
||||
if (ancStrength == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte vocalMode = encodeBoolean(prefs.getBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE,
|
||||
false
|
||||
));
|
||||
final byte adaptiveAnc = encodeBoolean(prefs.getBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING,
|
||||
true
|
||||
));
|
||||
final byte windNoiseReduction = encodeBoolean(prefs.getBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION,
|
||||
false
|
||||
));
|
||||
|
||||
final byte[] payload = new byte[]{
|
||||
ambientSoundMode.byteValue(),
|
||||
ancStrength.byteValue(),
|
||||
vocalMode,
|
||||
adaptiveAnc,
|
||||
windNoiseReduction
|
||||
};
|
||||
|
||||
if (appendStateByte) {
|
||||
final byte[] statePayload = Arrays.copyOf(payload, payload.length + 1);
|
||||
statePayload[statePayload.length - 1] = 0x01;
|
||||
return encodeCommand(CMD_SET_AUDIO_MODE, statePayload);
|
||||
}
|
||||
|
||||
return encodeCommand(CMD_SET_AUDIO_MODE, payload);
|
||||
}
|
||||
|
||||
protected void decodeAdvancedAudioMode(final byte[] payload) {
|
||||
if (payload.length < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SharedPreferences.Editor editor = getDevicePrefs().getPreferences().edit();
|
||||
|
||||
editor.putString(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL,
|
||||
decodeAmbientSoundMode(payload[0])
|
||||
);
|
||||
editor.putInt(
|
||||
DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL,
|
||||
decodeAncStrength(payload[1])
|
||||
);
|
||||
editor.putBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE,
|
||||
payload[2] == 0x01
|
||||
);
|
||||
editor.putBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING,
|
||||
payload[3] == 0x01
|
||||
);
|
||||
editor.putBoolean(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION,
|
||||
payload[4] == 0x01
|
||||
);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
protected Byte encodeAmbientSoundMode(final String ambientMode) {
|
||||
switch (ambientMode) {
|
||||
case "noise_cancelling":
|
||||
return (byte) 0x00;
|
||||
case "ambient_sound":
|
||||
return (byte) 0x01;
|
||||
case "off":
|
||||
return (byte) 0x02;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String decodeAmbientSoundMode(final byte ambientMode) {
|
||||
switch (ambientMode) {
|
||||
case 0x00:
|
||||
return "noise_cancelling";
|
||||
case 0x01:
|
||||
return "ambient_sound";
|
||||
case 0x02:
|
||||
default:
|
||||
return "off";
|
||||
}
|
||||
}
|
||||
|
||||
protected Byte encodeAncStrength(final int strength) {
|
||||
if (strength < 0 || strength > 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (byte) ((strength + 1) << 4);
|
||||
}
|
||||
|
||||
protected int decodeAncStrength(final byte strength) {
|
||||
switch (strength & 0x30) {
|
||||
case 0x20:
|
||||
return 1;
|
||||
case 0x30:
|
||||
return 2;
|
||||
case 0x10:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-35
@@ -7,7 +7,6 @@ import android.content.SharedPreferences;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -15,22 +14,23 @@ import java.util.List;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.AbstractSoundcoreProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.SoundcorePacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.protocol.impl.v1.SoundcoreProtocolImplV1;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
public class SoundcoreQ30Protocol extends SoundcoreProtocolImplV1 {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreQ30Protocol.class);
|
||||
|
||||
private static final short CMD_SET_EQUALIZER = (short) 0x8102;
|
||||
|
||||
protected SoundcoreQ30Protocol(GBDevice device) {
|
||||
super(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
||||
ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
SoundcorePacket packet = SoundcorePacket.decode(buf);
|
||||
SoundcorePacket packet = decodePacket(responseData);
|
||||
|
||||
if (packet == null)
|
||||
return null;
|
||||
@@ -39,7 +39,7 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
short cmd = packet.getCommand();
|
||||
byte[] payload = packet.getPayload();
|
||||
|
||||
if (cmd == (short) 0x0101) {
|
||||
if (cmd == CMD_GET_DEVICE_INFO) {
|
||||
int battery = payload[0] * 20; // only 20% steps available here
|
||||
devEvts.add(buildBatteryInfo(0, battery));
|
||||
|
||||
@@ -56,9 +56,9 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
String serialNumber = readString(payload, 44, 16);
|
||||
devEvts.add(buildVersionInfo(firmware1, firmware2, serialNumber));
|
||||
|
||||
} else if (cmd == (short) 0x0106) { // ANC Mode Updated by Button
|
||||
} else if (cmd == CMD_NOTIFY_AUDIO_MODE) {
|
||||
decodeAudioMode(payload);
|
||||
} else if (cmd == (short) 0x8106) {
|
||||
} else if (cmd == CMD_SET_AUDIO_MODE) {
|
||||
// Acknowledgement for changed Ambient Mode
|
||||
// empty payload
|
||||
} else {
|
||||
@@ -94,20 +94,14 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
private byte[] encodeAudioMode() {
|
||||
Prefs prefs = getDevicePrefs();
|
||||
|
||||
byte ambient_sound_mode;
|
||||
switch (prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off")) {
|
||||
case "noise_cancelling":
|
||||
ambient_sound_mode = 0x00;
|
||||
break;
|
||||
case "ambient_sound":
|
||||
ambient_sound_mode = 0x01;
|
||||
break;
|
||||
case "off":
|
||||
ambient_sound_mode = 0x02;
|
||||
break;
|
||||
default:
|
||||
LOG.error("Invalid Ambient Mode selected");
|
||||
return null;
|
||||
final Byte ambient_sound_mode = encodeAmbientSoundMode(prefs.getString(
|
||||
DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL,
|
||||
"off"
|
||||
));
|
||||
|
||||
if (ambient_sound_mode == null) {
|
||||
LOG.error("Invalid Ambient Mode selected");
|
||||
return null;
|
||||
}
|
||||
|
||||
byte anc_mode;
|
||||
@@ -126,8 +120,8 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] payload = new byte[]{ambient_sound_mode, anc_mode, 0x01};
|
||||
return new SoundcorePacket((short) 0x8106, payload).encode();
|
||||
byte[] payload = new byte[]{ambient_sound_mode.byteValue(), anc_mode, 0x01};
|
||||
return encodeCommand(CMD_SET_AUDIO_MODE, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,17 +130,9 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
private void decodeAudioMode(byte[] payload) {
|
||||
SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
String ambient_sound_mode = "off";
|
||||
String ambient_sound_mode = decodeAmbientSoundMode(payload[0]);
|
||||
String anc_mode = "transport";
|
||||
|
||||
if (payload[0] == 0x00) {
|
||||
ambient_sound_mode = "noise_cancelling";
|
||||
} else if (payload[0] == 0x01) {
|
||||
ambient_sound_mode = "ambient_sound";
|
||||
} else if (payload[0] == 0x02) {
|
||||
ambient_sound_mode = "off";
|
||||
}
|
||||
|
||||
if (payload[1] == 0x00) {
|
||||
anc_mode = "transport";
|
||||
} else if (payload[1] == 0x01) {
|
||||
@@ -178,7 +164,7 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
byte band8 = 0x78;
|
||||
|
||||
byte[] payload = new byte[]{(byte) 0xfe, (byte) 0xfe, band1, band2, band3, band4, band5, band6, band7, band8};
|
||||
return new SoundcorePacket((short) 0x8102, payload).encode();
|
||||
return encodeCommand(CMD_SET_EQUALIZER, payload);
|
||||
}
|
||||
|
||||
private void decodeEqualizer(byte[] payload) {
|
||||
@@ -195,6 +181,6 @@ public class SoundcoreQ30Protocol extends AbstractSoundcoreProtocol {
|
||||
|
||||
|
||||
byte[] encodeMysteryDataRequest2() {
|
||||
return new SoundcorePacket((short) 0x0105).encode();
|
||||
return encodeRequest(CMD_GET_UNKNOWN_DATA_0105);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-98
@@ -2,7 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore.sport_x20
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -15,6 +14,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
private static final short CMD_SET_EQUALIZER = (short) 0x8703;
|
||||
private static final short CMD_SET_3D_SURROUND = (short) 0x8602;
|
||||
|
||||
private static final int CUSTOM_PRESET_ID = 0xfe;
|
||||
private static final int EQ_BANDS = 8;
|
||||
|
||||
@@ -53,11 +54,10 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
|
||||
@Override
|
||||
public GBDeviceEvent[] decodeResponse(final byte[] responseData) {
|
||||
final ByteBuffer buf = ByteBuffer.wrap(responseData);
|
||||
final SoundcorePacket packet = SoundcorePacket.decode(buf);
|
||||
final SoundcorePacket packet = decodePacket(responseData);
|
||||
|
||||
if (packet != null && packet.getCommand() == (short) 0x0106) {
|
||||
decodeAncAudioMode(packet.getPayload());
|
||||
if (packet != null && packet.getCommand() == CMD_NOTIFY_AUDIO_MODE) {
|
||||
decodeAdvancedAudioMode(packet.getPayload());
|
||||
return new GBDeviceEvent[0];
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE:
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING:
|
||||
case DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL:
|
||||
return encodeAncAudioMode();
|
||||
return encodeAdvancedAudioMode(false);
|
||||
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT:
|
||||
prefString = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_CONTROL_SINGLE_TAP_ACTION_LEFT, "PLAYPAUSE");
|
||||
@@ -109,11 +109,11 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE:
|
||||
final boolean pressAlert = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TOUCH_TONE, false);
|
||||
return new SoundcorePacket((short) 0x8301, new byte[]{encodeBoolean(pressAlert)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_TOUCH_TONE, pressAlert);
|
||||
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_3D_SURROUND:
|
||||
final boolean surround3d = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_3D_SURROUND, false);
|
||||
return new SoundcorePacket((short) 0x8602, new byte[]{encodeBoolean(surround3d)}).encode();
|
||||
return encodeBooleanCommand(CMD_SET_3D_SURROUND, surround3d);
|
||||
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_PRESET:
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_EQUALIZER_BAND1_VALUE:
|
||||
@@ -127,21 +127,13 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
return encodeEqualizer();
|
||||
|
||||
case DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ENABLE_PAIRING_MODE:
|
||||
return new SoundcorePacket((short) 0x850b, new byte[]{0x00, (byte) 0x90}).encode();
|
||||
return encodePairingMode();
|
||||
|
||||
default:
|
||||
return super.encodeSendConfiguration(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeFindDevice(final boolean start) {
|
||||
final boolean findLeft = start;
|
||||
final boolean findRight = start;
|
||||
final byte[] payload = new byte[]{encodeBoolean(findLeft), encodeBoolean(findRight), 0x00};
|
||||
return new SoundcorePacket((short) 0x8910, payload).encode();
|
||||
}
|
||||
|
||||
private byte[] encodeControlFunctionMessage(final TapAction action, final boolean right, final TapFunction function) {
|
||||
final byte functionByte;
|
||||
switch (action) {
|
||||
@@ -158,8 +150,7 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] payload = new byte[]{encodeBoolean(right), action.getCode(), functionByte};
|
||||
return new SoundcorePacket((short) 0x8104, payload).encode();
|
||||
return encodeControlFunctionMessage(right, action.getCode(), functionByte);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,83 +161,7 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
* 4: Auto Power off 60 min
|
||||
*/
|
||||
private byte[] encodeAutoPowerOff(final int duration) {
|
||||
final byte[] payload;
|
||||
|
||||
if (duration > 0) {
|
||||
payload = new byte[]{(byte) 0x01, (byte) (duration - 1)};
|
||||
} else {
|
||||
payload = new byte[]{(byte) 0x00, (byte) 0x03};
|
||||
}
|
||||
|
||||
return new SoundcorePacket((short) 0x8601, payload).encode();
|
||||
}
|
||||
|
||||
private void decodeAncAudioMode(final byte[] payload) {
|
||||
if (payload.length < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||
final SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
String ambientSoundMode = "off";
|
||||
if (payload[0] == 0x00) {
|
||||
ambientSoundMode = "noise_cancelling";
|
||||
} else if (payload[0] == 0x01) {
|
||||
ambientSoundMode = "ambient_sound";
|
||||
} else if (payload[0] == 0x02) {
|
||||
ambientSoundMode = "off";
|
||||
}
|
||||
|
||||
int ancStrength = ((payload[1] & 0x30) >> 4) - 1;
|
||||
|
||||
final boolean vocalMode = (payload[2] == 0x01);
|
||||
final boolean adaptiveAnc = (payload[3] == 0x01);
|
||||
final boolean windNoiseReduction = (payload[4] == 0x01);
|
||||
|
||||
editor.putString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, ambientSoundMode);
|
||||
editor.putInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, ancStrength);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, vocalMode);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, adaptiveAnc);
|
||||
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, windNoiseReduction);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private byte[] encodeAncAudioMode() {
|
||||
final Prefs prefs = getDevicePrefs();
|
||||
|
||||
final String ambientMode = prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off");
|
||||
final int ancStrengthValue = prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0);
|
||||
final boolean vocalMode = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false);
|
||||
final boolean adaptive = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true);
|
||||
final boolean windReduction = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false);
|
||||
|
||||
if (ancStrengthValue < 0 || ancStrengthValue > 2) {
|
||||
return null;
|
||||
}
|
||||
final byte ancStrengthByte = (byte) ((ancStrengthValue + 1) << 4);
|
||||
|
||||
final byte ambientModeByte;
|
||||
switch (ambientMode) {
|
||||
case "noise_cancelling":
|
||||
ambientModeByte = 0x00;
|
||||
break;
|
||||
case "ambient_sound":
|
||||
ambientModeByte = 0x01;
|
||||
break;
|
||||
case "off":
|
||||
ambientModeByte = 0x02;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte adaptiveByte = encodeBoolean(adaptive);
|
||||
final byte vocalModeByte = encodeBoolean(vocalMode);
|
||||
final byte windReductionByte = encodeBoolean(windReduction);
|
||||
|
||||
final byte[] payload = new byte[]{ambientModeByte, ancStrengthByte, vocalModeByte, adaptiveByte, windReductionByte};
|
||||
return new SoundcorePacket((short) 0x8106, payload).encode();
|
||||
return encodeAutoPowerOff(duration, (byte) 0x03);
|
||||
}
|
||||
|
||||
private byte[] encodeEqualizer() {
|
||||
@@ -256,7 +171,7 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
if (preset != CUSTOM_PRESET_ID) {
|
||||
final byte[] presetPayload = EQ_PRESET_PAYLOADS.get(preset);
|
||||
if (presetPayload != null) {
|
||||
return new SoundcorePacket(CMD_SET_EQUALIZER, presetPayload).encode();
|
||||
return encodeCommand(CMD_SET_EQUALIZER, presetPayload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +191,7 @@ public class SoundcoreSportX20Protocol extends SoundcoreLibertyProtocol {
|
||||
bandsToHex(tailBands)
|
||||
);
|
||||
|
||||
return new SoundcorePacket(CMD_SET_EQUALIZER, payload).encode();
|
||||
return encodeCommand(CMD_SET_EQUALIZER, payload);
|
||||
}
|
||||
|
||||
private void decodeEqualizer(final byte[] payload) {
|
||||
|
||||
Reference in New Issue
Block a user