use crate::{
api::HueAPIError,
command::{
merge_commands, BasicCommand, GeofenceClientCommand, GeolocationCommand, MotionCommand,
},
service::{Bridge, ResourceIdentifier, ResourceType, SetStatus},
};
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct Contact<'a> {
bridge: &'a Bridge,
data: ContactData,
}
impl<'a> Contact<'a> {
pub fn new(bridge: &'a Bridge, data: ContactData) -> Self {
Contact { bridge, data }
}
pub fn data(&self) -> &ContactData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
pub async fn send(
&self,
commands: &[BasicCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_contact(self.id(), &payload).await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct ContactData {
pub id: String,
pub id_v1: Option<String>,
pub owner: ResourceIdentifier,
pub enabled: bool,
pub contact_report: Option<ContactReport>,
}
impl ContactData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::Contact,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct ContactReport {
pub changed: String,
pub state: ContactStatus,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum ContactStatus {
Contact,
NoContact,
}
#[derive(Debug)]
pub struct Motion<'a> {
bridge: &'a Bridge,
data: MotionData,
}
impl<'a> Motion<'a> {
pub fn new(bridge: &'a Bridge, data: MotionData) -> Self {
Motion { bridge, data }
}
pub fn data(&self) -> &MotionData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id().to_owned(),
rtype: ResourceType::Motion,
}
}
pub async fn send(
&self,
commands: &[MotionCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_motion(self.id(), &payload).await
}
}
#[derive(Debug)]
pub struct CameraMotion<'a> {
bridge: &'a Bridge,
data: MotionData,
}
impl<'a> CameraMotion<'a> {
pub fn new(bridge: &'a Bridge, data: MotionData) -> Self {
CameraMotion { bridge, data }
}
pub fn data(&self) -> &MotionData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id().to_owned(),
rtype: ResourceType::CameraMotion,
}
}
pub async fn send(
&self,
commands: &[MotionCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_camera_motion(self.id(), &payload).await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct MotionData {
pub id: String,
pub id_v1: Option<String>,
pub owner: ResourceIdentifier,
pub enabled: bool,
pub motion: MotionState,
pub sensitivity: Option<Sensitivity>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct MotionState {
#[deprecated]
pub motion_valid: bool,
pub motion_report: Option<MotionReport>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct MotionReport {
pub changed: String,
pub motion: bool,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Sensitivity {
pub status: SetStatus,
pub sensitivity: usize,
pub sensitivity_max: Option<usize>,
}
#[derive(Debug)]
pub struct Temperature<'a> {
bridge: &'a Bridge,
data: TemperatureData,
}
impl<'a> Temperature<'a> {
pub fn new(bridge: &'a Bridge, data: TemperatureData) -> Self {
Temperature { bridge, data }
}
pub fn data(&self) -> &TemperatureData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
pub async fn send(
&self,
commands: &[BasicCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_temperature(self.id(), &payload).await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct TemperatureData {
pub id: String,
pub id_v1: Option<String>,
pub owner: ResourceIdentifier,
pub enabled: bool,
pub temperature: TemperatureState,
}
impl TemperatureData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::Temperature,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct TemperatureState {
#[deprecated]
pub temperature: f32,
#[deprecated]
pub temperature_valid: bool,
pub temperature_report: Option<TemperatureReport>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct TemperatureReport {
pub changed: String,
pub temperature: f32,
}
#[derive(Debug)]
pub struct LightLevel<'a> {
bridge: &'a Bridge,
data: LightLevelData,
}
impl<'a> LightLevel<'a> {
pub fn new(bridge: &'a Bridge, data: LightLevelData) -> Self {
LightLevel { bridge, data }
}
pub fn data(&self) -> &LightLevelData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
pub async fn send(
&self,
commands: &[BasicCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_light_level(self.id(), &payload).await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct LightLevelData {
pub id: String,
pub id_v1: Option<String>,
pub owner: ResourceIdentifier,
pub enabled: bool,
pub light: LightLevelState,
}
impl LightLevelData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::LightLevel,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct LightLevelState {
#[deprecated]
pub light_level: usize,
#[deprecated]
pub light_level_valid: bool,
pub light_level_report: Option<LightLevelReport>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct LightLevelReport {
pub changed: String,
pub light_level: usize,
}
#[derive(Debug)]
pub struct Geolocation<'a> {
bridge: &'a Bridge,
data: GeolocationData,
}
impl<'a> Geolocation<'a> {
pub fn new(bridge: &'a Bridge, data: GeolocationData) -> Self {
Geolocation { bridge, data }
}
pub fn data(&self) -> &GeolocationData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
pub async fn send(
&self,
commands: &[GeolocationCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge.api.put_geolocation(self.id(), &payload).await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct GeolocationData {
pub id: String,
pub id_v1: Option<String>,
pub is_configured: bool,
pub sun_today: Option<SunToday>,
}
impl GeolocationData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::Geolocation,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct SunToday {
pub sunset_time: String,
pub day_type: DayType,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DayType {
NormalDay,
PolarDay,
PolarNight,
#[serde(other)]
Unknown,
}
#[derive(Debug)]
pub struct GeofenceClient<'a> {
bridge: &'a Bridge,
data: GeofenceClientData,
}
impl<'a> GeofenceClient<'a> {
pub fn new(bridge: &'a Bridge, data: GeofenceClientData) -> Self {
GeofenceClient { bridge, data }
}
pub fn data(&self) -> &GeofenceClientData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
pub fn builder(name: impl Into<String>) -> GeofenceClientBuilder {
GeofenceClientBuilder::new(name)
}
pub async fn send(
&self,
commands: &[GeofenceClientCommand],
) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
let payload = merge_commands(commands);
self.bridge
.api
.put_geofence_client(self.id(), &payload)
.await
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct GeofenceClientData {
pub id: String,
pub id_v1: Option<String>,
pub name: String,
}
impl GeofenceClientData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::GeofenceClient,
}
}
}
#[derive(Serialize)]
pub struct GeofenceClientBuilder {
is_at_home: bool,
name: String,
}
impl GeofenceClientBuilder {
pub fn new(name: impl Into<String>) -> Self {
GeofenceClientBuilder {
is_at_home: true,
name: name.into(),
}
}
pub fn is_at_home(mut self, b: bool) -> Self {
self.is_at_home = b;
self
}
}
#[derive(Debug)]
pub struct Tamper {
data: TamperData,
}
impl Tamper {
pub fn new(data: TamperData) -> Self {
Tamper { data }
}
pub fn data(&self) -> &TamperData {
&self.data
}
pub fn id(&self) -> &str {
&self.data.id
}
pub fn rid(&self) -> ResourceIdentifier {
self.data.rid()
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct TamperData {
pub id: String,
pub id_v1: Option<String>,
pub owner: ResourceIdentifier,
pub tamper_reports: Vec<TamperReport>,
}
impl TamperData {
pub fn rid(&self) -> ResourceIdentifier {
ResourceIdentifier {
rid: self.id.to_owned(),
rtype: ResourceType::Tamper,
}
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct TamperReport {
pub changed: String,
pub source: String,
pub state: TamperStatus,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum TamperStatus {
Tampered,
NotTampered,
}