use crate::pin_function::PinFunction;
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "std"))]
use core::clone::Clone;
#[cfg(not(feature = "std"))]
use core::option::Option;
#[cfg(not(feature = "std"))]
use core::prelude::rust_2024::derive;
#[cfg(not(feature = "std"))]
use heapless::String;
#[cfg(not(feature = "std"))]
use heapless::Vec;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::string::String;
#[cfg(feature = "std")]
use std::vec::Vec;
#[allow(dead_code)] pub const SSID_NAME_MAX_LENGTH: usize = 32;
#[allow(dead_code)] pub const SSID_PASS_MAX_LENGTH: usize = 63;
#[allow(dead_code)] pub const SSID_PASS_MIN_LENGTH: usize = 8;
#[allow(dead_code)] #[cfg(all(feature = "discovery", feature = "tcp"))]
pub const TCP_MDNS_SERVICE_NAME: &str = "_pigg";
#[allow(dead_code)] #[cfg(all(feature = "discovery", feature = "tcp"))]
pub const TCP_MDNS_SERVICE_PROTOCOL: &str = "_tcp";
#[allow(dead_code)] #[cfg(all(feature = "discovery", feature = "tcp"))]
pub const TCP_MDNS_SERVICE_TYPE: &str = "_pigg._tcp.local.";
pub type BCMPinNumber = u8;
pub type BoardPinNumber = u8;
pub type PinLevel = bool;
#[cfg(feature = "std")]
pub type SerialNumber = String;
#[cfg(feature = "std")]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HardwareDescription {
pub details: HardwareDetails,
pub pins: PinDescriptionSet,
}
#[cfg(feature = "std")]
impl PinDescriptionSet {
#[allow(dead_code)] pub fn bcm_pins_sorted(&self) -> Vec<&PinDescription> {
let mut pins = self
.pins()
.iter()
.filter(|pin| pin.bcm.is_some())
.collect::<Vec<&PinDescription>>();
pins.sort_by_key(|pin| pin.bcm.expect("Could not get BCM pin number"));
pins
}
}
#[cfg(not(feature = "std"))]
#[derive(Serialize)]
#[cfg_attr(feature = "std", derive(Debug, Clone, Deserialize))]
pub struct HardwareDescription<'a> {
pub details: HardwareDetails<'a>,
pub pins: PinDescriptionSet<'a>,
}
#[cfg(feature = "std")]
#[cfg_attr(debug_assertions, derive(PartialEq))]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct HardwareDetails {
pub model: String,
pub hardware: String,
pub revision: String,
pub serial: SerialNumber,
pub wifi: bool,
pub app_name: String,
pub app_version: String,
}
#[cfg(feature = "std")]
impl std::fmt::Display for HardwareDetails {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Application: {}", self.app_name)?;
writeln!(f, "App Version: {}", self.app_version)?;
writeln!(f, "Hardware: {}", self.hardware)?;
writeln!(f, "Revision: {}", self.revision)?;
writeln!(f, "Serial: {}", self.serial)?;
writeln!(f, "Model: {}", self.model)?;
if self.wifi {
write!(f, "Wi-Fi Supported: Yes")
} else {
write!(f, "Wi-Fi Supported: No")
}
}
}
#[cfg(not(feature = "std"))]
#[derive(Serialize)]
pub struct HardwareDetails<'a> {
pub model: &'a str,
pub hardware: &'a str,
pub revision: &'a str,
pub serial: &'a str,
pub wifi: bool,
pub app_name: &'a str,
pub app_version: &'a str,
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SsidSpec {
pub ssid_name: String,
pub ssid_pass: String,
pub ssid_security: String,
}
#[cfg(not(feature = "std"))]
#[derive(Serialize, Deserialize, Clone)]
pub struct SsidSpec {
pub ssid_name: String<SSID_NAME_MAX_LENGTH>,
pub ssid_pass: String<SSID_PASS_MAX_LENGTH>,
pub ssid_security: String<4>,
}
#[cfg(feature = "std")]
impl SsidSpec {
pub fn try_new(name: String, pass: String, security: String) -> Result<SsidSpec, String> {
if name.trim().is_empty() {
return Err("Please Enter SSID name".into());
}
if name.trim().len() > SSID_NAME_MAX_LENGTH {
return Err("SSID name is too long".into());
}
match security.as_str() {
"wpa" | "wpa2" | "wpa3" => {
if pass.trim().is_empty() {
return Err("Please Enter SSID password".into());
}
if pass.trim().len() < SSID_PASS_MIN_LENGTH {
return Err("SSID password is too short".into());
}
if pass.trim().len() > SSID_PASS_MAX_LENGTH {
return Err("SSID password is too long".into());
}
}
_ => {}
}
Ok(SsidSpec {
ssid_name: name,
ssid_pass: pass,
ssid_security: security,
})
}
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WiFiDetails {
pub ssid_spec: Option<SsidSpec>,
pub tcp: Option<([u8; 4], u16)>, }
#[cfg(not(feature = "std"))]
#[derive(Serialize)]
pub struct WiFiDetails {
pub ssid_spec: Option<SsidSpec>,
pub tcp: Option<([u8; 4], u16)>, }
#[cfg(feature = "std")]
#[derive(Serialize, Debug, Clone, Deserialize)]
pub struct PinDescriptionSet {
pins: Vec<PinDescription>,
}
#[cfg(not(feature = "std"))]
#[derive(Serialize)]
pub struct PinDescriptionSet<'a> {
pub pins: Vec<PinDescription<'a>, 40>,
}
#[cfg(not(feature = "std"))]
impl<'a> PinDescriptionSet<'a> {
pub fn new(pin_slice: &'a [PinDescription]) -> Self {
Self {
pins: Vec::from_slice(pin_slice).unwrap(),
}
}
}
#[cfg(feature = "std")]
impl PinDescriptionSet {
#[allow(dead_code)] pub fn pins(&self) -> &[PinDescription] {
&self.pins
}
pub fn new(pin_slice: &[PinDescription]) -> Self {
Self {
pins: pin_slice.to_vec(),
}
}
}
#[cfg(feature = "std")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PinDescription {
pub bpn: BoardPinNumber,
pub bcm: Option<BCMPinNumber>,
pub name: Cow<'static, str>,
pub options: Cow<'static, [PinFunction]>,
}
#[cfg(feature = "std")]
impl std::fmt::Display for PinDescription {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Board Pin #: {}", self.bpn)?;
writeln!(f, "\tBCM Pin #: {:?}", self.bcm)?;
writeln!(f, "\tName Pin #: {}", self.name)?;
writeln!(f, "\tFunctions #: {:?}", self.options)
}
}
#[cfg(not(feature = "std"))]
#[derive(Clone, Serialize)]
pub struct PinDescription<'a> {
pub bpn: BoardPinNumber,
pub bcm: Option<BCMPinNumber>,
pub name: &'static str,
pub options: &'a [PinFunction],
}