1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use heapless::{String, Vec};
use crate::{MaxCommandLen, MaxResponseLines};
use crate::error::Error;

/// Trait to be implemented by device driver crates.
///
/// # Examples
///
/// ```
/// #[derive(Debug, Clone)]
/// enum Command {
///   AT,
///   GetSerialNum,
///   GetUMSM,
///   GetCSGT,
///   SetDefaultPeer {
///     peer_id: u8,
///     url: String<MaxCommandLen>,
///     connect_scheme: u8,
///   },
/// }

/// #[derive(Debug, Clone, PartialEq)]
/// enum Response {
///   None,
///   SerialNum { serial: String<MaxCommandLen> },
///   UMSM { start_mode: u8 },
///   CSGT { mode: u8, text: String<MaxCommandLen> },

///   // Unsolicited responses
///   PeerDisconnected { peer_handle: u8 },
/// }

/// impl ATCommandInterface<Response> for Command {
///   fn get_cmd(&self) -> String<MaxCommandLen> {
///     let mut buffer = String::new();
///     match self {
///       Command::AT => String::from("AT"),
///       Command::GetUMSM => String::from("AT+UMSM?\r\n"),
///       Command::GetCSGT => String::from("AT+CSGT?\r\n"),
///       Command::GetSerialNum => String::from("AT+CGSN"),
///       Command::SetDefaultPeer {
///         ref peer_id,
///         ref url,
///         ref connect_scheme,
///       } => {
///         write!(
///           buffer,
///           "AT+UDDRP={},{},{}",
///           peer_id, url, *connect_scheme as u8
///         )
///         .unwrap();
///         buffer
///       }
///     }
///   }
///   fn parse_resp(&self, response_lines: &mut Vec<String<MaxCommandLen>, MaxResponseLines>) -> Response {
///     if response_lines.is_empty() {
///       return Response::None;
///     }
///     let mut responses: Vec<Vec<&str, MaxResponseLines>, MaxResponseLines> = utils::split_parameterized_resp(response_lines);

///     let response = responses.pop().unwrap();

///     match *self {
///       Command::AT => Response::None,
///       Command::GetUMSM => Response::UMSM {
///         start_mode: response[0].parse::<u8>().unwrap(),
///       },
///       Command::GetCSGT => Response::CSGT {
///         mode: response[0].parse::<u8>().unwrap(),
///         text: String::from(response[1]),
///       },
///       Command::GetSerialNum => Response::SerialNum {
///         serial: String::from(response[0]),
///       },
///       Command::SetDefaultPeer { .. } => Response::None,
///     }
///   }

///   fn parse_unsolicited(response_line: &str) -> Response {
///     let (cmd, parameters) = utils::split_parameterized_unsolicited(response_line);

///     match cmd {
///       "+UUDPD" => Response::PeerDisconnected {
///         peer_handle: parameters[0].parse::<u8>().unwrap(),
///       },
///       _ => Response::None,
///     }
///   }
/// }
/// ```
pub trait ATCommandInterface<R> {
    fn get_cmd(&self) -> String<MaxCommandLen>;
    fn parse_resp(&self, response_lines: &mut Vec<String<MaxCommandLen>, MaxResponseLines>) -> R;
    fn parse_unsolicited(response_line: &str) -> R;
}


pub trait ATInterface<Command, Response> {
    fn send(&mut self, cmd: Command) -> Result<Response, Error>;

    fn send_timeout(&mut self, cmd: Command, timeout: u32) -> Result<Response, Error>;

    // Can these be made using rusts new shiny async/await?
    fn wait_responses(&mut self, timeout: u32) -> Result<Response, Error>;

    // fn is_wifi_enabled(&self) -> Result<bool, WifiError>;

    // /// Turn on the wifi interface of host machine.
    // fn turn_on(&mut self) -> Result<(), WifiError>;

    // /// Turn off the wifi interface of host machine.
    // fn turn_off(&mut self) -> Result<(), WifiError>;
}