Skip to main content

homeassistant_agent/connector/
client.rs

1use crate::model::{DeviceId, Discovery};
2use rumqttc::{AsyncClient, QoS};
3
4#[derive(Debug, thiserror::Error)]
5pub enum ClientError {
6    #[error("serialization failure")]
7    Serialization(#[from] serde_json::Error),
8    #[error("client error")]
9    Client(#[from] rumqttc::ClientError),
10}
11
12#[derive(Clone)]
13pub struct Client {
14    pub mqtt: AsyncClient,
15
16    pub(crate) base_topic: String,
17}
18
19impl Client {
20    pub async fn update_state(
21        &self,
22        topic: impl Into<String>,
23        payload: impl Into<Vec<u8>>,
24    ) -> Result<(), ClientError> {
25        let topic = topic.into();
26        log::info!("Update state on {topic}");
27
28        self.mqtt
29            .try_publish(topic, QoS::AtLeastOnce, false, payload.into())
30            .inspect_err(|err| {
31                log::warn!("failed to publish state: {err}");
32            })?;
33
34        Ok(())
35    }
36
37    pub async fn announce(&self, id: &DeviceId, discovery: &Discovery) -> Result<(), ClientError> {
38        let topic = format!("{}/{}", self.base_topic, id.config_topic());
39        log::info!("announce {id} on {topic}: {discovery:?}", id = id.id);
40
41        self.mqtt
42            .publish(
43                topic,
44                QoS::AtLeastOnce,
45                false,
46                serde_json::to_vec(discovery)?,
47            )
48            .await?;
49
50        Ok(())
51    }
52
53    pub async fn subscribe(&self, topic: impl Into<String>, qos: QoS) -> Result<(), ClientError> {
54        let topic = topic.into();
55        log::info!("Subscribing to: {topic}");
56        self.mqtt.subscribe(topic, qos).await?;
57
58        Ok(())
59    }
60}