Skip to content

Commit a8ab756

Browse files
committed
Merge branch 'chrivers/device-update' into dev
2 parents 9a3f825 + ba95a9b commit a8ab756

File tree

12 files changed

+312
-46
lines changed

12 files changed

+312
-46
lines changed

src/hue/api/device.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use std::ops::{AddAssign, Sub};
2+
13
use serde::{Deserialize, Serialize};
24

3-
use crate::hue::api::{Metadata, RType, ResourceLink, Stub};
5+
use crate::hue::api::{Metadata, MetadataUpdate, RType, ResourceLink, Stub};
46
use crate::hue::version::SwVersion;
57
use crate::hue::HUE_BRIDGE_V2_MODEL_ID;
68
use crate::z2m;
@@ -16,6 +18,12 @@ pub struct Device {
1618
pub identify: Option<Stub>,
1719
}
1820

21+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
22+
pub struct DeviceUpdate {
23+
#[serde(skip_serializing_if = "Option::is_none")]
24+
pub metadata: Option<MetadataUpdate>,
25+
}
26+
1927
impl Device {
2028
#[must_use]
2129
pub fn light_service(&self) -> Option<&ResourceLink> {
@@ -86,6 +94,62 @@ impl DeviceProductData {
8694
}
8795
}
8896

97+
impl DeviceUpdate {
98+
#[must_use]
99+
pub fn new() -> Self {
100+
Self::default()
101+
}
102+
103+
#[must_use]
104+
pub fn with_metadata(self, metadata: Metadata) -> Self {
105+
Self {
106+
metadata: Some(MetadataUpdate {
107+
archetype: Some(metadata.archetype),
108+
name: Some(metadata.name),
109+
}),
110+
}
111+
}
112+
}
113+
114+
impl AddAssign<DeviceUpdate> for Device {
115+
fn add_assign(&mut self, upd: DeviceUpdate) {
116+
if let Some(md) = upd.metadata {
117+
if let Some(name) = md.name {
118+
self.metadata.name = name;
119+
}
120+
if let Some(archetype) = md.archetype {
121+
self.metadata.archetype = archetype;
122+
}
123+
}
124+
}
125+
}
126+
127+
#[allow(clippy::if_not_else)]
128+
impl Sub<&Device> for &Device {
129+
type Output = DeviceUpdate;
130+
131+
fn sub(self, rhs: &Device) -> Self::Output {
132+
let mut upd = Self::Output::default();
133+
134+
if self.metadata != rhs.metadata {
135+
upd.metadata = Some(MetadataUpdate {
136+
name: if self.metadata.name != rhs.metadata.name {
137+
Some(rhs.metadata.name.clone())
138+
} else {
139+
None
140+
},
141+
archetype: if self.metadata.archetype != rhs.metadata.archetype {
142+
Some(rhs.metadata.archetype.clone())
143+
} else {
144+
None
145+
},
146+
});
147+
}
148+
149+
upd
150+
}
151+
}
152+
89153
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
90154
#[serde(rename_all = "snake_case")]
91155
pub enum DeviceArchetype {

src/hue/api/light.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ops::{AddAssign, Sub};
44
use serde::{Deserialize, Serialize};
55
use serde_json::Value;
66

7-
use crate::hue::api::{DeviceArchetype, Identify, Metadata, ResourceLink, Stub};
7+
use crate::hue::api::{DeviceArchetype, Identify, Metadata, MetadataUpdate, ResourceLink, Stub};
88
use crate::model::types::XY;
99
use crate::z2m::api::Expose;
1010

@@ -45,15 +45,15 @@ pub struct Light {
4545
pub signaling: Option<LightSignaling>,
4646
}
4747

48-
#[derive(Debug, Serialize, Deserialize, Clone)]
48+
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
4949
#[serde(rename_all = "snake_case")]
5050
pub enum LightFunction {
5151
Functional,
5252
Decorative,
5353
Mixed,
5454
}
5555

56-
#[derive(Debug, Serialize, Deserialize, Clone)]
56+
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
5757
pub struct LightMetadata {
5858
pub name: String,
5959
pub archetype: DeviceArchetype,
@@ -136,7 +136,16 @@ impl Light {
136136

137137
impl AddAssign<LightUpdate> for Light {
138138
fn add_assign(&mut self, upd: LightUpdate) {
139-
if let Some(state) = &upd.on {
139+
if let Some(md) = upd.metadata {
140+
if let Some(name) = md.name {
141+
self.metadata.name = name;
142+
}
143+
if let Some(archetype) = md.archetype {
144+
self.metadata.archetype = archetype;
145+
}
146+
}
147+
148+
if let Some(state) = upd.on {
140149
self.on.on = state.on;
141150
}
142151

@@ -161,16 +170,27 @@ impl AddAssign<LightUpdate> for Light {
161170
}
162171
}
163172

173+
#[allow(clippy::if_not_else)]
164174
impl Sub<&Light> for &Light {
165175
type Output = LightUpdate;
166176

167177
fn sub(self, rhs: &Light) -> Self::Output {
168-
let mut upd = Self::Output {
169-
on: None,
170-
dimming: None,
171-
color: None,
172-
color_temperature: None,
173-
};
178+
let mut upd = Self::Output::default();
179+
180+
if self.metadata != rhs.metadata {
181+
upd.metadata = Some(MetadataUpdate {
182+
name: if self.metadata.name != rhs.metadata.name {
183+
Some(rhs.metadata.name.clone())
184+
} else {
185+
None
186+
},
187+
archetype: if self.metadata.archetype != rhs.metadata.archetype {
188+
Some(rhs.metadata.archetype.clone())
189+
} else {
190+
None
191+
},
192+
});
193+
}
174194

175195
if self.on != rhs.on {
176196
upd.on = Some(rhs.on);
@@ -346,6 +366,8 @@ pub struct LightTimedEffects {
346366

347367
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
348368
pub struct LightUpdate {
369+
#[serde(skip_serializing_if = "Option::is_none")]
370+
pub metadata: Option<MetadataUpdate>,
349371
#[serde(skip_serializing_if = "Option::is_none")]
350372
pub on: Option<On>,
351373
#[serde(skip_serializing_if = "Option::is_none")]

src/hue/api/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ mod scene;
77
mod stubs;
88
mod update;
99

10-
pub use device::{Device, DeviceArchetype, DeviceProductData, Identify};
10+
pub use device::{Device, DeviceArchetype, DeviceProductData, DeviceUpdate, Identify};
11+
1112
pub use grouped_light::{GroupedLight, GroupedLightUpdate};
1213
pub use light::{
1314
ColorGamut, ColorTemperature, ColorTemperatureUpdate, ColorUpdate, Delta, Dimming,
1415
DimmingUpdate, GamutType, Light, LightColor, LightMetadata, LightUpdate, MirekSchema, On,
1516
};
1617
pub use resource::{RType, ResourceLink, ResourceRecord};
17-
pub use room::{Room, RoomArchetype, RoomMetadata};
18+
pub use room::{Room, RoomArchetype, RoomMetadata, RoomMetadataUpdate, RoomUpdate};
1819
pub use scene::{
1920
Scene, SceneAction, SceneActionElement, SceneMetadata, SceneRecall, SceneStatus,
2021
SceneStatusUpdate, SceneUpdate,
@@ -24,8 +25,9 @@ pub use stubs::{
2425
ButtonData, ButtonMetadata, ButtonReport, DevicePower, DeviceSoftwareUpdate, DollarRef,
2526
Entertainment, EntertainmentConfiguration, EntertainmentSegment, EntertainmentSegments,
2627
GeofenceClient, Geolocation, GroupedLightLevel, GroupedMotion, Homekit, LightLevel, Matter,
27-
Metadata, Motion, PrivateGroup, PublicImage, RelativeRotary, SmartScene, Taurus, Temperature,
28-
TimeZone, ZigbeeConnectivity, ZigbeeConnectivityStatus, ZigbeeDeviceDiscovery, Zone,
28+
Metadata, MetadataUpdate, Motion, PrivateGroup, PublicImage, RelativeRotary, SmartScene,
29+
Taurus, Temperature, TimeZone, ZigbeeConnectivity, ZigbeeConnectivityStatus,
30+
ZigbeeDeviceDiscovery, Zone,
2931
};
3032
pub use update::{Update, UpdateRecord};
3133

src/hue/api/room.rs

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
1+
use std::ops::{AddAssign, Sub};
2+
13
use serde::{Deserialize, Serialize};
24

35
use crate::hue::api::{RType, ResourceLink};
46

5-
#[derive(Debug, Serialize, Deserialize, Clone)]
7+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
68
pub struct RoomMetadata {
79
pub name: String,
810
pub archetype: RoomArchetype,
911
}
1012

11-
#[derive(Debug, Serialize, Deserialize, Clone)]
13+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
14+
pub struct RoomMetadataUpdate {
15+
pub name: Option<String>,
16+
pub archetype: Option<RoomArchetype>,
17+
}
18+
19+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
1220
pub struct Room {
1321
pub children: Vec<ResourceLink>,
1422
pub metadata: RoomMetadata,
1523
#[serde(default)]
1624
pub services: Vec<ResourceLink>,
1725
}
1826

27+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
28+
pub struct RoomUpdate {
29+
pub children: Option<Vec<ResourceLink>>,
30+
pub metadata: Option<RoomMetadataUpdate>,
31+
}
32+
1933
impl Room {
2034
#[must_use]
2135
pub fn grouped_light_service(&self) -> Option<&ResourceLink> {
@@ -25,7 +39,25 @@ impl Room {
2539
}
2640
}
2741

28-
#[derive(Copy, Debug, Serialize, Deserialize, Clone)]
42+
impl RoomUpdate {
43+
#[must_use]
44+
pub fn new() -> Self {
45+
Self::default()
46+
}
47+
48+
#[must_use]
49+
pub fn with_metadata(self, metadata: RoomMetadata) -> Self {
50+
Self {
51+
metadata: Some(RoomMetadataUpdate {
52+
name: Some(metadata.name),
53+
archetype: Some(metadata.archetype),
54+
}),
55+
..self
56+
}
57+
}
58+
}
59+
60+
#[derive(Copy, Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
2961
#[serde(rename_all = "snake_case")]
3062
pub enum RoomArchetype {
3163
LivingRoom,
@@ -79,3 +111,54 @@ impl RoomMetadata {
79111
}
80112
}
81113
}
114+
115+
impl AddAssign<RoomMetadataUpdate> for RoomMetadata {
116+
fn add_assign(&mut self, upd: RoomMetadataUpdate) {
117+
if let Some(name) = upd.name {
118+
self.name = name;
119+
}
120+
if let Some(archetype) = upd.archetype {
121+
self.archetype = archetype;
122+
}
123+
}
124+
}
125+
126+
#[allow(clippy::if_not_else)]
127+
impl Sub<&RoomMetadata> for &RoomMetadata {
128+
type Output = RoomMetadataUpdate;
129+
130+
fn sub(self, rhs: &RoomMetadata) -> Self::Output {
131+
let mut upd = Self::Output::default();
132+
133+
if self != rhs {
134+
if self.name != rhs.name {
135+
upd.name = Some(rhs.name.clone());
136+
}
137+
if self.archetype != rhs.archetype {
138+
upd.archetype = Some(rhs.archetype);
139+
}
140+
}
141+
142+
upd
143+
}
144+
}
145+
146+
#[allow(clippy::if_not_else)]
147+
impl Sub<&Room> for &Room {
148+
type Output = RoomUpdate;
149+
150+
fn sub(self, rhs: &Room) -> Self::Output {
151+
let mut upd = Self::Output::default();
152+
153+
if self != rhs {
154+
if self.children != rhs.children {
155+
upd.children = Some(rhs.children.clone());
156+
}
157+
if self.metadata != rhs.metadata {
158+
upd.metadata = Some(&self.metadata - &rhs.metadata);
159+
}
160+
}
161+
162+
upd
163+
}
164+
}

0 commit comments

Comments
 (0)