1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//
// Copyright (C) 2018 Kubos Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use super::*;
use nom::*;

const COMPONENT_SIZE: usize = 108;

/// Log message containing version information
#[derive(Clone, Default, Debug, PartialEq)]
pub struct VersionLog {
    /// Current status of receiver
    pub recv_status: ReceiverStatusFlags,
    /// Validity of the time information
    pub time_status: u8,
    /// GPS reference week
    pub week: u16,
    /// Milliseconds into GPS reference week
    pub ms: i32,
    /// Number of components present in this structure
    pub num_components: u32,
    /// Version information for each component present in the system
    pub components: Vec<Component>,
}

impl VersionLog {
    /// Convert a raw data buffer into a useable struct
    pub fn new(
        recv_status: ReceiverStatusFlags,
        time_status: u8,
        week: u16,
        ms: i32,
        mut raw: Vec<u8>,
    ) -> Option<Self> {
        let raw_comp = raw.split_off(4);

        let mut log = VersionLog {
            recv_status,
            time_status,
            week,
            ms,
            num_components: {
                match le_u32(&raw) {
                    Ok(v) => v.1,
                    Err(_) => return None,
                }
            },
            components: vec![],
        };

        for elem in raw_comp.chunks(COMPONENT_SIZE) {
            if let Ok(conv) = parse_component(elem) {
                log.components.push(conv.1);
            }
        }

        Some(log)
    }
}

/// Version information about a specific system component
#[derive(Clone, Default, Debug, PartialEq)]
pub struct Component {
    /// The component type which the version info is about
    pub comp_type: u32,
    /// Model number
    pub model: String,
    /// Serial number
    pub serial_num: String,
    /// Hardware version
    pub hw_version: String,
    /// Software version
    pub sw_version: String,
    /// Boot code version
    pub boot_version: String,
    /// Software compilation date stamp
    pub compile_date: String,
    /// Software compilation time stamp
    pub compile_time: String,
}

named!(parse_component(&[u8]) -> Component,
    do_parse!(
        comp_type: le_u32 >>
        model: take!(16) >>
        serial_num: take!(16) >>
        hw_version: take!(16) >>
        sw_version: take!(16) >>
        boot_version: take!(16) >>
        compile_date: take!(12) >>
        compile_time: take!(12) >>
        (Component {
            comp_type,
            model: String::from_utf8_lossy(model)
                            .trim_end_matches('\u{0}').to_owned(),
            serial_num: String::from_utf8_lossy(serial_num)
                            .trim_end_matches('\u{0}').to_owned(),
            hw_version: String::from_utf8_lossy(hw_version)
                            .trim_end_matches('\u{0}').to_owned(),
            sw_version: String::from_utf8_lossy(sw_version)
                            .trim_end_matches('\u{0}').to_owned(),
            boot_version: String::from_utf8_lossy(boot_version)
                            .trim_end_matches('\u{0}').to_owned(),
            compile_date: String::from_utf8_lossy(compile_date)
                            .trim_end_matches('\u{0}').to_owned(),
            compile_time: String::from_utf8_lossy(compile_time)
                            .trim_end_matches('\u{0}').to_owned(),
            }
        )
    )
);