pub trait AtContext<const SIZE: usize> {
// Provided methods
fn exec(&mut self) -> AtResult<'_, SIZE> { ... }
fn query(&mut self) -> AtResult<'_, SIZE> { ... }
fn test(&mut self) -> AtResult<'_, SIZE> { ... }
fn set(&mut self, _args: Args<'_>) -> AtResult<'_, SIZE> { ... }
}Expand description
Trait that defines the context for AT command execution.
Implement this trait for each AT command your device exposes.
Each method corresponds to one of the four standard AT command forms.
All methods have a default implementation that returns
AtError::NotSupported, so you only need to override the forms your
command actually needs.
The const generic SIZE defines the capacity (in bytes) of the
Bytes response buffer returned by each handler.
All handlers registered in the same AtParser
must use the same SIZE.
§Example — minimal handler
use at_parser_rs::context::AtContext;
use at_parser_rs::{Args, AtResult, AtError};
use osal_rs::utils::Bytes;
const SIZE: usize = 64;
struct ResetModule;
impl AtContext<SIZE> for ResetModule {
fn exec(&mut self) -> AtResult<'_, SIZE> {
// AT+RST performs a system reset
Ok(Bytes::from_str("OK"))
}
}§Example — full handler with all forms
use at_parser_rs::context::AtContext;
use at_parser_rs::{Args, AtResult, AtError};
use osal_rs::utils::Bytes;
const SIZE: usize = 64;
struct EchoModule { enabled: bool }
impl AtContext<SIZE> for EchoModule {
fn exec(&mut self) -> AtResult<'_, SIZE> {
let s = if self.enabled { "ECHO: ON" } else { "ECHO: OFF" };
Ok(Bytes::from_str(s))
}
fn query(&mut self) -> AtResult<'_, SIZE> {
Ok(Bytes::from_str(if self.enabled { "1" } else { "0" }))
}
fn test(&mut self) -> AtResult<'_, SIZE> {
Ok(Bytes::from_str("(0,1)"))
}
fn set(&mut self, args: Args) -> AtResult<'_, SIZE> {
let value = args.get(0).ok_or(AtError::InvalidArgs)?;
match value.as_ref() {
"0" => { self.enabled = false; Ok(Bytes::from_str("OK")) }
"1" => { self.enabled = true; Ok(Bytes::from_str("OK")) }
_ => Err(AtError::InvalidArgs),
}
}
}Provided Methods§
Sourcefn exec(&mut self) -> AtResult<'_, SIZE>
fn exec(&mut self) -> AtResult<'_, SIZE>
Execute command (AT+CMD)
Called when the command is invoked without any suffix. Use this to implement an action that does not require parameters.
§Returns
Ok(Bytes<SIZE>)— response to send back to the callerErr(AtError::NotSupported)— default when not overridden
§Example
struct PingModule;
impl AtContext<SIZE> for PingModule {
fn exec(&mut self) -> AtResult<'_, SIZE> {
Ok(Bytes::from_str("PONG"))
}
}
// AT+PING → "PONG"Examples found in repository?
176fn execute_command(cmd: &str, name: &str, module: &mut dyn AtContext<SIZE>) {
177 let result = if let Some(rest) = cmd.strip_prefix(name) {
178 if rest.is_empty() {
179 module.exec()
180 } else if rest == "?" {
181 module.query()
182 } else if rest == "=?" {
183 module.test()
184 } else if let Some(args_str) = rest.strip_prefix('=') {
185 module.set(Args { raw: args_str })
186 } else {
187 Err(AtError::InvalidArgs)
188 }
189 } else {
190 Err(AtError::UnknownCommand)
191 };
192 let _ = result;
193}Sourcefn query(&mut self) -> AtResult<'_, SIZE>
fn query(&mut self) -> AtResult<'_, SIZE>
Query command (AT+CMD?)
Called to retrieve the current value or state of the command.
§Returns
Ok(Bytes<SIZE>)— current value/stateErr(AtError::NotSupported)— default when not overridden
§Example
struct VolumeModule { level: u8 }
impl AtContext<SIZE> for VolumeModule {
fn query(&mut self) -> AtResult<'_, SIZE> {
let mut buf = Bytes::new();
buf.format(core::format_args!("{}", self.level));
Ok(buf)
}
}
// AT+VOL? → "75" (if level == 75)Examples found in repository?
176fn execute_command(cmd: &str, name: &str, module: &mut dyn AtContext<SIZE>) {
177 let result = if let Some(rest) = cmd.strip_prefix(name) {
178 if rest.is_empty() {
179 module.exec()
180 } else if rest == "?" {
181 module.query()
182 } else if rest == "=?" {
183 module.test()
184 } else if let Some(args_str) = rest.strip_prefix('=') {
185 module.set(Args { raw: args_str })
186 } else {
187 Err(AtError::InvalidArgs)
188 }
189 } else {
190 Err(AtError::UnknownCommand)
191 };
192 let _ = result;
193}Sourcefn test(&mut self) -> AtResult<'_, SIZE>
fn test(&mut self) -> AtResult<'_, SIZE>
Test command (AT+CMD=?)
Called to report whether a command is supported or to return the
valid parameter ranges accepted by set.
§Returns
Ok(Bytes<SIZE>)— human-readable description of valid parametersErr(AtError::NotSupported)— default when not overridden
§Example
struct VolumeModule { level: u8 }
impl AtContext<SIZE> for VolumeModule {
fn test(&mut self) -> AtResult<'_, SIZE> {
Ok(Bytes::from_str("(0-100)"))
}
}
// AT+VOL=? → "(0-100)"Examples found in repository?
176fn execute_command(cmd: &str, name: &str, module: &mut dyn AtContext<SIZE>) {
177 let result = if let Some(rest) = cmd.strip_prefix(name) {
178 if rest.is_empty() {
179 module.exec()
180 } else if rest == "?" {
181 module.query()
182 } else if rest == "=?" {
183 module.test()
184 } else if let Some(args_str) = rest.strip_prefix('=') {
185 module.set(Args { raw: args_str })
186 } else {
187 Err(AtError::InvalidArgs)
188 }
189 } else {
190 Err(AtError::UnknownCommand)
191 };
192 let _ = result;
193}Sourcefn set(&mut self, _args: Args<'_>) -> AtResult<'_, SIZE>
fn set(&mut self, _args: Args<'_>) -> AtResult<'_, SIZE>
Set command (AT+CMD=<args>)
Called to configure the command with one or more parameters.
Arguments are accessible via Args::get using a
0-based comma-separated index. Quoted arguments are unquoted and
escape sequences such as \" are decoded automatically.
§Arguments
args— parsed argument list; useargs.get(n)to retrieve the n-th comma-separated token (0-indexed)
§Returns
Ok(Bytes<SIZE>)— confirmation/responseErr(AtError::InvalidArgs)— when arguments are missing or invalidErr(AtError::NotSupported)— default when not overridden
§Example
struct VolumeModule { level: u8 }
impl AtContext<SIZE> for VolumeModule {
fn set(&mut self, args: Args) -> AtResult<'_, SIZE> {
let val: u8 = args.get(0)
.ok_or(AtError::InvalidArgs)?
.parse()
.map_err(|_| AtError::InvalidArgs)?;
if val > 100 { return Err(AtError::InvalidArgs); }
self.level = val;
Ok(Bytes::from_str("OK"))
}
}
// AT+VOL=75 → "OK" (sets level to 75)
// AT+VOL=200 → Err(InvalidArgs)
// AT+VOL= → Err(InvalidArgs)Examples found in repository?
176fn execute_command(cmd: &str, name: &str, module: &mut dyn AtContext<SIZE>) {
177 let result = if let Some(rest) = cmd.strip_prefix(name) {
178 if rest.is_empty() {
179 module.exec()
180 } else if rest == "?" {
181 module.query()
182 } else if rest == "=?" {
183 module.test()
184 } else if let Some(args_str) = rest.strip_prefix('=') {
185 module.set(Args { raw: args_str })
186 } else {
187 Err(AtError::InvalidArgs)
188 }
189 } else {
190 Err(AtError::UnknownCommand)
191 };
192 let _ = result;
193}