clasp_embedded/
lib.rs

1//! Clasp Embedded
2//!
3//! Minimal no_std implementation for embedded devices.
4//! This crate provides the "Lite" profile for constrained devices.
5//!
6//! # Features
7//! - Fixed 2-byte addresses (numeric IDs)
8//! - Minimal message set
9//! - No compression/encryption
10//! - UDP only
11//!
12//! # Memory Requirements
13//! - < 4KB RAM
14//! - < 16KB Flash
15
16#![no_std]
17
18#[cfg(feature = "alloc")]
19extern crate alloc;
20
21// TODO: Implement lite protocol
22// - Numeric addresses
23// - Fixed-size messages
24// - Simple state machine
25
26/// Lite message types
27#[repr(u8)]
28pub enum LiteMessageType {
29    Hello = 0x01,
30    Welcome = 0x02,
31    Set = 0x21,
32    Publish = 0x20,
33    Ping = 0x41,
34    Pong = 0x42,
35}
36
37/// Lite frame header (fixed 4 bytes)
38#[repr(C, packed)]
39pub struct LiteHeader {
40    pub magic: u8,    // 0x53
41    pub msg_type: u8, // LiteMessageType
42    pub address: u16, // Numeric address
43}
44
45/// Lite SET message
46#[repr(C, packed)]
47pub struct LiteSetMessage {
48    pub header: LiteHeader,
49    pub value: i32, // Fixed 32-bit value
50}
51
52/// Encode a lite SET message
53pub fn encode_lite_set(address: u16, value: i32, buf: &mut [u8]) -> usize {
54    if buf.len() < 8 {
55        return 0;
56    }
57
58    buf[0] = 0x53; // Magic
59    buf[1] = LiteMessageType::Set as u8;
60    buf[2] = (address >> 8) as u8;
61    buf[3] = address as u8;
62    buf[4] = (value >> 24) as u8;
63    buf[5] = (value >> 16) as u8;
64    buf[6] = (value >> 8) as u8;
65    buf[7] = value as u8;
66
67    8
68}
69
70/// Decode a lite message header
71pub fn decode_lite_header(buf: &[u8]) -> Option<(LiteMessageType, u16)> {
72    if buf.len() < 4 || buf[0] != 0x53 {
73        return None;
74    }
75
76    let msg_type = match buf[1] {
77        0x01 => LiteMessageType::Hello,
78        0x02 => LiteMessageType::Welcome,
79        0x21 => LiteMessageType::Set,
80        0x20 => LiteMessageType::Publish,
81        0x41 => LiteMessageType::Ping,
82        0x42 => LiteMessageType::Pong,
83        _ => return None,
84    };
85
86    let address = ((buf[2] as u16) << 8) | (buf[3] as u16);
87
88    Some((msg_type, address))
89}