Skip to content

Commit

Permalink
WIP adding additional layers of abstraction in accordance with normat…
Browse files Browse the repository at this point in the history
…ive descriptions

Currently tests are failing. Starting from v0.1.0 semantic versioning should be strictly introduced and also branching for new features with a clear branching naming scheme
  • Loading branch information
maebli committed Mar 29, 2024
1 parent f926bfe commit 0af21ed
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 20 deletions.
29 changes: 17 additions & 12 deletions src/user_data/data_information.rs
@@ -1,16 +1,21 @@
pub struct DataInformationBlock {
pub _data_information_field: DataInformationField,
pub _data_information_field_extension: Option<DataInformationExtensionField>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct DataInformation {
pub struct DataInformationField {
pub storage_number: u64,
pub function_field: FunctionField,
pub data_field_coding: DataFieldCoding,
pub data_information_extension: Option<DataInformationExtension>,
pub data_information_extension: Option<DataInformationExtensionField>,
pub size: usize,
}

const MAXIMUM_DATA_INFORMATION_SIZE: usize = 11;

#[derive(Debug, Clone, PartialEq)]
pub struct DataInformationExtension {}
pub struct DataInformationExtensionField {}

#[derive(Debug, PartialEq)]
pub enum DataInformationError {
Expand All @@ -19,7 +24,7 @@ pub enum DataInformationError {
DataTooShort,
}

impl TryFrom<&[u8]> for DataInformation {
impl TryFrom<&[u8]> for DataInformationField {
type Error = DataInformationError;

fn try_from(data: &[u8]) -> Result<Self, DataInformationError> {
Expand Down Expand Up @@ -79,12 +84,12 @@ impl TryFrom<&[u8]> for DataInformation {
_ => unreachable!(), // This case should never occur due to the 4-bit width
};

Ok(DataInformation {
Ok(DataInformationField {
storage_number,
function_field,
data_field_coding,
data_information_extension: if extension_bit {
Some(DataInformationExtension {})
Some(DataInformationExtensionField {})
} else {
None
},
Expand All @@ -93,7 +98,7 @@ impl TryFrom<&[u8]> for DataInformation {
}
}

impl DataInformation {
impl DataInformationField {
pub fn get_size(&self) -> usize {
self.size
}
Expand Down Expand Up @@ -272,10 +277,10 @@ mod tests {
#[test]
fn test_data_information() {
let data = [0x13 as u8];
let result = DataInformation::try_from(data.as_slice());
let result = DataInformationField::try_from(data.as_slice());
assert_eq!(
result,
Ok(DataInformation {
Ok(DataInformationField {
storage_number: 0,
function_field: FunctionField::MaximumValue,
data_field_coding: DataFieldCoding::Integer24Bit,
Expand All @@ -290,7 +295,7 @@ mod tests {
let data = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
];
let result = DataInformation::try_from(data.as_slice());
let result = DataInformationField::try_from(data.as_slice());
assert_eq!(result, Err(DataInformationError::DataTooLong));
}

Expand All @@ -299,14 +304,14 @@ mod tests {
let data = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
];
let result = DataInformation::try_from(data.as_slice());
let result = DataInformationField::try_from(data.as_slice());
assert_ne!(result, Err(DataInformationError::DataTooLong));
}

#[test]
fn test_short_data_information() {
let data = [0xFF];
let result = DataInformation::try_from(data.as_slice());
let result = DataInformationField::try_from(data.as_slice());
assert_eq!(result, Err(DataInformationError::DataTooShort));
}
}
13 changes: 7 additions & 6 deletions src/user_data/value_information.rs
Expand Up @@ -280,7 +280,6 @@ impl TryFrom<&ValueInformation> for Unit {
_ => todo!("Implement the rest of the units: {:?}", x),
},
ValueInformation::PlainText(_) => Ok(Unit::PlainText),
ValueInformation::PlainText(_) => Ok(Unit::PlainText),
ValueInformation::Extended(x) => match x {
VIFExtension::EnergyMWh(_) => Ok(Unit::MegaWattHour),
VIFExtension::EnergyGJ(_) => Ok(Unit::GigaJoul),
Expand Down Expand Up @@ -340,22 +339,21 @@ mod tests {
}

//
// To solve this descrpeancy the parser needs to be configurable
// To solve this issue the parser needs to be configurable
// it should try to parse according to mbus and if it fails it should try to parse
// with the wrong, but common, method

#[test]
fn test_plain_text_vif_common_none_norm_conform() {
use crate::user_data::value_information::VIFExtension;
use crate::user_data::value_information::ValueInformation;
use arrayvec::ArrayVec;
// This is how the VIF is encoded in the test vectors
// It is however none norm conform, see the next example which follows
// the MBUS Norm which explicitly states that the VIIFE should be after the VIF
// not aftter the ASCII plain text and its size
// VIF LEN(3) 'R' 'H' '%' VIFE
//0xFC, 0x03, 0x48, 0x52, 0x25, 0x74,
// 0xFC, 0x03, 0x48, 0x52, 0x25, 0x74,
// %RH
// VIFE = 0x74 => E111 0nnn Multiplicative correction factor for value (not unit): 10nnn–6 => 10^-2
let data = [0xFC, 0x03, 0x48, 0x52, 0x25, 0x74];
let mut a = ArrayVec::<u8, 10>::new();
a.try_extend_from_slice(&data[2..5]).unwrap();
Expand All @@ -371,8 +369,11 @@ mod tests {
use arrayvec::ArrayVec;
// This is the ascii conform method of encoding the VIF
// VIF VIFE LEN(3) 'R' 'H' '%'
//0xFC, 0x74, 0x03, 0x48, 0x52, 0x25,
// 0xFC, 0x74, 0x03, 0x48, 0x52, 0x25,
// %RH
// Combinable (orthogonal) VIFE-Code extension table
// VIFE = 0x74 => E111 0nnn Multiplicative correction factor for value (not unit): 10nnn–6 => 10^-2
//
let data = [0xFC, 0x74, 0x03, 0x48, 0x52, 0x25];
let mut a = ArrayVec::<u8, 10>::new();
a.try_extend_from_slice(&data[2..5]).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions src/user_data/variable_user_data.rs
@@ -1,5 +1,5 @@
use super::data_information::FunctionField;
use super::data_information::{self, DataInformation};
use super::data_information::{self, DataInformationField};
use super::value_information::{self, Unit, ValueInformation};
use super::DataRecords;

Expand Down Expand Up @@ -124,7 +124,7 @@ impl From<value_information::ValueInformationError> for DataRecordError {
impl TryFrom<&[u8]> for DataRecord {
type Error = DataRecordError;
fn try_from(data: &[u8]) -> Result<DataRecord, DataRecordError> {
let data_information = DataInformation::try_from(data)?;
let data_information = DataInformationField::try_from(data)?;
let value_information = ValueInformation::try_from(&data[1..])?;
let value_and_data_information_size =
data_information.get_size() + value_information.get_size();
Expand Down

0 comments on commit 0af21ed

Please sign in to comment.