1use crate::device;
2use serde::Deserialize;
3use serde::Serialize;
4
5pub mod request {
7 use super::*;
8
9 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
11 #[serde(rename_all = "camelCase")]
12 pub struct Payload {}
13}
14
15pub mod response {
17 use super::*;
18
19 #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
21 #[serde(rename_all = "camelCase")]
22 pub struct Response {
23 pub request_id: String,
24 pub payload: Payload,
25 }
26
27 #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
29 #[serde(rename_all = "camelCase")]
30 pub struct Payload {
31 pub agent_user_id: String,
33 #[serde(skip_serializing_if = "Option::is_none")]
36 pub error_code: Option<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub debug_string: Option<String>,
40 pub devices: Vec<PayloadDevice>,
42 }
43
44 #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
46 #[serde(rename_all = "camelCase")]
47 pub struct PayloadDevice {
48 pub id: String,
53 #[serde(rename = "type")]
55 pub device_type: device::Type,
56 pub traits: Vec<device::Trait>,
58 pub name: PayloadDeviceName,
60 pub will_report_state: bool,
63 #[serde(default)]
65 pub notification_supported_by_agent: bool,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub room_hint: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub device_info: Option<PayloadDeviceInfo>,
72 #[serde(default)]
74 pub attributes: Attributes,
75 #[serde(default, skip_serializing_if = "Option::is_none")]
77 pub custom_data: Option<serde_json::Map<String, serde_json::Value>>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub other_device_ids: Option<Vec<PayloadOtherDeviceID>>,
81 }
82
83 #[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
84 #[serde(rename_all = "camelCase")]
85 pub struct Attributes {
86 #[serde(skip_serializing_if = "Option::is_none")]
88 pub color_model: Option<ColorModel>,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub color_temperature_range: Option<ColorTemperatureRange>,
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub command_only_color_setting: Option<bool>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
96 pub available_thermostat_modes: Option<Vec<String>>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub buffer_range_celsius: Option<f64>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub command_only_temperature_setting: Option<bool>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub query_only_temperature_setting: Option<bool>,
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub thermostat_temperature_range: Option<ThermostatTemperatureRange>,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub thermostat_temperature_unit: Option<ThermostatTemperatureUnit>,
107 }
108
109 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
110 #[serde(rename_all = "camelCase")]
111 pub struct ColorTemperatureRange {
112 pub temperature_min_k: u64,
113 pub temperature_max_k: u64,
114 }
115
116 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
117 #[serde(rename_all = "camelCase")]
118 pub enum ColorModel {
119 Rgb,
120 Hsv,
121 }
122
123 #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
124 #[serde(rename_all = "camelCase")]
125 pub struct ThermostatTemperatureRange {
126 pub min_threshold_celsius: f64,
127 pub max_threshold_celcius: f64,
128 }
129
130 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
131 pub enum ThermostatTemperatureUnit {
132 C,
133 F,
134 }
135
136 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
137 #[serde(rename_all = "camelCase")]
138 pub struct PayloadDeviceName {
139 #[serde(skip_serializing_if = "Option::is_none")]
141 pub default_names: Option<Vec<String>>,
142 pub name: String,
145 #[serde(skip_serializing_if = "Option::is_none")]
147 pub nicknames: Option<Vec<String>>,
148 }
149
150 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
151 #[serde(rename_all = "camelCase")]
152 pub struct PayloadDeviceInfo {
153 #[serde(skip_serializing_if = "Option::is_none")]
156 pub manufacturer: Option<String>,
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub model: Option<String>,
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub hw_version: Option<String>,
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub sw_version: Option<String>,
166 }
167
168 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
169 #[serde(rename_all = "camelCase")]
170 pub struct PayloadOtherDeviceID {
171 #[serde(skip_serializing_if = "Option::is_none")]
173 pub agent_id: Option<String>,
174 pub device_id: String,
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182
183 use serde_json::json;
184
185 #[test]
186 fn color_setting_attributes() {
187 let attributes = response::Attributes {
188 color_model: Some(response::ColorModel::Rgb),
189 command_only_color_setting: Some(true),
190 ..Default::default()
191 };
192 assert_eq!(
193 serde_json::to_string(&attributes).unwrap(),
194 json!({"colorModel": "rgb", "commandOnlyColorSetting": true}).to_string()
195 );
196 }
197}