Skip to content

Commit

Permalink
wip: introduce compat module and use new parser
Browse files Browse the repository at this point in the history
  • Loading branch information
gmallios committed Oct 15, 2023
1 parent cae5007 commit e9ee629
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 127 deletions.
3 changes: 3 additions & 0 deletions soundcore-lib/src/compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub use state::*;

mod state;
103 changes: 103 additions & 0 deletions soundcore-lib/src/compat/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use crate::error::SoundcoreError;
use crate::models::{
Battery, DualBattery, EQConfiguration, MonoEQ, SideTone, SoundMode, StereoEQConfiguration,
TouchTone, TwsStatus, WearDetection,
};
use crate::packets::ResponsePacket;
use crate::types::{ANCProfile, BatteryCharging, BatteryLevel, DeviceStatus, EQWave};

impl TryInto<DeviceStatus> for ResponsePacket {
type Error = SoundcoreError;
fn try_into(self) -> Result<DeviceStatus, Self::Error> {
match self {
ResponsePacket::DeviceState(state) => {
let (battery_level, battery_charging) = state.battery.into();
let (left_eq, right_eq) = state.eq.into();
Ok(DeviceStatus {
host_device: state.host_device.unwrap_or(0),
tws_status: state.tws_status.unwrap_or(TwsStatus(false)).0,
battery_level,
battery_charging,
anc_status: ANCProfile::from(state.sound_mode),
side_tone_enabled: state.side_tone.unwrap_or(SideTone(false)).0,
wear_detection_enabled: state.wear_detection.unwrap_or(WearDetection(false)).0,
touch_tone_enabled: state.touch_tone.unwrap_or(TouchTone(false)).0,
left_eq,
right_eq,
// TODO: Use actual HearID data
hearid_enabled: false,
left_hearid: EQWave::default(),
right_hearid: EQWave::default(),
left_hearid_customdata: EQWave::default(),
right_hearid_customdata: EQWave::default(),
})
}
_ => Err(SoundcoreError::IncompatibleResponse),
}
}
}

impl From<SoundMode> for ANCProfile {
fn from(mode: SoundMode) -> Self {
let bytes = mode.to_bytes();

ANCProfile {
option: bytes[0],
anc_option: bytes[1],
transparency_option: bytes[2],
anc_custom: bytes[3],
}
}
}

impl Into<(BatteryLevel, BatteryCharging)> for Battery {
fn into(self) -> (BatteryLevel, BatteryCharging) {
match self {
Battery::Single(batt) => {
let left = BatteryLevel {
left: batt.level,
right: 0,
};
let right = BatteryCharging {
left: batt.charging,
right: false,
};
(left, right)
}
Battery::Dual(batt) => {
let left = BatteryLevel {
left: batt.left.level,
right: batt.right.level,
};
let right = BatteryCharging {
left: batt.left.charging,
right: batt.right.charging,
};
(left, right)
}
}
}
}
// Maybe figure out how to do this better and test it
impl Into<EQWave> for MonoEQ {
fn into(self) -> EQWave {
EQWave::decode(&self.to_bytes()).unwrap()
}
}

impl Into<(EQWave, EQWave)> for EQConfiguration {
fn into(self) -> (EQWave, EQWave) {
match self {
EQConfiguration::Stereo(stereo) => {
let left = stereo.eq.left.into();
let right = stereo.eq.right.into();
(left, right)
}
EQConfiguration::Mono(mono) => {
let left = mono.eq.into();
let right = EQWave::default();
(left, right)
}
}
}
}
15 changes: 6 additions & 9 deletions soundcore-lib/src/devices/A3951Device.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use async_trait::async_trait;
use bluetooth_lib::{platform::RFCOMM, BluetoothAdrr, RFCOMMClient};
use log::debug;
use tokio::time::sleep;

use crate::packets::ResponsePacket;
use crate::{
base::{SoundcoreANC, SoundcoreDevice, SoundcoreEQ, SoundcoreHearID, SoundcoreLDAC},
error::SoundcoreError,
Expand All @@ -16,7 +12,11 @@ use crate::{
Clamp,
},
};
use async_trait::async_trait;
use bluetooth_lib::{platform::RFCOMM, BluetoothAdrr, RFCOMMClient};
use log::debug;
use std::time::Duration;
use tokio::time::sleep;

static SLEEP_DURATION: Duration = std::time::Duration::from_millis(30);

Expand Down Expand Up @@ -87,10 +87,7 @@ impl SoundcoreDevice for A3951 {
self.build_and_send_cmd(A3951_CMD_DEVICE_STATUS, None)
.await?;
let resp = self.recv().await?;
if A3951_RESPONSE_VERIFICATION {
verify_resp(&resp)?;
}
Ok(Self::decode(self, &resp)?)
Ok(ResponsePacket::from_bytes(&resp)?.try_into()?)
}

async fn get_info(&self) -> Result<DeviceInfo, SoundcoreError> {
Expand Down
18 changes: 17 additions & 1 deletion soundcore-lib/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,23 @@ pub enum SoundcoreError {
#[error("Invalid response")]
InvalidResponse,
#[error("Invalid response length (expected {expected}, got {got}, data: {data:?})")]
InvalidResponseLength { expected: usize, got: usize, data: Vec<u8> },
InvalidResponseLength {
expected: usize,
got: usize,
data: Vec<u8>,
},
#[error("Nom Parsing error")]
NomParseError { error: String },
#[error("Incompatible response")]
IncompatibleResponse,
}

impl From<nom::Err<nom::error::VerboseError<&[u8]>>> for SoundcoreError {
fn from<'a>(error: nom::Err<nom::error::VerboseError<&'a [u8]>>) -> Self {
SoundcoreError::NomParseError {
error: format!("{:?}", error),
}
}
}

// impl std::fmt::Display for SoundcoreError {
Expand Down
4 changes: 3 additions & 1 deletion soundcore-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
pub use bluetooth_lib::BluetoothAdrr;

pub mod api;
pub mod base;
pub mod compat;
pub mod devices;
pub mod error;
mod models;
Expand All @@ -9,4 +12,3 @@ pub mod statics;
pub mod types;
#[allow(non_snake_case)]
mod utils;
pub use bluetooth_lib::BluetoothAdrr;
111 changes: 0 additions & 111 deletions soundcore-lib/src/main.rs

This file was deleted.

2 changes: 1 addition & 1 deletion soundcore-lib/src/models/custom_anc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
#[derive(
Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Default, Hash,
)]
pub struct CustomANC(u8);
pub struct CustomANC(pub u8);

impl CustomANC {
pub fn from_u8(value: u8) -> Self {
Expand Down
3 changes: 2 additions & 1 deletion soundcore-lib/src/packets/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use crate::{
parsers::{parse_and_check_checksum, parse_packet_header},
};

use nom::error::{VerboseError};
use nom::error::VerboseError;

#[derive(Debug)]
pub enum ResponsePacket {
DeviceState(DeviceStateResponse),
DeviceInfo, // TODO
Expand Down
8 changes: 5 additions & 3 deletions soundcore-lib/src/packets/response/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ use serde::{Deserialize, Serialize};

use crate::{
models::{
AgeRange, Battery, ButtonModel, CustomHearID, SideTone,
SoundMode, SoundcoreFeatureFlags, TwsStatus, WearDetection,
AgeRange, Battery, ButtonModel, CustomHearID, EQConfiguration, SideTone, SoundMode,
SoundcoreFeatureFlags, TouchTone, TwsStatus, WearDetection,
},
parsers::{SoundcoreParseError, SoundcoreParseResult},
};

/// This is a generalized version of the state responses for all devices
/// All device-specific state responses should be able to be converted to this type
/// Also, this must be impl Into<SoundcoreDeviceState>
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone, Hash, Default)]
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone, Hash)]
pub struct DeviceStateResponse {
pub feature_flags: BitFlags<SoundcoreFeatureFlags>,
pub battery: Battery,
pub sound_mode: SoundMode,
pub eq: EQConfiguration,
pub host_device: Option<u8>,
pub tws_status: Option<TwsStatus>,
pub button_model: Option<ButtonModel>,
Expand All @@ -26,6 +27,7 @@ pub struct DeviceStateResponse {
pub wear_detection: Option<WearDetection>,
pub hear_id: Option<CustomHearID>,
pub age_range: Option<AgeRange>,
pub touch_tone: Option<TouchTone>,
}

// TODO
Expand Down
2 changes: 2 additions & 0 deletions soundcore-lib/src/packets/response/state/a3951.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ impl From<A3951StateResponse> for DeviceStateResponse {
wear_detection: Some(value.wear_detection),
hear_id: Some(value.hear_id),
age_range: Some(value.age_range),
touch_tone: Some(value.touch_tone),
eq: crate::models::EQConfiguration::Stereo(value.eq),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions soundcore-lib/src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ pub type SoundcoreParseResult<'a, T, E> = IResult<&'a [u8], T, E>;
pub trait SoundcoreParseError<'a>: ParseError<&'a [u8]> + ContextError<&'a [u8]> {}

impl<'a> SoundcoreParseError<'a> for nom::error::VerboseError<&'a [u8]> {}

#[cfg(test)]
pub type TestParserError<'a> = nom::error::VerboseError<&'a [u8]>;

0 comments on commit e9ee629

Please sign in to comment.