gsof_protocol 0.1.23

Software to collect data generated by sources who provide GSOF messages (Trimble)
Documentation
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use std::path::Path;
use std::fs::File;
use std::io::BufReader;

// const path = Path::new(format!("{}",file!())).parent().unwrap();
// pub const PROTOCOL_FILE:&str = format!("{:?}/{}", path, "gsof_protocol.json");

/// An enum of possible values for a gsof table
#[derive(Debug, Serialize, Deserialize,Clone)]
pub enum Value {
    String,
    I8,
    U8,
    I16,
    U16,
    I32,
    U32,
    I64,
    U64,
    F32,
    F64,
    Bool,
}

#[doc = r#"
This is to take the data from json file and load in a structure.
Represents a particular item that describe the metadata for a table.
"#]
#[derive(Debug, Serialize, Deserialize)]
pub struct TableMetaData {
    pub name: String,
    pub fields : Vec<String>,
    pub conversion: Vec<String>
}

impl TableMetaData{
	/// Implements a serialization method
    pub fn json_dumps(&self) -> String {
        serde_json::to_string_pretty(&self).unwrap()
    }

	/// Implements a deserialization method
    pub fn json_loads(serialized: &str) -> Self {
        serde_json::from_str(&serialized).unwrap()
    }
}


/*

TableSet group, in a like dict, a hashmap all the table readed identified by a
number. The number is the table identification assigned on the Gsof protocol
 */
pub type TableSet = HashMap<u8,TableMetaData>;


/*
Read a json file structured a TableSet
 */
pub fn read_file_protocol<P: AsRef<Path>>(
    path:P
) -> Result<TableSet,Box<dyn std::error::Error>> {
    let file = File::open(path)?;
    let reader = BufReader::new(file);
    let u = serde_json::from_reader(reader)?;
    Ok(u)
}

/*
Read a particular json file save here
 */
pub fn read_gsof_file_protocol(
) -> Result<TableSet,Box<dyn std::error::Error>> {
	/*
	This is a embedded file that could be showed using a command
	 */
    let protocol_file = include_str!("gsof_protocol.json");
    let jsondata = serde_json::from_str(&protocol_file)?;
    Ok(jsondata)
}



/*
Define a trait to put in common among the tables defined by Gsof
 */
pub trait GsofTable {
    fn table_name(&self) -> &str;
}

/// Next tables are defined to recognize gsof tables as are formatted.

/// Head table contains all the information to retrieve the body and
/// tail of message
#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct HeadTable {
    pub stx: u8,
    pub status: u8,
    pub mtype: u8,
    pub length: u8,
    pub t_num: u8,
    pub page_index: u8,
    pub max_page_index: u8,
}

impl GsofTable for HeadTable {
	/// Returns the table name for HeadTable
    fn table_name(&self)->&str {
        "HEADER"
    }
}

impl HeadTable {
	/// Load a tuple with ordered values in the struct HeadTable
    pub fn new(values:(u8,u8,u8,u8,u8,u8,u8))->Self {
        let (stx, status, mtype, length, t_num, page_index, max_page_index) = values;
        HeadTable {
            stx,
            status,
            mtype,
            length,
            t_num,
            page_index,
            max_page_index            
        }
    }
}




/// GPSTimeTable contains all the values related to the description of
/// the time in terms of GPS taken data
#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct GPSTimeTable {
    pub gps_time: u32,
    pub gps_week: u16,
    pub svn_num: u8,
    // https://www.trimble.com/OEM_ReceiverHelp/v5.11/en/GSOFmessages_Flags.html#Position flags 1
    pub flags_1: u8,
    pub flags_2: u8,
    pub init_num: u8,
}


impl GsofTable for GPSTimeTable {
	/// Returns the table name for GPSTimeTable
    fn table_name(&self)->&str {
        "TIME"
    }
}

impl GPSTimeTable {
	/// Load a tuple with ordered values in the struct GPSTimeTable
    pub fn new(values:(u32,u16,u8,u8,u8,u8))->Self {
        GPSTimeTable {
            gps_time: values.0,
            gps_week: values.1,
            svn_num: values.2,
            flags_1: values.3,
            flags_2: values.4,
            init_num: values.5,
        }
    }
}

////////////////////

/// Define the ECEFTable table that describes the geographic position
/// in cartesian projection
#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct ECEFTable {
    pub x_pos: f64,
    pub y_pos: f64,
    pub z_pos: f64,
}


impl GsofTable for ECEFTable {
	/// Returns the table name for ECEFTable
    fn table_name(&self)->&str {
        "ECEF"
    }
}

impl ECEFTable {
	/// Load a tuple with ordered values in the struct ECEFTable
    pub fn new(values:(f64,f64,f64))->Self {
        ECEFTable {
            x_pos: values.0,
            y_pos: values.1,
            z_pos: values.2,
        }
    }
}



////////////////////
/// SIGMATable contains all the information related to the errors
/// related to the calculation of position. Is used to estimate
/// difference respect a reference and error matrix.
#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct SIGMATable {
    pub position_rms_sig: f32,
    pub sig_east: f32,
    pub sig_nort: f32,
    pub covar_en: f32,
    pub sig_up: f32,
    pub semi_major: f32,
    pub semi_minor: f32,
    pub orientation: f32,
    pub unit_var_sig: f32,
    pub num_eposh_sig:u16
}


impl GsofTable for SIGMATable {

	/// Returns the table name for SIGMATable
    fn table_name(&self)->&str {
        "SIGMA"
    }
}

impl SIGMATable {

	/// Load a tuple with ordered values in the struct SIGMATable
    pub fn new(values:(f32,f32,f32,f32,f32,f32,f32,f32,f32,u16))->Self {
        SIGMATable {
             position_rms_sig: values.0,
             sig_east: values.1,
             sig_nort: values.2,
             covar_en: values.3,
             sig_up: values.4,
             semi_major: values.5,
             semi_minor: values.6,
             orientation: values.7,
             unit_var_sig: values.8,
             num_eposh_sig:values.9
        }
    }
}

////////////////////


////////////////////
/// PositionVCV has the data related to matrix variance covariance
/*
            "POSITION_RMS_VCV",
            "VCV_XX",
            "VCV_XY",
            "VCV_XZ",
            "VCV_YY",
            "VCV_YZ",
            "VCV_ZZ",
            "UNIT_VAR_VCV",
            "NUM_EPOCHS_VCV"

*/

#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct PositionVCV {
    pub position_rms: f32,
    pub xx: f32,
    pub xy: f32,
    pub xz: f32,
    pub yy: f32,
    pub yz: f32,
    pub zz: f32,
    pub unit_var: f32,
    pub num_epochs: i16,
}


impl GsofTable for PositionVCV {

	/// Returns the table name for SIGMATable
    fn table_name(&self)->&str {
        "PositionVCV"
    }

}


impl PositionVCV {
	/// Load a tuple with ordered values in the struct SIGMATable
    pub fn new(values:(f32,f32,f32,f32,f32,f32,f32,f32,i16))->Self {

        Self {
			position_rms: values.0,
			xx: values.1,
			xy: values.2,
			xz: values.3,
			yy: values.4,
			yz: values.5,
			zz: values.6,
			unit_var: values.7,
			num_epochs: values.8,
        }
    }
}



///////////////////

/// BattMemTable contains the values related to the general status for
/// memmory and battery available.
#[derive(Debug, Serialize, Deserialize,Clone, Copy)]
pub struct BattMemTable {
    batt_capacity: u16,
    remaining_mem: f64,
}


impl GsofTable for BattMemTable {

	/// Returns the table name for BattMemTable
    fn table_name(&self)->&str {
        "BATT_MEM"
    }
}

impl BattMemTable {

	/// Load a tuple with ordered values in the struct BattMemTable
    pub fn new(values:(u16,f64))->Self {
        BattMemTable {
            batt_capacity: values.0,
            remaining_mem: values.1,
        }
    }
}

////////////////////

type BaseTable = HashMap<String,Value>;

/// TableData is a generic table to load info structured.
#[derive(Debug, Serialize, Deserialize,Clone)]
pub struct TableData {
    name: String,
    values: BaseTable
}


impl Default for TableData {
    fn default() -> Self {
        let dict = HashMap::new();
        TableData{
            name: "default".to_string(),
            values: dict            
        }
    }
}

impl TableData {
    pub fn json_dumps(&self) -> String {
        serde_json::to_string_pretty(&self).unwrap()
    }
    pub fn json_loads(serialized: &str) -> Self {
        serde_json::from_str(serialized).unwrap()
    }
    
	/// Serialize to serde::Value
    pub fn json_to_value(&self) -> serde_json::Value {
        serde_json::to_value(self).unwrap()
    }

	/// Deserialize frm serde::Value
    pub fn json_from_value(value:&serde_json::Value) -> Self {
        serde_json::from_value(value.clone()).unwrap()
    }

}