Skip to content

Commit

Permalink
feat(parser): ✨ Add A3027 DeviceState parser
Browse files Browse the repository at this point in the history
  • Loading branch information
gmallios committed Oct 28, 2023
1 parent 1de7b59 commit 2079b1e
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 8 deletions.
1 change: 0 additions & 1 deletion soundcore-lib/src/models/fw.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash)]
// TODO: Create parser
pub enum DeviceFirmware {
DUAL(FirmwareVer, FirmwareVer),
SINGLE(FirmwareVer),
Expand Down
9 changes: 6 additions & 3 deletions soundcore-lib/src/packets/response/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};

use crate::{
models::{
AgeRange, Battery, ButtonModel, CustomHearID, EQConfiguration, SideTone, SoundMode,
AgeRange, Battery, ButtonModel, CustomHearID, EQConfiguration, HearID, SideTone, SoundMode,
SoundcoreFeatureFlags, TouchTone, TwsStatus, WearDetection,
},
parsers::{SoundcoreParseError, SoundcoreParseResult},
Expand All @@ -25,7 +25,7 @@ pub struct DeviceStateResponse {
pub side_tone: Option<SideTone>,
pub hearid_eq_preset: Option<u16>,
pub wear_detection: Option<WearDetection>,
pub hear_id: Option<CustomHearID>,
pub hear_id: Option<HearID>,
pub age_range: Option<AgeRange>,
pub touch_tone: Option<TouchTone>,
}
Expand All @@ -42,5 +42,8 @@ pub fn parse_state_update_packet<'a, E: SoundcoreParseError<'a>>(
})(bytes)
}

mod a3027;
mod a3951;
pub use a3951::*;

use a3027::*;
use a3951::*;
124 changes: 124 additions & 0 deletions soundcore-lib/src/packets/response/state/a3027.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use enumflags2::{make_bitflags, BitFlags};
use nom::{
combinator::{all_consuming, opt},
error::context,
number::complete::{le_u16, le_u8},
sequence::tuple,
};
use serde::{Deserialize, Serialize};

use crate::{
models::{
A3909ButtonModel, AgeRange, BaseHearID, Battery, ButtonModel, CustomHearID, DeviceFirmware,
DualBattery, EQConfiguration, FirmwareVer, Gender, HearID, SerialNumber, SideTone,
SingleBattery, SoundMode, SoundcoreFeatureFlags, StereoEQConfiguration, TouchTone,
TwsStatus, WearDetection,
},
parsers::{
parse_base_hear_id, parse_bool, parse_dual_fw, parse_fw, parse_serial_number,
parse_single_battery,
},
};

use crate::parsers::{
bool_parser, parse_a3909_button_model, parse_age_range, parse_custom_hear_id,
parse_dual_battery, parse_gender, parse_sound_mode, parse_stereo_eq_configuration,
SoundcoreParseError, SoundcoreParseResult,
};

use super::DeviceStateResponse;

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
pub struct A3027StateResponse {
pub tws_status: TwsStatus,
pub battery: SingleBattery,
pub eq: StereoEQConfiguration,
pub gender: Gender,
pub age_range: AgeRange,
pub hear_id: BaseHearID,
pub sound_mode: SoundMode,
pub fw: DeviceFirmware,
pub sn: SerialNumber,
pub wear_detection: WearDetection,
pub touch_func: bool,
}

const A3027_FEATURE_FLAGS: BitFlags<SoundcoreFeatureFlags> = make_bitflags!(SoundcoreFeatureFlags::{
SOUND_MODE
| ANC_MODE
| TRANS_MODE
| CUSTOM_ANC
| WEAR_DETECTION
| EQ
| STEREO_EQ
| HEARID
});

impl From<A3027StateResponse> for DeviceStateResponse {
fn from(value: A3027StateResponse) -> Self {
DeviceStateResponse {
feature_flags: A3027_FEATURE_FLAGS,
battery: value.battery.into(),
sound_mode: value.sound_mode,
eq: EQConfiguration::Stereo(value.eq).into(),
host_device: None,
tws_status: value.tws_status.into(),
button_model: None,
side_tone: None,
hearid_eq_preset: None,
wear_detection: value.wear_detection.into(),
hear_id: Some(HearID::Base(value.hear_id)),
age_range: value.age_range.into(),
touch_tone: None,
}
}
}

pub fn parse_a3027_state_response<'a, E: SoundcoreParseError<'a>>(
bytes: &'a [u8],
) -> SoundcoreParseResult<A3027StateResponse, E> {
context(
"a3027_state_response",
all_consuming(|bytes| {
let (
bytes,
(battery, eq, gender, age_range, hear_id, sound_mode, fw, sn, wear_detection),
) = tuple((
parse_single_battery,
parse_stereo_eq_configuration,
parse_gender,
parse_age_range,
parse_base_hear_id,
parse_sound_mode,
parse_dual_fw,
parse_serial_number,
bool_parser::<WearDetection, E>,
))(bytes)?;

// Optional Fields
let (bytes, touch_func) = opt(parse_bool)(bytes)?;

Ok((
bytes,
A3027StateResponse {
tws_status: TwsStatus(true),
battery,
eq,
gender,
age_range,
hear_id,
sound_mode,
wear_detection,
fw: DeviceFirmware::DUAL(fw.0, fw.1),
sn,
touch_func: touch_func.unwrap_or(false),
},
))
}),
)(bytes)
}

#[cfg(test)]
mod a3027_state {
// TODO
}
9 changes: 5 additions & 4 deletions soundcore-lib/src/packets/response/state/a3951.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use nom::{
use serde::{Deserialize, Serialize};

use crate::models::{
A3909ButtonModel, AgeRange, Battery, ButtonModel, CustomHearID, DualBattery, Gender, SideTone,
SoundMode, SoundcoreFeatureFlags, StereoEQConfiguration, TouchTone, TwsStatus, WearDetection,
self, A3909ButtonModel, AgeRange, Battery, ButtonModel, CustomHearID, DualBattery,
EQConfiguration, Gender, HearID, SideTone, SoundMode, SoundcoreFeatureFlags,
StereoEQConfiguration, TouchTone, TwsStatus, WearDetection,
};

use crate::parsers::{
Expand Down Expand Up @@ -64,10 +65,10 @@ impl From<A3951StateResponse> for DeviceStateResponse {
side_tone: Some(value.side_tone),
hearid_eq_preset: value.hearid_eq_preset,
wear_detection: Some(value.wear_detection),
hear_id: Some(value.hear_id),
hear_id: Some(HearID::Custom(value.hear_id)),
age_range: Some(value.age_range),
touch_tone: Some(value.touch_tone),
eq: crate::models::EQConfiguration::Stereo(value.eq),
eq: EQConfiguration::Stereo(value.eq),
}
}
}
Expand Down

0 comments on commit 2079b1e

Please sign in to comment.