homeassistant_agent/connector/
client.rs1use 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}