use std::u8;
use bytes::{BytesMut, BufMut, Buf};
use chrono::{Utc, Timelike};
use num_derive::FromPrimitive;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PDUHeaderRecord {
pub protocol_version: ProtocolVersion,
pub exercise_id: u8,
pub pdu_type: PDUType,
pub protocol_family: ProtocolFamily,
pub timestamp: u32,
pub length: u16,
pub padding: u16
}
impl PDUHeaderRecord {
pub fn new(pdu_type: PDUType, protocol_family: ProtocolFamily, exercise_id: u8, length: u16,) -> Self {
PDUHeaderRecord {
protocol_version: ProtocolVersion::DIS_PDUv2_Fourth_Draft_Revised,
exercise_id,
pdu_type,
protocol_family,
timestamp: PDUHeaderRecord::calculate_dis_timestamp() as u32,
length: length as u16,
padding: 0 as u16
}
}
pub fn default(pdu_type: PDUType, protocol_family: ProtocolFamily, length: u16,) -> Self {
PDUHeaderRecord {
protocol_version: ProtocolVersion::DIS_PDUv2_Fourth_Draft_Revised,
exercise_id: 1,
pdu_type,
protocol_family,
timestamp: PDUHeaderRecord::calculate_dis_timestamp() as u32,
length: length as u16,
padding: 0 as u16
}
}
pub fn calculate_dis_timestamp() -> u32 {
let current_minute = ((Utc::now().minute() * 60) * 1e6 as u32) as u64 ;
let current_second = (Utc::now().second() * 1e6 as u32) as u64;
let current_nanos = (Utc::now().nanosecond() / 1000) as u64;
let dis_units = (current_second + current_minute + current_nanos) as f32 / 1.68;
dis_units as u32
}
pub fn serialize(&self, buf: &mut BytesMut) {
buf.put_u8(self.protocol_version as u8);
buf.put_u8(self.exercise_id as u8);
buf.put_u8(self.pdu_type as u8);
buf.put_u8(self.protocol_family as u8);
buf.put_u32(self.timestamp as u32);
buf.put_u16(self.length as u16);
buf.put_u16(self.padding as u16);
}
fn decode_protocol_version(data: u8) -> ProtocolVersion {
match data {
1 => ProtocolVersion::DIS_PDUv1,
2 => ProtocolVersion::IEEE1278,
3 => ProtocolVersion::DIS_PDUv2_Third_Draft,
4 => ProtocolVersion::DIS_PDUv2_Fourth_Draft_Revised,
5 => ProtocolVersion::IEEE1278_1,
_ => ProtocolVersion::Other
}
}
pub fn decode(buf: &mut BytesMut) -> PDUHeaderRecord {
PDUHeaderRecord {
protocol_version: PDUHeaderRecord::decode_protocol_version(buf.get_u8()),
exercise_id: buf.get_u8(),
pdu_type: PDUHeaderRecord::decode_pdu_type(buf.get_u8()),
protocol_family: PDUHeaderRecord::decode_protocol_family(buf.get_u8()),
timestamp: buf.get_u32(),
length: buf.get_u16(),
padding: buf.get_u16()
}
}
fn decode_pdu_type(data: u8) -> PDUType {
match data {
1 => PDUType::EntityState,
2 => PDUType::Fire,
3 => PDUType::Detonation,
4 => PDUType::Collision,
5 => PDUType::ServiceRequest,
6 => PDUType::ResupplyOffer,
7 => PDUType::ResupplyReceived,
8 => PDUType::ResupplyCancel,
9 => PDUType::RepairComplete,
10 => PDUType::RepairRepsonse,
11 => PDUType::CreateEntity,
12 => PDUType::RemoveEntity,
13 => PDUType::StartResume,
14 => PDUType::StopFreeze,
15 => PDUType::Acknowledge,
16 => PDUType::ActionRequest,
17 => PDUType::ActionReponse,
18 => PDUType::DataQuery,
19 => PDUType::SetData,
20 => PDUType::Data,
21 => PDUType::EventReport,
22 => PDUType::Comment,
23 => PDUType::ElectromagneticEmission,
24 => PDUType::Designator,
25 => PDUType::Transmitter,
26 => PDUType::Signal,
27 => PDUType::Recevier,
_ => PDUType::Other
}
}
fn decode_protocol_family(data: u8) -> ProtocolFamily {
match data {
1 => ProtocolFamily::EntityInformation,
2 => ProtocolFamily::Warfare,
3 => ProtocolFamily::Logistics,
4 => ProtocolFamily::RadioCommunications,
5 => ProtocolFamily::SimulationManagement,
6 => ProtocolFamily::DistributedEmissionRegeneration,
_ => ProtocolFamily::Other
}
}
}
#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
pub enum ProtocolFamily {
Other = 0,
EntityInformation = 1,
Warfare = 2,
Logistics = 3,
RadioCommunications = 4,
SimulationManagement = 5,
DistributedEmissionRegeneration = 6
}
#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
#[allow(non_camel_case_types)]
pub enum ProtocolVersion {
Other = 0,
DIS_PDUv1 = 1,
IEEE1278 = 2,
DIS_PDUv2_Third_Draft = 3,
DIS_PDUv2_Fourth_Draft_Revised = 4,
IEEE1278_1 = 5
}
#[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
pub enum PDUType {
Other = 0,
EntityState = 1,
Fire = 2,
Detonation = 3,
Collision = 4,
ServiceRequest = 5,
ResupplyOffer = 6,
ResupplyReceived = 7,
ResupplyCancel = 8,
RepairComplete = 9,
RepairRepsonse = 10,
CreateEntity = 11,
RemoveEntity = 12,
StartResume = 13,
StopFreeze = 14,
Acknowledge = 15,
ActionRequest = 16,
ActionReponse = 17,
DataQuery = 18,
SetData = 19,
Data = 20,
EventReport = 21,
Comment = 22,
ElectromagneticEmission = 23,
Designator = 24,
Transmitter = 25,
Signal = 26,
Recevier = 27,
}