Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): add bounce effect #73

Merged
merged 1 commit into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions server/src/graphql/schema_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub(super) struct StaticLedEffectInput {
pub duration: Option<i32>,
#[graphql(description = "Name of the effect.")]
pub name: Option<String>,
#[graphql(description = "Hue/color (min 0.0, max 360.0)")]
#[graphql(description = "Hue/color (min 0, max 360)")]
pub hue: i32,
#[graphql(description = "Saturation (min 0.0, max 1.0)")]
pub saturation: f64,
Expand All @@ -44,7 +44,7 @@ pub(super) struct BreathingLedEffectInput {
pub duration: Option<i32>,
#[graphql(description = "Name of the effect.")]
pub name: Option<String>,
#[graphql(description = "Hue/color (min 0.0, max 360.0)")]
#[graphql(description = "Hue/color (min 0, max 360)")]
pub hue: i32,
#[graphql(description = "Saturation (min 0.0, max 1.0)")]
pub saturation: f64,
Expand Down Expand Up @@ -88,7 +88,7 @@ pub(super) struct BlinkLedEffectInput {
pub duration: Option<i32>,
#[graphql(description = "Name of the effect.")]
pub name: Option<String>,
#[graphql(description = "Hue/color (min 0.0, max 360.0)")]
#[graphql(description = "Hue/color (min 0, max 360)")]
pub hue: i32,
#[graphql(description = "Saturation (min 0.0, max 1.0)")]
pub saturation: f64,
Expand All @@ -101,14 +101,14 @@ pub(super) struct BlinkLedEffectInput {
#[derive(GraphQLInputObject, Debug)]
pub(super) struct CandleLedEffectInput {
#[graphql(
description = "If specified, must not be empty, and applies the effect only on these controller addresses."
description = "If specified, must not be empty, and applies the effect only on these controller addresses."
)]
pub controllers: Option<Vec<String>>,
#[graphql(description = "Duration of effect, in milliseconds, if specified.")]
pub duration: Option<i32>,
#[graphql(description = "Name of the effect.")]
pub name: Option<String>,
#[graphql(description = "Hue/color (min 0.0, max 360.0)")]
#[graphql(description = "Hue/color (min 0, max 360)")]
pub hue: i32,
#[graphql(description = "Saturation (min 0.0, max 1.0)")]
pub saturation: f64,
Expand All @@ -122,6 +122,26 @@ pub(super) struct CandleLedEffectInput {
pub interval: Option<i32>,
}

#[derive(GraphQLInputObject, Debug)]
pub(super) struct BounceLedEffectInput {
#[graphql(
description = "If specified, must not be empty, and applies the effect only on these controller addresses."
)]
pub controllers: Option<Vec<String>>,
#[graphql(description = "Duration of effect, in milliseconds, if specified.")]
pub duration: Option<i32>,
#[graphql(description = "Name of the effect.")]
pub name: Option<String>,
#[graphql(description = "Hue colors to bounce (each min 0, max 360)")]
pub hues: Vec<i32>,
#[graphql(description = "To Saturation (min 0.0, max 1.0)")]
pub saturation: f64,
#[graphql(description = "To value (min 0.0, max 1.0)")]
pub value: f64,
#[graphql(description = "Step ratio, percentage of change from one color to the other. (min 0.0=stay in from, max 1.0=stay in to)")]
pub step: f64
}

#[derive(GraphQLInputObject, Debug)]
pub(super) struct StaticRumbleEffectInput {
#[graphql(
Expand Down
49 changes: 48 additions & 1 deletion server/src/graphql/schema_mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ impl MutationRoot {
}

#[graphql(
description = "Randomly set brightness between min value and max value, simulating a candle/flame."
description = "Randomly set brightness between min value and max value, simulating a candle/flame."
)]
fn set_led_candle(ctx: &Context, input: CandleLedEffectInput) -> FieldResult<MutationResponse> {
tracing::info!(
Expand Down Expand Up @@ -363,6 +363,53 @@ impl MutationRoot {
)
}

#[graphql(
description = "Bounces from one color to the other."
)]
fn set_led_bounce(ctx: &Context, input: BounceLedEffectInput) -> FieldResult<MutationResponse> {
tracing::info!(
"Received led bounce effect ({})",
input
.name
.clone()
.map_or(String::from("unnamed"), |name| format!("'{name}'"))
);
tracing::debug!("Effect input: {input:?}");

if input.name.map_or(false, |name| name.is_empty()) {
return Err(FieldError::new("Name can't be empty!", Value::Null));
}

if !input.hues.iter().all(|hue| (0..=360).contains(hue)) {
return Err(FieldError::new(
"Hue must be between 0 and 360!",
Value::Null,
));
}

if !(0.0..=1.0).contains(&input.saturation) {
return Err(FieldError::new(
"Saturation must be between 0.0 and 1.0!",
Value::Null,
));
}

if !(0.0..=1.0).contains(&input.value) {
return Err(FieldError::new(
"Min value must between 0.0 and 1.0!",
Value::Null,
));
}

let effect = LedEffectKind::new_bounce(input.hues.iter().map(|hue| *hue as f32).collect(), input.saturation as f32, input.value as f32, input.step as f32);

process_led_effect_mutation(
ctx,
LedEffect::from(effect, input.duration),
input.controllers,
)
}

#[graphql(description = "Turn rumble off.")]
fn set_rumble_off(
ctx: &Context,
Expand Down
1 change: 1 addition & 0 deletions server/src/graphql/schema_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl QueryRoot {
api::LedEffectKind::Rainbow { .. } => { graphql::LedEffectType::Rainbow }
api::LedEffectKind::Blink { .. } => { graphql::LedEffectType::Blink }
api::LedEffectKind::Candle { .. } => { graphql::LedEffectType::Candle }
api::LedEffectKind::Bounce { .. } => { graphql::LedEffectType::Bounce }
},
current_rumble_effect: match ctl.rumble_effect.kind {
api::RumbleEffectKind::Off => { graphql::RumbleEffectType::Off }
Expand Down
1 change: 1 addition & 0 deletions server/src/graphql/schema_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(super) enum LedEffectType {
Rainbow,
Blink,
Candle,
Bounce,
}

#[derive(GraphQLEnum)]
Expand Down
11 changes: 4 additions & 7 deletions server/src/monitoring/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,10 @@ pub async fn metrics_handler() -> Result<impl Reply, Rejection> {
if let Err(e) = encoder.encode(&prometheus::gather(), &mut buffer) {
eprintln!("could not encode prometheus metrics: {}", e);
};
let result = match String::from_utf8(buffer.clone()) {
Ok(v) => v,
Err(e) => {
eprintln!("prometheus metrics could not be from_utf8'd: {}", e);
String::default()
}
};
let result = String::from_utf8(buffer.clone()).unwrap_or_else(|e| {
eprintln!("prometheus metrics could not be from_utf8'd: {}", e);
String::default()
});
buffer.clear();

Ok(result)
Expand Down
2 changes: 1 addition & 1 deletion server/src/ps_move/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl PsMoveApi {
}

if connection_type == ConnectionType::Usb {
usb_path = path.clone();
usb_path.clone_from(&path);
bt_address = if cfg!(windows) {
self.get_bt_address_on_windows(&path)
} else {
Expand Down
18 changes: 8 additions & 10 deletions server/src/ps_move/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ impl PsMoveController {
}

if self.connection_type == ConnectionType::Usb {
self.info.bt_path = other.info.bt_path.clone();
self.info.bt_path.clone_from(&other.info.bt_path);
} else if self.connection_type == ConnectionType::Bluetooth {
self.info.usb_path = other.info.usb_path.clone();
self.info.usb_path.clone_from(&other.info.usb_path);
}
self.connection_type = ConnectionType::UsbAndBluetooth;
}
Expand All @@ -94,10 +94,10 @@ impl PsMoveController {
}

pub fn revert_led_effect(&mut self) {
let current_effect = self.led_effect;
let current_effect = self.led_effect.clone();
let current_led = self.setting.led;

self.led_effect = self.last_led_effect;
self.led_effect = self.last_led_effect.clone();
self.setting.led = self.setting.last_led;

self.last_led_effect = current_effect;
Expand All @@ -110,22 +110,20 @@ impl PsMoveController {
info!("Last led effect '{}' of '{}' has already expired, setting to off", last_led_effect, self.bt_address);
let off_effect = LedEffect::off();

self.led_effect = off_effect;
self.setting.led = off_effect.kind.get_initial_hsv()
self.setting.led = off_effect.kind.get_initial_hsv();
self.led_effect = off_effect
}
}

info!("Reverted '{:?}' to '{}'", self.bt_address, self.led_effect);
}

pub fn set_led_effect(&mut self, effect: LedEffect) {
self.last_led_effect = self.led_effect;
self.last_led_effect = self.led_effect.clone();
self.setting.last_led = self.setting.led;

let kind = effect.kind;

self.setting.led = effect.kind.get_initial_hsv();
self.led_effect = effect;
self.setting.led = kind.get_initial_hsv();
}

pub fn set_led_effect_with_hsv(&mut self, effect: LedEffect, hsv: Hsv) {
Expand Down
Loading
Loading