fix: implement new proto spec
This commit is contained in:
parent
53f1b36505
commit
5811d29032
9 changed files with 161 additions and 46 deletions
|
@ -1,8 +1,15 @@
|
|||
use crate::packet::packet_data::PacketData;
|
||||
|
||||
/// NM = Node Management
|
||||
/// This is the abstraction for managing nodes.
|
||||
pub mod node_management;
|
||||
/// PC = Property Control
|
||||
/// This is the abstraction for controling properties on a node.
|
||||
pub mod property_control;
|
||||
/// RDT = Raw Data Transmission
|
||||
/// This is the abstraction for sending raw data over domo.
|
||||
pub mod raw_data_transmission;
|
||||
|
||||
impl_into_enum_variant!(PacketData::NodeManagement, node_management::NodeManagementCommand);
|
||||
impl_into_enum_variant!(PacketData::PropertyControl, property_control::PropertyControlCommand);
|
||||
impl_into_enum_variant!(PacketData::Raw, Vec<u8>);
|
||||
impl_into_enum_variant!(PacketData::Unknown, Vec<u8>);
|
||||
|
|
78
domo_proto/src/commands/raw_data_transmission/mod.rs
Normal file
78
domo_proto/src/commands/raw_data_transmission/mod.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use std::io;
|
||||
|
||||
use crate::{
|
||||
identifier::Identifier,
|
||||
packet::{packet_data::PacketData, raw_packet::RawPacket, Packet, ToPacket},
|
||||
prelude::as_u32_be,
|
||||
};
|
||||
|
||||
pub mod vec;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RawDataTransmission {
|
||||
SetupTransmission {
|
||||
/// The total size of the data being sent.
|
||||
size: u64,
|
||||
/// This string is the mime type of the data being sent.
|
||||
/// By default this should be `application/octet-stream`.
|
||||
/// The maximum length of this string is 128 bytes since the mime rfc states the recommended max is 127 bytes.
|
||||
mime_type: String,
|
||||
},
|
||||
Data {
|
||||
/// The number of the segment in the sequence of segments being sent.
|
||||
sequence_number: u32,
|
||||
/// Segment size in bytes
|
||||
size: u32,
|
||||
/// A segment of the data being sent
|
||||
data: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
impl ToPacket for RawDataTransmission {
|
||||
fn to_packet(
|
||||
self,
|
||||
src: Identifier,
|
||||
dest: Identifier,
|
||||
packet_id: Identifier,
|
||||
reply_to: Identifier,
|
||||
) -> Packet {
|
||||
Packet {
|
||||
src,
|
||||
dest,
|
||||
packet_id,
|
||||
reply_to,
|
||||
command: 0x20,
|
||||
data: PacketData::RawDataTransmission(self.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RawPacket> for RawDataTransmission {
|
||||
type Error = io::Error;
|
||||
fn try_from(raw_packet: RawPacket) -> io::Result<Self> {
|
||||
let build_invalid_input_err = |r: &str| Err(io::Error::new(io::ErrorKind::InvalidInput, r));
|
||||
|
||||
let mut data = raw_packet.data;
|
||||
match raw_packet.command {
|
||||
0x20 => {
|
||||
let size = u64::from_be_bytes([
|
||||
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
|
||||
]);
|
||||
let mime_type = String::from_utf8(data[8..].to_vec()).map_err(|_| {
|
||||
io::Error::new(io::ErrorKind::InvalidInput, "Invalid mime type string")
|
||||
})?;
|
||||
Ok(RawDataTransmission::SetupTransmission { size, mime_type })
|
||||
}
|
||||
0x21 => {
|
||||
let sequence_number = as_u32_be(&mut data);
|
||||
let size = as_u32_be(&mut data);
|
||||
Ok(RawDataTransmission::Data {
|
||||
sequence_number,
|
||||
size,
|
||||
data,
|
||||
})
|
||||
}
|
||||
_ => build_invalid_input_err("Invalid command"),
|
||||
}
|
||||
}
|
||||
}
|
21
domo_proto/src/commands/raw_data_transmission/vec.rs
Normal file
21
domo_proto/src/commands/raw_data_transmission/vec.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
use super::RawDataTransmission;
|
||||
|
||||
impl Into<Vec<u8>> for RawDataTransmission {
|
||||
fn into(self) -> Vec<u8> {
|
||||
match self {
|
||||
RawDataTransmission::SetupTransmission { size, mime_type } => {
|
||||
let mut v = vec![];
|
||||
v.extend(size.to_be_bytes().to_vec());
|
||||
v.extend(mime_type.into_bytes());
|
||||
v
|
||||
},
|
||||
RawDataTransmission::Data { sequence_number, size, data } => {
|
||||
let mut v = vec![];
|
||||
v.extend(sequence_number.to_be_bytes().to_vec());
|
||||
v.extend(size.to_be_bytes().to_vec());
|
||||
v.extend(data);
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,39 +11,30 @@ pub enum DataType {
|
|||
Array(Vec<DataType>),
|
||||
|
||||
// Basic types
|
||||
/// Basic Type: Switch (`0x10`]
|
||||
Switch(bool),
|
||||
/// Basic Type: Boolean (`0x10`]
|
||||
Boolean(bool),
|
||||
/// Basic Type: Slider (`0x11`)
|
||||
Slider(u8),
|
||||
Number(u64),
|
||||
/// Basic Type: Text (`0x12`)
|
||||
Text(String),
|
||||
/// Basic Type: Identifier (`0x13`)
|
||||
Identifier(Identifier),
|
||||
|
||||
// Cosmetic
|
||||
/// Cosmetic Type: RGB (`0x20`)
|
||||
// Color
|
||||
/// Color Type: RGB (`0x20`)
|
||||
RGB(u8, u8, u8),
|
||||
|
||||
// Time & Space
|
||||
/// Time & Space Type: Seconds (`0x90`)
|
||||
Seconds(u64),
|
||||
|
||||
// Domo Types
|
||||
/// Domo type: Node Ref (`0xF0`)
|
||||
NodeRef(Identifier),
|
||||
}
|
||||
|
||||
impl DataType {
|
||||
pub fn get_data_size(data_type: u8) -> usize {
|
||||
match data_type {
|
||||
0x00 => 0,
|
||||
0x01 => {
|
||||
2
|
||||
},
|
||||
0x01 => 2,
|
||||
0x10 => 1,
|
||||
0x11 => 1,
|
||||
0x11 => 8,
|
||||
0x12 => 256,
|
||||
0x13 => 4,
|
||||
0x20 => 3,
|
||||
0x90 => 8,
|
||||
0xF0 => 4,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io;
|
||||
use crate::data_types::{DataType, get_data_types};
|
||||
use crate::identifier::Identifier;
|
||||
use crate::identifier::{Identifier, self};
|
||||
use crate::prelude::as_u64_be;
|
||||
|
||||
impl Into<Vec<u8>> for DataType {
|
||||
|
@ -14,24 +14,23 @@ impl Into<Vec<u8>> for DataType {
|
|||
}
|
||||
res
|
||||
},
|
||||
DataType::Switch(b) => vec![0x10, b as u8],
|
||||
DataType::Slider(v) => vec![0x11, v],
|
||||
DataType::Boolean(b) => vec![0x10, b as u8],
|
||||
DataType::Number(v) => {
|
||||
let mut bytes = vec![0x11];
|
||||
bytes.extend(v.to_be_bytes());
|
||||
bytes
|
||||
},
|
||||
DataType::Text(s) => {
|
||||
let mut bytes = vec![0x12];
|
||||
bytes.extend(s.into_bytes());
|
||||
bytes
|
||||
},
|
||||
DataType::Identifier(identifier) => {
|
||||
let mut bytes = vec![0x13];
|
||||
bytes.extend(identifier.bytes);
|
||||
bytes
|
||||
},
|
||||
DataType::RGB(r, g, b) => vec![0x20, r, g, b],
|
||||
DataType::Seconds(s) => {
|
||||
let mut bytes = vec![0x90];
|
||||
bytes.extend_from_slice(s.to_be_bytes().as_ref());
|
||||
bytes
|
||||
},
|
||||
DataType::NodeRef(id) => {
|
||||
let mut bytes = vec![0xF0];
|
||||
bytes.extend_from_slice(id.bytes.as_ref());
|
||||
bytes
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +60,11 @@ impl TryFrom<Vec<u8>> for DataType {
|
|||
if value.len() - 1 < size as usize { return Err(io::Error::new(io::ErrorKind::InvalidData, "Array specified data length != array data length")) }
|
||||
Ok(DataType::Array(get_data_types(value[3..(size as usize)].to_vec())))
|
||||
},
|
||||
0x10 => impl_data_type!(value, 1, DataType::Switch(value[1] != 0)),
|
||||
0x11 => impl_data_type!(value, 1, DataType::Slider(value[1])),
|
||||
0x10 => impl_data_type!(value, 1, DataType::Boolean(value[1] != 0)),
|
||||
0x11 => impl_data_type!(value, 8, DataType::Number(u64::from_be_bytes([
|
||||
value[1], value[2], value[3], value[4],
|
||||
value[5], value[6], value[7], value[8]
|
||||
]))),
|
||||
0x12 => impl_data_type!(
|
||||
value,
|
||||
256,
|
||||
|
@ -72,9 +74,8 @@ impl TryFrom<Vec<u8>> for DataType {
|
|||
DataType::Nothing
|
||||
}
|
||||
),
|
||||
0x13 => impl_data_type!(value, 4, DataType::Identifier(Identifier::from(&value[1..5]))),
|
||||
0x20 => impl_data_type!(value, 3, DataType::RGB(value[1], value[2], value[3])),
|
||||
0x90 => impl_data_type!(value, 8, DataType::Seconds(as_u64_be(&value[1..9]))),
|
||||
0xF0 => impl_data_type!(value, 4, DataType::NodeRef(Identifier::from(&value[1..5]))),
|
||||
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "Could not match data type header to a data type.")),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Welcome to the Domo protocol rust implementation.
|
||||
//!
|
||||
//! This implementation is up-to-date with DomoProto v1.
|
||||
//! This implementation is up-to-date with Domo protocol v1.
|
||||
//!
|
||||
//! Most code that should/is actually used (usually) has documentation with it.
|
||||
|
||||
|
@ -27,7 +27,6 @@ mod tests {
|
|||
use crate::packet;
|
||||
use crate::data_types::{DataType, get_data_types};
|
||||
use crate::identifier::Identifier;
|
||||
use crate::packet::Packet;
|
||||
use crate::packet::packet_data::PacketData;
|
||||
|
||||
#[test]
|
||||
|
@ -37,12 +36,12 @@ mod tests {
|
|||
get_data_types(vec![0x00, 0x10, 0x00]),
|
||||
vec![
|
||||
DataType::Nothing,
|
||||
DataType::Switch(false),
|
||||
DataType::Boolean(false),
|
||||
]);
|
||||
|
||||
// test DataType -> Vec<u8>
|
||||
assert_eq!(
|
||||
Into::<Vec<u8>>::into(DataType::Switch(true)),
|
||||
Into::<Vec<u8>>::into(DataType::Boolean(true)),
|
||||
vec![0x10, 0x01]
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub const FULL_PACKET_SIZE: usize = 65559;
|
|||
pub const BASE_PACKET_SIZE: usize = 65555;
|
||||
|
||||
/// The abstraction for all DomoProto packets.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Packet {
|
||||
pub dest: Identifier,
|
||||
pub src: Identifier,
|
||||
|
@ -31,6 +31,20 @@ pub trait ToPacket {
|
|||
fn to_packet(self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier) -> Packet;
|
||||
}
|
||||
|
||||
/// Default packet is a ping from 0x0 to 0xFFFFFFFF
|
||||
impl Default for Packet {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
dest: Identifier::from(0xFFFFFFFF),
|
||||
src: Identifier::from(0),
|
||||
command: 0x00,
|
||||
packet_id: Identifier::random(),
|
||||
reply_to: Identifier::default(),
|
||||
data: PacketData::Unknown(vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Secretly calls RawPacket::try_from().into()
|
||||
impl TryFrom<Vec<u8>> for Packet {
|
||||
type Error = io::Error;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::io;
|
||||
use crate::commands::property_control::PropertyControlCommand;
|
||||
use crate::commands::node_management::NodeManagementCommand;
|
||||
use crate::commands::raw_data_transmission::RawDataTransmission;
|
||||
use crate::packet::raw_packet::RawPacket;
|
||||
|
||||
/// Abstraction used for interpreting the data in a packet.
|
||||
|
@ -8,13 +9,14 @@ use crate::packet::raw_packet::RawPacket;
|
|||
pub enum PacketData {
|
||||
NodeManagement(NodeManagementCommand),
|
||||
PropertyControl(PropertyControlCommand),
|
||||
Raw(Vec<u8>)
|
||||
RawDataTransmission(RawDataTransmission),
|
||||
Unknown(Vec<u8>)
|
||||
}
|
||||
|
||||
/// Returns an empty `PacketData::Raw`
|
||||
impl Default for PacketData {
|
||||
fn default() -> Self {
|
||||
PacketData::Raw(vec![])
|
||||
PacketData::Unknown(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +25,8 @@ impl PacketData {
|
|||
match self {
|
||||
PacketData::NodeManagement(v) => v.into(),
|
||||
PacketData::PropertyControl(v) => v.into(),
|
||||
PacketData::Raw(v) => v
|
||||
PacketData::RawDataTransmission(v) => v.into(),
|
||||
PacketData::Unknown(v) => v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +39,7 @@ impl TryFrom<RawPacket> for PacketData {
|
|||
} {
|
||||
0x0 => Ok(PacketData::NodeManagement(NodeManagementCommand::try_from(raw_packet)?)),
|
||||
0x1 => Ok(PacketData::PropertyControl(PropertyControlCommand::try_from(raw_packet)?)),
|
||||
0xF => Ok(PacketData::RawDataTransmission(RawDataTransmission::try_from(raw_packet)?)),
|
||||
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "command group is unsupported"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Into<Packet> for RawPacket {
|
|||
println!("{}", e);
|
||||
e
|
||||
})
|
||||
.unwrap_or(PacketData::Raw(self.data)),
|
||||
.unwrap_or(PacketData::Unknown(self.data)),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue