v0.15.0
This commit is contained in:
1 parent
32f8a32bd2
commit
df10ead47e
38 files changed
+655
-210
No files matched your search
+74
-10
@@ -89,6 +89,41 @@ fn default_temperature_step() -> f64 {
|
||||
1.0
|
||||
}
|
||||
|
||||
pub const VERTICAL_SWING_MAX: u8 = 11;
|
||||
pub const HORIZONTAL_SWING_MAX: u8 = 6;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum LouverPositionCompat {
|
||||
Bool(bool),
|
||||
Number(u8),
|
||||
}
|
||||
|
||||
fn louver_position_compat(value: LouverPositionCompat) -> u8 {
|
||||
match value {
|
||||
LouverPositionCompat::Bool(value) => u8::from(value),
|
||||
LouverPositionCompat::Number(value) => value,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_louver_position<'de, D>(deserializer: D) -> Result<u8, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(louver_position_compat(LouverPositionCompat::deserialize(
|
||||
deserializer,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn deserialize_optional_louver_position<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<u8>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(Option::<LouverPositionCompat>::deserialize(deserializer)?.map(louver_position_compat))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum EnergySourcePreference {
|
||||
@@ -176,10 +211,12 @@ pub struct Device {
|
||||
pub target_temperature: f64,
|
||||
#[serde(default = "default_fan")]
|
||||
pub fan_speed: u8,
|
||||
#[serde(default)]
|
||||
pub swing_vertical: bool,
|
||||
#[serde(default)]
|
||||
pub swing_horizontal: bool,
|
||||
/// Raw GREE `SwUpDn` louver position. 0=off/default, 1=full swing, 2..6=fixed positions, 7..11=partial swing ranges.
|
||||
#[serde(default, deserialize_with = "deserialize_louver_position")]
|
||||
pub swing_vertical: u8,
|
||||
/// Raw GREE `SwingLfRig` louver position. 0=off/default, 1=full swing, 2..6=fixed positions.
|
||||
#[serde(default, deserialize_with = "deserialize_louver_position")]
|
||||
pub swing_horizontal: u8,
|
||||
#[serde(default)]
|
||||
pub quiet: bool,
|
||||
/// Raw non-zero value last reported by the unit for the GREE `Quiet` property.
|
||||
@@ -290,8 +327,8 @@ impl Device {
|
||||
mode: "cool".into(),
|
||||
target_temperature: 23.0,
|
||||
fan_speed: 0,
|
||||
swing_vertical: false,
|
||||
swing_horizontal: false,
|
||||
swing_vertical: 0,
|
||||
swing_horizontal: 0,
|
||||
quiet: false,
|
||||
quiet_wire_value: None,
|
||||
turbo: false,
|
||||
@@ -389,8 +426,12 @@ pub struct DeviceCommand {
|
||||
pub mode: Option<String>,
|
||||
pub target_temperature: Option<f64>,
|
||||
pub fan_speed: Option<u8>,
|
||||
pub swing_vertical: Option<bool>,
|
||||
pub swing_horizontal: Option<bool>,
|
||||
/// Raw GREE `SwUpDn` value. Legacy boolean payloads remain accepted (`false`=0, `true`=1).
|
||||
#[serde(default, deserialize_with = "deserialize_optional_louver_position")]
|
||||
pub swing_vertical: Option<u8>,
|
||||
/// Raw GREE `SwingLfRig` value. Legacy boolean payloads remain accepted (`false`=0, `true`=1).
|
||||
#[serde(default, deserialize_with = "deserialize_optional_louver_position")]
|
||||
pub swing_horizontal: Option<u8>,
|
||||
pub quiet: Option<bool>,
|
||||
pub turbo: Option<bool>,
|
||||
pub light: Option<bool>,
|
||||
@@ -476,10 +517,10 @@ impl DeviceCommand {
|
||||
device.fan_speed = v.min(5);
|
||||
}
|
||||
if let Some(v) = self.swing_vertical {
|
||||
device.swing_vertical = v;
|
||||
device.swing_vertical = v.min(VERTICAL_SWING_MAX);
|
||||
}
|
||||
if let Some(v) = self.swing_horizontal {
|
||||
device.swing_horizontal = v;
|
||||
device.swing_horizontal = v.min(HORIZONTAL_SWING_MAX);
|
||||
}
|
||||
if let Some(v) = self.quiet {
|
||||
device.quiet = v;
|
||||
@@ -544,4 +585,27 @@ mod connection_type_tests {
|
||||
let migrated: Device = serde_json::from_value(value).expect("deserialize legacy device");
|
||||
assert_eq!(migrated.connection_type, ConnectionType::Local);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_boolean_swing_values_migrate_to_positions() {
|
||||
let device = Device::simulated_default();
|
||||
let mut value = serde_json::to_value(device).expect("serialize device");
|
||||
let object = value.as_object_mut().expect("device object");
|
||||
object.insert("swing_vertical".into(), serde_json::Value::Bool(true));
|
||||
object.insert("swing_horizontal".into(), serde_json::Value::Bool(false));
|
||||
let migrated: Device = serde_json::from_value(value).expect("deserialize legacy device");
|
||||
assert_eq!(migrated.swing_vertical, 1);
|
||||
assert_eq!(migrated.swing_horizontal, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_boolean_swing_command_is_accepted() {
|
||||
let command: DeviceCommand = serde_json::from_value(serde_json::json!({
|
||||
"swing_vertical": true,
|
||||
"swing_horizontal": false
|
||||
}))
|
||||
.expect("deserialize legacy command");
|
||||
assert_eq!(command.swing_vertical, Some(1));
|
||||
assert_eq!(command.swing_horizontal, Some(0));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user