use w5500_hl::{io::Write, Error as HlError};
use crate::{properties::Properties, ClientId, CtrlPkt};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum ConnectReasonCode {
UnspecifiedError = 0x80,
MalformedPacket = 0x81,
ProtocolError = 0x82,
ImplementationSpecificError = 0x83,
UnsupportedProtocolVersion = 0x84,
ClientIdentifierNotValid = 0x85,
BadUserNameOrPassword = 0x86,
NotAuthorized = 0x87,
ServerUnavailable = 0x88,
ServerBusy = 0x89,
Banned = 0x8A,
BadAuthenticationMethod = 0x8C,
TopicNameInvalid = 0x90,
PacketTooLarge = 0x95,
QuotaExceeded = 0x97,
PayloadFormatInvalid = 0x99,
RetainNotSupported = 0x9A,
QoSNotSupported = 0x9B,
UseAnotherServer = 0x9C,
ServerMoved = 0x9D,
ConnectionRateExceeded = 0x9F,
}
impl TryFrom<u8> for ConnectReasonCode {
type Error = u8;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
x if x == (Self::UnspecifiedError as u8) => Ok(Self::UnspecifiedError),
x if x == (Self::MalformedPacket as u8) => Ok(Self::MalformedPacket),
x if x == (Self::ProtocolError as u8) => Ok(Self::ProtocolError),
x if x == (Self::ImplementationSpecificError as u8) => {
Ok(Self::ImplementationSpecificError)
}
x if x == (Self::UnsupportedProtocolVersion as u8) => {
Ok(Self::UnsupportedProtocolVersion)
}
x if x == (Self::ClientIdentifierNotValid as u8) => Ok(Self::ClientIdentifierNotValid),
x if x == (Self::BadUserNameOrPassword as u8) => Ok(Self::BadUserNameOrPassword),
x if x == (Self::NotAuthorized as u8) => Ok(Self::NotAuthorized),
x if x == (Self::ServerUnavailable as u8) => Ok(Self::ServerUnavailable),
x if x == (Self::ServerBusy as u8) => Ok(Self::ServerBusy),
x if x == (Self::Banned as u8) => Ok(Self::Banned),
x if x == (Self::BadAuthenticationMethod as u8) => Ok(Self::BadAuthenticationMethod),
x if x == (Self::TopicNameInvalid as u8) => Ok(Self::TopicNameInvalid),
x if x == (Self::PacketTooLarge as u8) => Ok(Self::PacketTooLarge),
x if x == (Self::QuotaExceeded as u8) => Ok(Self::QuotaExceeded),
x if x == (Self::PayloadFormatInvalid as u8) => Ok(Self::PayloadFormatInvalid),
x if x == (Self::RetainNotSupported as u8) => Ok(Self::RetainNotSupported),
x if x == (Self::QoSNotSupported as u8) => Ok(Self::QoSNotSupported),
x if x == (Self::UseAnotherServer as u8) => Ok(Self::UseAnotherServer),
x if x == (Self::ServerMoved as u8) => Ok(Self::ServerMoved),
x if x == (Self::ConnectionRateExceeded as u8) => Ok(Self::ConnectionRateExceeded),
x => Err(x),
}
}
}
pub fn send_connect<E, Writer: Write<E>>(
mut writer: Writer,
client_id: &Option<ClientId>,
rx_max: u16,
) -> Result<(), HlError<E>> {
const KEEP_ALIVE: u16 = 15 * 60;
let client_id_len: u8 = client_id.map(|id| id.len()).unwrap_or(0);
#[rustfmt::skip]
writer.write_all(&[
(CtrlPkt::CONNECT as u8) << 4,
18 + client_id_len,
0, 4,
b'M', b'Q', b'T', b'T',
5,
0b00000010,
(KEEP_ALIVE >> 8) as u8, KEEP_ALIVE as u8,
5,
(Properties::MaxPktSize as u8), 0, 0, (rx_max >> 8) as u8, rx_max as u8,
0, client_id_len,
])?;
if let Some(client_id) = client_id {
writer.write_all(client_id.as_bytes())?;
}
writer.send()?;
Ok(())
}