embassy_ha/
entity_switch.rs1use crate::{
2 BinaryState, CommandPolicy, Entity, EntityCommonConfig, EntityConfig, SwitchCommand,
3 SwitchState, constants,
4};
5
6#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
7pub enum SwitchClass {
8 #[default]
9 Generic,
10 Outlet,
11 Switch,
12}
13
14#[derive(Debug, Default)]
18pub struct SwitchConfig {
19 pub common: EntityCommonConfig,
20 pub class: SwitchClass,
21 pub command_policy: CommandPolicy,
22}
23
24impl SwitchConfig {
25 pub(crate) fn populate(&self, config: &mut EntityConfig) {
26 self.common.populate(config);
27 config.domain = constants::HA_DOMAIN_SWITCH;
28 config.device_class = match self.class {
29 SwitchClass::Generic => None,
30 SwitchClass::Outlet => Some(constants::HA_DEVICE_CLASS_SWITCH_OUTLET),
31 SwitchClass::Switch => Some(constants::HA_DEVICE_CLASS_SWITCH_SWITCH),
32 };
33 }
34}
35
36pub struct Switch<'a>(Entity<'a>);
37
38impl<'a> Switch<'a> {
39 pub(crate) fn new(entity: Entity<'a>) -> Self {
40 Self(entity)
41 }
42
43 pub fn state(&self) -> Option<BinaryState> {
44 self.0.with_data(|data| {
45 let storage = data.storage.as_switch_mut();
46 storage.state.as_ref().map(|s| s.value)
47 })
48 }
49
50 pub fn command(&self) -> Option<BinaryState> {
51 self.0.with_data(|data| {
52 let storage = data.storage.as_switch_mut();
53 storage.command.as_ref().map(|s| s.value)
54 })
55 }
56
57 pub fn toggle(&mut self) -> BinaryState {
58 let new_state = self.state().unwrap_or(BinaryState::Off).flip();
59 self.set(new_state);
60 new_state
61 }
62
63 pub fn set(&mut self, state: BinaryState) {
64 let publish = self.0.with_data(|data| {
65 let storage = data.storage.as_switch_mut();
66 let timestamp = embassy_time::Instant::now();
67 let publish = match &storage.command {
68 Some(command) => command.value != state,
69 None => true,
70 };
71 storage.state = Some(SwitchState {
72 value: state,
73 timestamp,
74 });
75 storage.command = Some(SwitchCommand {
76 value: state,
77 timestamp,
78 });
79 publish
80 });
81 if publish {
82 self.0.queue_publish();
83 }
84 }
85
86 pub async fn wait(&mut self) -> BinaryState {
87 loop {
88 self.0.wait_command().await;
89 if let Some(state) = self.command() {
90 return state;
91 }
92 }
93 }
94}