Skip to content

Commit

Permalink
Feature check_a2l
Browse files Browse the repository at this point in the history
  • Loading branch information
RainerZ committed Sep 28, 2024
1 parent a3a1222 commit a6f9a01
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 98 deletions.
50 changes: 47 additions & 3 deletions src/reg/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,33 @@ impl Registry {
self.characteristic_list.iter().find(|c| c.name == name)
}

#[cfg(feature = "check_a2l")]
pub fn a2l_load(&mut self, filename: &str) -> Result<a2lfile::A2lFile, a2lfile::A2lError> {
trace!("Load A2L file {}", filename);
let input_filename = &std::ffi::OsString::from(filename);
let mut logmsgs = Vec::<a2lfile::A2lError>::new();
let res = a2lfile::load(input_filename, None, &mut logmsgs, true);
for log_msg in logmsgs {
warn!("A2l Loader: {}", log_msg);
}
match res {
Ok(a2l_file) => {
// Perform a consistency check
let mut logmsgs = Vec::<String>::new();
a2l_file.check(&mut logmsgs);
for log_msg in logmsgs {
warn!("A2l Checker: {}", log_msg);
}
Ok(a2l_file)
}

Err(e) => {
error!("a2lfile::load failed: {:?}", e);
Err(e)
}
}
}

/// Generate A2L file from registry
pub fn write_a2l(&mut self) -> Result<(), std::io::Error> {
// Error if registry is closed
Expand All @@ -743,13 +770,30 @@ impl Registry {
}

// Sort measurement and calibration lists to get deterministic order
// Event and CalSeg lists stay in the order they were added
// Event and CalSeg lists stay in the order the were added
self.measurement_list.sort();
self.characteristic_list.sort();

// Write to A2L file
let writer = A2lWriter::new();
writer.write_a2l(self)
let a2l_name = self.name.unwrap();
let a2l_path = format!("{}.a2l", a2l_name);
let a2l_file = std::fs::File::create(&a2l_path)?;
let a2l_file_writer: &mut dyn std::io::Write = &mut std::io::LineWriter::new(a2l_file);
let mut writer = A2lWriter::new(a2l_file_writer);
writer.write_a2l(a2l_name, a2l_name, self)?;

// @@@@ Dev
// Check A2L file
#[cfg(feature = "check_a2l")]
{
if let Err(e) = self.a2l_load(&a2l_path) {
error!("a2lfile::load failed: {:?}", e);
} else {
info!("A2L file check ok");
}
}

Ok(())
}
}

Expand Down
139 changes: 44 additions & 95 deletions src/reg/registry/a2l_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// Sub Module a2l_writer
// Export an A2L file from super::registry

use std::{
fs::File,
io::{LineWriter, Write},
};
use std::io::Write;

#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
Expand Down Expand Up @@ -268,19 +265,18 @@ impl GenerateA2l for RegistryCharacteristic {

//-------------------------------------------------------------------------------------------------

#[derive(Debug)]
pub struct A2lWriter {}
pub struct A2lWriter<'a> {
writer: &'a mut dyn Write,
}

impl A2lWriter {
pub fn new() -> A2lWriter {
A2lWriter {}
impl<'a> A2lWriter<'a> {
pub fn new(writer: &'a mut dyn Write) -> A2lWriter {
A2lWriter { writer }
}

fn write_a2l_head(&self, writer: &mut dyn Write, a2l_name: &str) -> std::io::Result<()> {
let project_name = a2l_name;
let module_name = a2l_name;
fn write_a2l_head(&mut self, project_name: &str, module_name: &str) -> std::io::Result<()> {
write!(
writer,
self.writer,
r#"
ASAP2_VERSION 1 71
/begin PROJECT {project_name} ""
Expand Down Expand Up @@ -343,24 +339,24 @@ impl A2lWriter {
)
}

fn write_a2l_modpar(&self, writer: &mut dyn Write, registry: &Registry) -> std::io::Result<()> {
fn write_a2l_modpar(&mut self, registry: &Registry) -> std::io::Result<()> {
// EPK segment
let mod_par = &registry.mod_par;

// // Memory segments from calibration segments
let memory_segments = &registry.cal_seg_list;

write!(writer, "\n\t\t/begin MOD_PAR \"\"")?;
write!(self.writer, "\n\t\t/begin MOD_PAR \"\"")?;

mod_par.write_a2l(writer)?;
memory_segments.write_a2l(writer)?;
mod_par.write_a2l(self.writer)?;
memory_segments.write_a2l(self.writer)?;

writeln!(writer, "\n\t\t/end MOD_PAR")
writeln!(self.writer, "\n\t\t/end MOD_PAR")
}

fn write_a2l_if_data(&self, writer: &mut dyn Write, registry: &Registry) -> std::io::Result<()> {
fn write_a2l_if_data(&mut self, registry: &Registry) -> std::io::Result<()> {
write!(
writer,
self.writer,
r#"
/begin IF_DATA XCP
/begin PROTOCOL_LAYER
Expand Down Expand Up @@ -398,7 +394,7 @@ impl A2lWriter {

let event_count = registry.event_list.len();
write!(
writer,
self.writer,
"\n\n\t\t\t/begin DAQ
DYNAMIC 0 {event_count} 0 OPTIMISATION_TYPE_DEFAULT ADDRESS_EXTENSION_FREE IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE GRANULARITY_ODT_ENTRY_SIZE_DAQ_BYTE 0xF8 OVERLOAD_INDICATION_PID
/begin TIMESTAMP_SUPPORTED
Expand All @@ -409,24 +405,24 @@ impl A2lWriter {

// Eventlist
for e in registry.event_list.iter() {
e.write_a2l(writer)?
e.write_a2l(self.writer)?
}

write!(writer, "\n\t\t\t/end DAQ\n")?;
write!(self.writer, "\n\t\t\t/end DAQ\n")?;

// Transport layer parameters in IF_DATA
if let Some(tl_params) = registry.tl_params {
tl_params.write_a2l(writer)?;
tl_params.write_a2l(self.writer)?;
}

write!(writer, "\n\t\t/end IF_DATA\n")?;
write!(self.writer, "\n\t\t/end IF_DATA\n")?;
Ok(())
}

fn write_a2l_measurements(&self, writer: &mut dyn Write, registry: &Registry) -> std::io::Result<()> {
fn write_a2l_measurements(&mut self, registry: &Registry) -> std::io::Result<()> {
// Measurements
for m in registry.measurement_list.iter() {
m.write_a2l(writer)?;
m.write_a2l(self.writer)?;
}

// Create a root measurement group for each event, if more than one element
Expand All @@ -436,24 +432,24 @@ impl A2lWriter {
continue;
}
if registry.measurement_list.iter().filter(|m| m.event.get_name() == e.get_name()).count() > 1 {
write!(writer, "\n/begin GROUP {} \"\" ROOT /begin REF_MEASUREMENT", e.get_name())?;
write!(self.writer, "\n/begin GROUP {} \"\" ROOT /begin REF_MEASUREMENT", e.get_name())?;
for m in registry.measurement_list.iter() {
if m.event.get_name() == e.get_name() {
write!(writer, " {}", m.name)?;
write!(self.writer, " {}", m.name)?;
}
}
write!(writer, " /end REF_MEASUREMENT /end GROUP")?;
write!(self.writer, " /end REF_MEASUREMENT /end GROUP")?;
}
}

Ok(())
}

fn write_a2l_characteristics(&self, writer: &mut dyn Write, registry: &Registry) -> std::io::Result<()> {
fn write_a2l_characteristics(&mut self, registry: &Registry) -> std::io::Result<()> {
// Characteristics not in a in calibration segment
for c in registry.characteristic_list.iter() {
if c.calseg_name.is_none() {
c.write_a2l(writer)?;
c.write_a2l(self.writer)?;
}
}

Expand All @@ -463,54 +459,27 @@ impl A2lWriter {
for c in registry.characteristic_list.iter() {
if let Some(calseg_name) = c.calseg_name {
if s.name == calseg_name {
c.write_a2l(writer)?;
c.write_a2l(self.writer)?;
}
}
}
// Characteristic group for each calibration segment
write!(writer, "\n/begin GROUP {} \"\" ROOT /begin REF_CHARACTERISTIC ", s.name)?;
write!(self.writer, "\n/begin GROUP {} \"\" ROOT /begin REF_CHARACTERISTIC ", s.name)?;
for c in registry.characteristic_list.iter() {
if let Some(calseg_name) = c.calseg_name {
if s.name == calseg_name {
write!(writer, " {} ", c.name.as_str())?;
write!(self.writer, " {} ", c.name.as_str())?;
}
}
}
writeln!(writer, "/end REF_CHARACTERISTIC /end GROUP\n")?;
writeln!(self.writer, "/end REF_CHARACTERISTIC /end GROUP\n")?;
}

Ok(())
}

#[cfg(feature = "check_a2l")]
pub fn a2l_load(&self, filename: &str) -> Result<a2lfile::A2lFile, a2lfile::A2lError> {
trace!("Load A2L file {}", filename);
let input_filename = &std::ffi::OsString::from(filename);
let mut logmsgs = Vec::<a2lfile::A2lError>::new();
let res = a2lfile::load(input_filename, None, &mut logmsgs, true);
for log_msg in logmsgs {
warn!("A2l Loader: {}", log_msg);
}
match res {
Ok(a2l_file) => {
// Perform a consistency check
let mut logmsgs = Vec::<String>::new();
a2l_file.check(&mut logmsgs);
for log_msg in logmsgs {
warn!("A2l Checker: {}", log_msg);
}
Ok(a2l_file)
}

Err(e) => {
error!("a2lfile::load failed: {:?}", e);
Err(e)
}
}
}

fn write_a2l_tail(&self, writer: &mut dyn Write) -> std::io::Result<()> {
writer.write_all(
fn write_a2l_tail(&mut self) -> std::io::Result<()> {
self.writer.write_all(
r#"
/end MODULE
/end PROJECT
Expand All @@ -519,36 +488,16 @@ impl A2lWriter {
)
}

pub fn write_a2l(&self, registry: &Registry) -> Result<(), std::io::Error> {
if let Some(a2l_name) = &registry.name {
// Write to file
let a2l_path = format!("{}.a2l", a2l_name);
let a2l_file = File::create(&a2l_path)?;
let a2l_file_writer: &mut dyn Write = &mut LineWriter::new(a2l_file);

self.write_a2l_head(a2l_file_writer, a2l_name)?;
self.write_a2l_modpar(a2l_file_writer, registry)?;
self.write_a2l_if_data(a2l_file_writer, registry)?;
self.write_a2l_measurements(a2l_file_writer, registry)?;
self.write_a2l_characteristics(a2l_file_writer, registry)?;
self.write_a2l_tail(a2l_file_writer)?;

info!("Write A2L file {}", a2l_path);

// @@@@ Dev
// Check A2L file
#[cfg(feature = "check_a2l")]
{
if let Err(e) = self.a2l_load(&a2l_path) {
error!("a2lfile::load failed: {:?}", e);
} else {
info!("A2L file check ok");
}
}
pub fn write_a2l(&mut self, project_name: &str, module_name: &str, registry: &Registry) -> Result<(), std::io::Error> {
self.write_a2l_head(project_name, module_name)?;
self.write_a2l_modpar(registry)?;
self.write_a2l_if_data(registry)?;
self.write_a2l_measurements(registry)?;
self.write_a2l_characteristics(registry)?;
self.write_a2l_tail()?;

Ok(())
} else {
Err(std::io::Error::new(std::io::ErrorKind::Other, "No name set"))
}
info!("Write A2L file {},{}", project_name, module_name);

Ok(())
}
}

0 comments on commit a6f9a01

Please sign in to comment.