Files
PlantCtrl/rust/src/mcutie_3_0_0/homeassistant/ser.rs
Empire Phoenix e05f3d768f Add mcutie MQTT client implementation and improve library structure
- Integrated `mcutie` library as a core MQTT client for device communication.
- Added support for Home Assistant entities (binary sensor, button) via MQTT.
- Implemented buffer management, async operations, and packet encoding/decoding.
- Introduced structured error handling and device registration features.
- Updated `Cargo.toml` with new dependencies and enabled feature flags for `serde` and `log`.
- Enhanced logging macros with configurable options (`defmt` or `log`).
- Organized codebase into modules (buffer, components, IO, publish, etc.) for better maintainability.

fix legacy dependecencies and compatiblity with mcutie vendored lib

fix shit i hate this
2026-05-04 01:48:22 +02:00

334 lines
8.8 KiB
Rust

use core::ops::Deref;
use serde::{
ser::{SerializeSeq, SerializeStruct},
Serialize, Serializer,
};
use crate::{
homeassistant::{AvailabilityTopics, Component, Entity},
Topic,
};
#[derive(Serialize)]
pub(super) struct AvailabilityTopicItem<'a> {
topic: Topic<&'a str>,
}
struct AvailabilityTopicList<'a, T: Deref<Target = str>, const N: usize> {
list: &'a [Topic<T>; N],
}
impl<'a, const N: usize, T: Deref<Target = str>> AvailabilityTopicList<'a, T, N> {
pub(super) fn new(list: &'a [Topic<T>; N]) -> Self {
Self { list }
}
}
impl<T: Deref<Target = str>, const N: usize> Serialize for AvailabilityTopicList<'_, T, N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut serializer = serializer.serialize_seq(Some(N))?;
for topic in self.list {
serializer.serialize_element(&AvailabilityTopicItem {
topic: topic.as_ref(),
})?;
}
serializer.end()
}
}
pub(super) struct List<'a, T: Serialize, const N: usize> {
list: &'a [T; N],
}
impl<'a, T: Serialize, const N: usize> List<'a, T, N> {
pub(super) fn new(list: &'a [T; N]) -> Self {
Self { list }
}
}
impl<T: Serialize, const N: usize> Serialize for List<'_, T, N> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut serializer = serializer.serialize_seq(Some(N))?;
for item in self.list {
serializer.serialize_element(item)?;
}
serializer.end()
}
}
pub(super) struct DiscoverySerializer<'a, const A: usize, C: Component, S: Serializer> {
pub(super) discovery: &'a Entity<'a, A, C>,
pub(super) inner: S,
}
impl<const A: usize, C: Component, S: Serializer> Serializer for DiscoverySerializer<'_, A, C, S> {
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = S::SerializeSeq;
type SerializeTuple = S::SerializeTuple;
type SerializeTupleStruct = S::SerializeTupleStruct;
type SerializeTupleVariant = S::SerializeTupleVariant;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
type SerializeStructVariant = S::SerializeStructVariant;
fn serialize_struct(
self,
name: &'static str,
mut len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
len += 5;
if self.discovery.state_topic.is_some() {
len += 1;
}
if self.discovery.command_topic.is_some() {
len += 1;
}
if self.discovery.unique_id.is_some() {
len += 1;
}
if !matches!(self.discovery.availability, AvailabilityTopics::None) {
len += 2;
}
let mut serializer = self.inner.serialize_struct(name, len)?;
serializer.serialize_field("dev", &self.discovery.device)?;
serializer.serialize_field("o", &self.discovery.origin)?;
serializer.serialize_field("p", C::platform())?;
serializer.serialize_field("obj_id", self.discovery.object_id)?;
serializer.serialize_field("name", self.discovery.name)?;
if let Some(t) = self.discovery.state_topic {
serializer.serialize_field("stat_t", &t)?;
} else {
serializer.skip_field("stat_t")?;
}
if let Some(t) = self.discovery.command_topic {
serializer.serialize_field("cmd_t", &t)?;
} else {
serializer.skip_field("cmd_t")?;
}
match &self.discovery.availability {
AvailabilityTopics::None => {
serializer.skip_field("avty")?;
serializer.skip_field("avty_mode")?;
}
AvailabilityTopics::All(topics) => {
serializer.serialize_field("avty_mode", "all")?;
serializer.serialize_field("avty", &AvailabilityTopicList::new(topics))?;
}
AvailabilityTopics::Any(topics) => {
serializer.serialize_field("avty_mode", "any")?;
serializer.serialize_field("avty", &AvailabilityTopicList::new(topics))?;
}
AvailabilityTopics::Latest(topics) => {
serializer.serialize_field("avty_mode", "latest")?;
serializer.serialize_field("avty", &AvailabilityTopicList::new(topics))?;
}
}
if let Some(v) = self.discovery.unique_id {
serializer.serialize_field("uniq_id", v)?;
} else {
serializer.skip_field("uniq_id")?;
}
Ok(serializer)
}
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_some<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_unit_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_newtype_struct<T>(self, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}
fn serialize_newtype_variant<T>(
self,
_: &'static str,
_: u32,
_: &'static str,
_: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
unimplemented!()
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
unimplemented!()
}
fn serialize_tuple_struct(
self,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
unimplemented!()
}
fn serialize_tuple_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
unimplemented!()
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
unimplemented!()
}
fn serialize_struct_variant(
self,
_: &'static str,
_: u32,
_: &'static str,
_: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
unimplemented!()
}
fn serialize_i128(self, _: i128) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn serialize_u128(self, _: u128) -> Result<Self::Ok, Self::Error> {
unimplemented!()
}
fn collect_seq<I>(self, _: I) -> Result<Self::Ok, Self::Error>
where
I: IntoIterator,
<I as IntoIterator>::Item: Serialize,
{
unimplemented!()
}
fn collect_map<K, V, I>(self, _: I) -> Result<Self::Ok, Self::Error>
where
K: Serialize,
V: Serialize,
I: IntoIterator<Item = (K, V)>,
{
unimplemented!()
}
fn collect_str<T>(self, _: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + core::fmt::Display,
{
unimplemented!()
}
fn is_human_readable(&self) -> bool {
unimplemented!()
}
}