xio_hwdb/
lib.rs

1#![deny(missing_docs)]
2
3//! The data structures for representing a XIO hardware database.
4
5#[macro_use]
6extern crate serde_derive;
7
8#[macro_use]
9extern crate serde_hex;
10
11#[cfg(test)]
12#[macro_use]
13extern crate serde_json;
14
15#[cfg(not(test))]
16extern crate serde_json;
17
18extern crate indexmap;
19extern crate ommui_file_loading;
20extern crate ommui_string_patterns;
21extern crate serde;
22extern crate uuid;
23extern crate xio_base_datatypes;
24
25use ommui_string_patterns::{freetextstring, idstring};
26use std::collections::BTreeMap;
27use uuid::Uuid;
28use xio_base_datatypes as base;
29
30mod hexnumber;
31
32/// Functionality for loading a XIO hardware database from files.
33pub mod filesystem;
34
35/// The description of a device.
36#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
37#[serde(rename_all = "camelCase", deny_unknown_fields)]
38pub struct DeviceDescription {
39    /// Description of the FTDI flashing chip.
40    pub ftdi: FtdiDescription,
41
42    /// Description of the XIO properties.
43    pub xio: Option<XioDescription>,
44
45    /// Description of the system.
46    pub system: SystemDescription,
47
48    /// Summary of the device status.
49    pub summary: SummaryDescription,
50}
51
52/// The description of a connected device recognized by FTDI chip.
53#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
54#[serde(rename_all = "camelCase", deny_unknown_fields)]
55pub struct FtdiDescription {
56    /// The string identifier stored in the FTDI EEPROM.
57    pub id: String,
58
59    /// The vendor string stored in the FTDI EEPROM.
60    pub vendor: String,
61
62    /// The product string stored in the FTDI EEPROM.
63    pub product: String,
64
65    /// The uuid stored in the FTDI EEPROM.
66    pub uuid: Uuid,
67
68    /// A flag indicating if the device is recognized.
69    pub recognized: bool,
70
71    /// A flag indicating if the device is programmed (a.k.a. flashed).
72    pub programmed: bool,
73
74    /// Board identifier string.
75    pub board: String,
76
77    /// Device path.
78    pub device: String,
79
80    /// Named symlink to the device.
81    pub symlink: String,
82}
83
84/// The description of a connected device recognized through USB.
85#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
86#[serde(rename_all = "camelCase", deny_unknown_fields)]
87pub struct XioDescription {
88    /// Id of the device.
89    pub id: String,
90
91    /// USB vendor string of the device.
92    pub vendor: String,
93
94    /// USB product string of the device.
95    pub product: String,
96
97    /// Device uuid.
98    pub uuid: Uuid,
99
100    /// Flag indicating if the device is recognized.
101    pub recognized: bool,
102
103    /// Flag indicating if the device is programmed (a.k.a. flashed).
104    pub programmed: bool,
105
106    /// Board identifier string.
107    pub board: String,
108
109    /// Device path.
110    pub device: String,
111
112    /// Named symlink to the device.
113    pub symlink: String,
114
115    /// Version string of the firmware running on the device.
116    pub version: String,
117}
118
119/// Systems description of a XIO device.
120#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
121#[serde(rename_all = "camelCase", deny_unknown_fields)]
122pub struct SystemDescription {
123    /// Version of the device.
124    pub version: String,
125
126    /// Version string of the firmware running on the device.
127    pub firmware: String,
128}
129
130/// Summary information of a XIO device.
131#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
132#[serde(rename_all = "camelCase", deny_unknown_fields)]
133pub struct SummaryDescription {
134    /// Flag indicating if the device is ready.
135    pub ready: bool,
136}
137
138/// Description of a XIO device hardware board type.
139#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
140#[serde(rename_all = "camelCase", deny_unknown_fields)]
141pub struct HardwareBoardDescription {
142    /// Name of the board.
143    #[serde(rename = "_caption", with = "freetextstring")]
144    pub caption: String,
145
146    /// Generic description of the board.
147    pub description: GenericDescription,
148
149    /// Capabilities provided by the board.
150    pub capabilities: BTreeMap<String, Capability>,
151}
152
153/// Generic description of some device properties.
154#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
155#[serde(rename_all = "camelCase", deny_unknown_fields)]
156pub struct GenericDescription {
157    /// Vendor of the device.
158    #[serde(with = "freetextstring")]
159    pub vendor: String,
160
161    /// Model name of the device.
162    #[serde(with = "freetextstring")]
163    pub model: String,
164}
165
166/// A capability implemented in a XIO device.
167#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
168#[serde(rename_all = "camelCase", deny_unknown_fields)]
169pub struct Capability {
170    /// Flag indicating if the capability is built into the device.
171    pub builtin: bool,
172
173    /// String identifier of the module type.
174    ///
175    /// The module must be present in the modules collection that
176    /// can be loaded through the `filesystem::HardwareDatabase`.
177    #[serde(with = "idstring")]
178    pub module: String,
179
180    /// The index number of the capability within the XIO device.
181    #[serde(with = "hexnumber")]
182    pub id: u16,
183}
184
185#[cfg(test)]
186mod capability_tests {
187    extern crate serde_json;
188    use super::Capability;
189
190    #[test]
191    fn deserialize_hex() {
192        let json =
193            json!({ "builtin": true, "module": "xyz", "id": "0x1234"});
194        let cap: Capability =
195            serde_json::from_str(&json.to_string()).unwrap();
196        assert_eq!(
197            cap,
198            Capability {
199                builtin: true,
200                module: "xyz".to_string(),
201                id: 0x1234,
202            }
203        );
204        assert_eq!(serde_json::to_value(cap).unwrap(), json);
205    }
206
207    #[test]
208    fn deserialize_hex_zero() {
209        let json =
210            json!({ "builtin": true, "module": "xyz", "id": "0x0000"});
211        let cap: Capability =
212            serde_json::from_str(&json.to_string()).unwrap();
213        assert_eq!(
214            cap,
215            Capability {
216                builtin: true,
217                module: "xyz".to_string(),
218                id: 0,
219            }
220        );
221        assert_eq!(serde_json::to_value(cap).unwrap(), json);
222    }
223
224    #[test]
225    fn deserialize() {
226        let json = json!({ "builtin": true, "module": "xyz", "id": 1234});
227        let cap: Capability =
228            serde_json::from_str(&json.to_string()).unwrap();
229        assert_eq!(
230            cap,
231            Capability {
232                builtin: true,
233                module: "xyz".to_string(),
234                id: 1234,
235            }
236        );
237        let json_hex =
238            json!({ "builtin": true, "module": "xyz", "id": "0x04d2"});
239        assert_eq!(serde_json::to_value(cap).unwrap(), json_hex);
240    }
241}
242
243/// Description of a XIO module.
244///
245/// This describes the functionality that can be provided by a
246/// module. A XIO board can have multiple capabilities referencing
247/// the same module description. If a board has e.g. two A/D converters
248/// of the same type, there are two capabilities which reference the
249/// same module id.
250#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
251#[serde(rename_all = "camelCase", deny_unknown_fields)]
252pub struct Module {
253    /// Caption of the module.
254    #[serde(rename = "_caption", with = "freetextstring")]
255    pub caption: String,
256
257    /// Generic description of the module.
258    pub description: GenericDescription,
259
260    /// List of channels provided by the module.
261    pub channels: Vec<Channel>,
262}
263
264/// Description of a channel available in a XIO module.
265#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
266#[serde(rename_all = "camelCase", deny_unknown_fields)]
267pub struct Channel {
268    /// String identifier of the module.
269    ///
270    /// Must be unique among all channels that are contained in a module.
271    #[serde(with = "idstring")]
272    pub id: String,
273
274    /// Caption of the channel.
275    #[serde(rename = "_caption", with = "freetextstring")]
276    pub caption: String,
277
278    /// Dataype of the channel value.
279    #[serde(rename = "type")]
280    pub channel_type: base::DataType,
281
282    /// Access permissions of the channel.
283    pub permission: base::ChannelPermission,
284}