use rand::random;
use structopt::StructOpt;
use hex;
use simple_error::SimpleError;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
pub id: u64,
pub device: String,
pub kind: RequestKind,
}
impl Request {
pub fn new(device: String, kind: RequestKind) -> Self {
Self{id: random(), device, kind}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub enum RequestKind {
#[structopt(name = "ping")]
Ping,
#[structopt(name = "spi-connect")]
SpiConnect(SpiConnect),
#[structopt(name = "spi-transfer")]
SpiTransfer{
#[structopt(parse(try_from_str))]
write_data: Data
},
#[structopt(name = "spi-write")]
SpiWrite{
#[structopt(parse(try_from_str))]
write_data: Data
},
#[structopt(name = "spi-disconnect")]
SpiDisconnect,
#[structopt(name = "pin-connect")]
PinConnect(PinMode),
#[structopt(name = "pin-set")]
PinSet(Value),
#[structopt(name = "pin-get")]
PinGet,
#[structopt(name = "pin-disconnect")]
PinDisconnect,
#[structopt(name = "i2c-connect")]
I2cConnect,
#[structopt(name = "i2c-write")]
I2cWrite(I2cWrite),
#[structopt(name = "i2c-read")]
I2cRead(I2cRead),
#[structopt(name = "i2c-write-read")]
I2cWriteRead(I2cWriteRead),
#[structopt(name = "i2c-disconnect")]
I2cDisconnect,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub enum PinMode {
#[structopt(name = "output")]
Output,
#[structopt(name = "input")]
Input,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub enum SpiMode {
#[structopt(name = "mode-0")]
Mode0,
#[structopt(name = "mode-1")]
Mode1,
#[structopt(name = "mode-2")]
Mode2,
#[structopt(name = "mode-3")]
Mode3,
}
impl std::str::FromStr for SpiMode {
type Err = SimpleError;
fn from_str(mode: &str) -> Result<Self, Self::Err> {
match mode {
"0" => Ok(SpiMode::Mode0),
"1" => Ok(SpiMode::Mode1),
"2" => Ok(SpiMode::Mode2),
"3" => Ok(SpiMode::Mode3),
_ => Err(SimpleError::new("invalid spi mode")),
}
}
}
impl std::string::ToString for SpiMode {
fn to_string(&self) -> String {
match self {
SpiMode::Mode0 => format!("0"),
SpiMode::Mode1 => format!("1"),
SpiMode::Mode2 => format!("2"),
SpiMode::Mode3 => format!("3"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
pub id: u64,
pub kind: ResponseKind,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ResponseKind {
Ok,
Error(String),
Unhandled,
DeviceAlreadyBound,
DeviceNotBound,
SpiTransfer(Vec<u8>),
PinGet(bool),
I2cRead(Vec<u8>),
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct Data {
pub data: Vec<u8>,
}
impl std::str::FromStr for Data {
type Err = hex::FromHexError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let s = s.replace(|v| v == ':' || v == ' ' || v == ',' || v == '[' || v == ']', "");
let s = s.trim_start_matches("0x");
let d = hex::decode(s)?;
Ok(Data{data: d})
}
}
impl std::string::ToString for Data {
fn to_string(&self) -> String {
format!("{:x?}", self.data)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct Value {
pub value: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct SpiConnect {
pub baud: u32,
pub mode: SpiMode,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct I2cWrite {
pub addr: u8,
#[structopt(parse(try_from_str))]
pub write_data: Data,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct I2cRead {
pub addr: u8,
pub read_len: u16,
}
#[derive(Debug, Clone, Serialize, Deserialize, StructOpt)]
pub struct I2cWriteRead {
pub addr: u8,
pub read_len: u16,
#[structopt(parse(try_from_str))]
pub write_data: Data,
}