├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples └── basic.rs ├── src ├── lib.rs ├── parser │ ├── conversions.rs │ └── mod.rs └── structs.rs └── tests ├── fixtures ├── Beckhoff_EK11xx.xml ├── Weidmueller_UR20_FBC.xml ├── Weidmueller_UR20_FBC_from_IgH.xml └── Weidmueller_UR20_IO.xml └── parse-xml.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ethercat-esi" 3 | description = "Handle EtherCAT Slave Information (ESI)" 4 | version = "0.2.0" 5 | authors = ["slowtec GmbH "] 6 | license = "MIT/Apache-2.0" 7 | readme = "README.md" 8 | keywords = ["fieldbus", "ethercat", "industrial"] 9 | homepage = "https://github.com/ethercat-rs/ethercat-esi" 10 | repository = "https://github.com/ethercat-rs/ethercat-esi" 11 | edition = "2018" 12 | 13 | [dependencies] 14 | ethercat-types = "0.3" 15 | serde = { version = "1", features = ["derive"] } 16 | serde-xml-rs = "0.4" 17 | 18 | [badges] 19 | maintenance = { status = "actively-developed" } 20 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 slowtec GmbH 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EtherCAT ESI 2 | 3 | A library to handle EtherCAT Slave Information (ESI) written in Rust. 4 | 5 | ## License 6 | 7 | Copyright 2020 [slowtec GmbH](https://www.slowtec.de) 8 | 9 | MIT/Apache-2.0 10 | -------------------------------------------------------------------------------- /examples/basic.rs: -------------------------------------------------------------------------------- 1 | use ethercat_esi::EtherCatInfo; 2 | use std::{ 3 | env, 4 | fs::File, 5 | io::{self, prelude::*}, 6 | }; 7 | 8 | fn main() -> io::Result<()> { 9 | match env::args().nth(1) { 10 | None => { 11 | eprintln!("Missing filename"); 12 | } 13 | Some(file_name) => { 14 | let mut xml_file = File::open(file_name)?; 15 | let mut xml_string = String::new(); 16 | xml_file.read_to_string(&mut xml_string)?; 17 | let info = EtherCatInfo::from_xml_str(&xml_string)?; 18 | println!("{:#?}", info); 19 | } 20 | } 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # EtherCAT Slave Information (ESI). 2 | //! 3 | //! The EtherCAT Slave Information (ESI) file is an XML file that is used by 4 | //! some EtherCAT master stacks to configure the slaves and generate network 5 | //! description files. 6 | //! However, it's main purpose is to describe how data is shared with the 7 | //! slave, including what sync managers it uses, and what PDOs are in 8 | //! each sync manager. 9 | //! 10 | //! The official XML schema can be found in the 11 | //! *[EtherCAT Slave Information (ESI) Schema](https://www.ethercat.org/en/downloads/downloads_981F0A9A81044A878CE329DC8818F495.htm)* 12 | //! (see `EtherCATInfo.xsd`). 13 | //! 14 | //! ## Example 15 | //! 16 | //! ```rust 17 | //! use ethercat_esi::EtherCatInfo; 18 | //! use std::{ 19 | //! env, 20 | //! fs::File, 21 | //! io::{self, prelude::*}, 22 | //! }; 23 | //! 24 | //! fn main() -> io::Result<()> { 25 | //! match env::args().nth(1) { 26 | //! None => { 27 | //! eprintln!("Missing filename"); 28 | //! } 29 | //! Some(file_name) => { 30 | //! let mut xml_file = File::open(file_name)?; 31 | //! let mut xml_string = String::new(); 32 | //! xml_file.read_to_string(&mut xml_string)?; 33 | //! let info = EtherCatInfo::from_xml_str(&xml_string)?; 34 | //! println!("{:#?}", info); 35 | //! } 36 | //! } 37 | //! Ok(()) 38 | //! } 39 | //! ``` 40 | 41 | use std::{ 42 | convert::TryInto, 43 | io::{Error, ErrorKind, Result}, 44 | }; 45 | 46 | mod parser; 47 | mod structs; 48 | 49 | pub use structs::*; 50 | 51 | impl EtherCatInfo { 52 | pub fn from_xml_str(xml: &str) -> Result { 53 | let raw_info: parser::EtherCATInfo = serde_xml_rs::from_reader(xml.as_bytes()) 54 | .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?; 55 | raw_info.try_into() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/parser/conversions.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::structs as S; 3 | use ethercat_types as ec; 4 | use std::{convert::TryFrom, num::ParseIntError, str::FromStr}; 5 | 6 | impl TryFrom for S::EtherCatInfo { 7 | type Error = Error; 8 | fn try_from(x: EtherCATInfo) -> Result { 9 | let mut description = match x.Descriptions { 10 | Some(d) => d.try_into()?, 11 | None => S::Description::default(), 12 | }; 13 | 14 | if let Some(Modules { 15 | items: Some(modules), 16 | }) = x.Modules 17 | { 18 | modules 19 | .into_iter() 20 | .map(S::Module::try_from) 21 | .collect::>>()? 22 | .into_iter() 23 | .for_each(|m| { 24 | description.modules.push(m); 25 | }) 26 | } 27 | 28 | Ok(S::EtherCatInfo { 29 | version: x.Version, 30 | info_reference: x.InfoReference, 31 | vendor: x.Vendor.try_into()?, 32 | description, 33 | }) 34 | } 35 | } 36 | 37 | impl TryFrom for S::Vendor { 38 | type Error = Error; 39 | fn try_from(v: Vendor) -> Result { 40 | let image = v.image()?; 41 | Ok(S::Vendor { 42 | file_version: v.FileVersion, 43 | id: u32_from_hex_dec_value(&v.Id)?, 44 | name: names_from(v.Name.unwrap_or_default())?, 45 | comment: v.Comment, 46 | url: v.URL, 47 | desc_url: v.DescriptionURL, 48 | image, 49 | }) 50 | } 51 | } 52 | 53 | impl Vendor { 54 | fn image(&self) -> Result> { 55 | match (&self.Image16x14, &self.ImageFile16x14, &self.ImageData16x14) { 56 | (None, None, None) => Ok(None), 57 | (Some(img), None, None) => Ok(Some(S::Image::Image16x14(img.clone()))), 58 | (None, Some(img), None) => Ok(Some(S::Image::ImageFile16x14(img.clone()))), 59 | (None, None, Some(img)) => { 60 | Ok(Some(S::Image::ImageData16x14(S::HexBinary(img.clone())))) 61 | } 62 | _ => Err(Error::new(ErrorKind::Other, "Multiple images found")), 63 | } 64 | } 65 | } 66 | 67 | impl Group { 68 | fn image(&self) -> Result> { 69 | let img = self.items.iter().filter(|p| match p { 70 | GroupProperty::Image16x14(_) 71 | | GroupProperty::ImageFile16x14(_) 72 | | GroupProperty::ImageData16x14(_) => true, 73 | _ => false, 74 | }); 75 | if img.clone().count() > 1 { 76 | return Err(Error::new(ErrorKind::Other, "Multiple images found")); 77 | } 78 | for p in img { 79 | match p { 80 | GroupProperty::Image16x14(img) => { 81 | return Ok(Some(S::Image::Image16x14(img.clone()))) 82 | } 83 | GroupProperty::ImageFile16x14(img) => { 84 | return Ok(Some(S::Image::ImageFile16x14(img.clone()))) 85 | } 86 | GroupProperty::ImageData16x14(img) => { 87 | return Ok(Some(S::Image::ImageData16x14(S::HexBinary(img.clone())))) 88 | } 89 | _ => {} 90 | } 91 | } 92 | Ok(None) 93 | } 94 | } 95 | 96 | impl TryFrom for S::Description { 97 | type Error = Error; 98 | fn try_from(d: Descriptions) -> Result { 99 | let groups: Vec<_> = d 100 | .Groups 101 | .map(|groups| { 102 | groups 103 | .items 104 | .map(|items| items.into_iter().map(S::Group::try_from).collect()) 105 | .unwrap_or_else(|| Ok(vec![])) 106 | }) 107 | .unwrap_or_else(|| Ok(vec![]))?; 108 | 109 | let devices: Vec<_> = d 110 | .Devices 111 | .items 112 | .unwrap_or_else(Vec::new) 113 | .into_iter() 114 | .map(S::Device::try_from) 115 | .collect::>()?; 116 | 117 | let modules: Vec<_> = d 118 | .Modules 119 | .map(|dev| { 120 | dev.items 121 | .map(|items| items.into_iter().map(S::Module::try_from).collect()) 122 | .unwrap_or_else(|| Ok(vec![])) 123 | }) 124 | .unwrap_or_else(|| Ok(vec![]))?; 125 | 126 | Ok(S::Description { 127 | groups, 128 | devices, 129 | modules, 130 | }) 131 | } 132 | } 133 | 134 | impl TryFrom for S::Group { 135 | type Error = Error; 136 | fn try_from(g: Group) -> Result { 137 | let image = g.image()?; 138 | let comment = g 139 | .items 140 | .iter() 141 | .filter_map(|p| { 142 | if let GroupProperty::Comment(c) = p { 143 | Some(c) 144 | } else { 145 | None 146 | } 147 | }) 148 | .cloned() 149 | .next(); 150 | 151 | let props = g.items.iter(); 152 | let name = props 153 | .clone() 154 | .filter_map(|p| { 155 | if let GroupProperty::Name(n) = p { 156 | Some(names_from(n.clone())) 157 | } else { 158 | None 159 | } 160 | }) 161 | .next() 162 | .ok_or_else(|| Error::new(ErrorKind::Other, "Mandatory group name not found"))??; 163 | 164 | let r#type = props 165 | .filter_map(|p| { 166 | if let GroupProperty::Type(t) = p { 167 | Some(t) 168 | } else { 169 | None 170 | } 171 | }) 172 | .cloned() 173 | .next() 174 | .ok_or_else(|| Error::new(ErrorKind::Other, "Mandatory group type not found"))?; 175 | 176 | Ok(S::Group { 177 | sort_order: g.SortOrder, 178 | parent_group: g.ParentGroup, 179 | name, 180 | comment, 181 | r#type, 182 | image, 183 | }) 184 | } 185 | } 186 | 187 | impl TryFrom for S::Device { 188 | type Error = Error; 189 | fn try_from(d: Device) -> Result { 190 | let props = d.items.iter(); 191 | let name = props 192 | .clone() 193 | .filter_map(|p| { 194 | if let DeviceProperty::Name(n) = p { 195 | Some(names_from(n.clone())) 196 | } else { 197 | None 198 | } 199 | }) 200 | .next() 201 | .ok_or_else(|| Error::new(ErrorKind::Other, "Mandatory device name not found"))??; 202 | 203 | let d_type = props 204 | .clone() 205 | .filter_map(|p| { 206 | if let DeviceProperty::Type(t) = p { 207 | Some(t) 208 | } else { 209 | None 210 | } 211 | }) 212 | .next() 213 | .ok_or_else(|| Error::new(ErrorKind::Other, "Mandatory device type not found"))?; 214 | 215 | let product_code = d_type 216 | .ProductCode 217 | .as_deref() 218 | .map(u32_from_hex_dec_value) 219 | .transpose()?; 220 | let revision_no = d_type 221 | .RevisionNo 222 | .as_deref() 223 | .map(u32_from_hex_dec_value) 224 | .transpose()?; 225 | let desc = d_type.Description.to_owned(); 226 | 227 | let sm = props 228 | .clone() 229 | .filter_map(|p| { 230 | if let DeviceProperty::Sm(sm) = p { 231 | Some(sm) 232 | } else { 233 | None 234 | } 235 | }) 236 | .cloned() 237 | .next() 238 | .unwrap_or_else(Vec::new) 239 | .into_iter() 240 | .map(S::Sm::try_from) 241 | .collect::>()?; 242 | 243 | let rx_pdo = props 244 | .clone() 245 | .filter_map(|p| { 246 | if let DeviceProperty::RxPdo(pdo) = p { 247 | Some(pdo) 248 | } else { 249 | None 250 | } 251 | }) 252 | .cloned() 253 | .next() 254 | .unwrap_or_else(Vec::new) 255 | .into_iter() 256 | .map(S::Pdo::try_from) 257 | .collect::>()?; 258 | 259 | let tx_pdo = props 260 | .clone() 261 | .filter_map(|p| { 262 | if let DeviceProperty::TxPdo(pdo) = p { 263 | Some(pdo) 264 | } else { 265 | None 266 | } 267 | }) 268 | .cloned() 269 | .next() 270 | .unwrap_or_else(Vec::new) 271 | .into_iter() 272 | .map(S::Pdo::try_from) 273 | .collect::>()?; 274 | 275 | Ok(S::Device { 276 | physics: d.Physics, 277 | name, 278 | desc, 279 | product_code, 280 | revision_no, 281 | sm, 282 | rx_pdo, 283 | tx_pdo, 284 | }) 285 | } 286 | } 287 | 288 | impl TryFrom for S::Sm { 289 | type Error = Error; 290 | fn try_from(sm: Sm) -> Result { 291 | Ok(S::Sm { 292 | start_address: u16_from_hex_dec_value(&sm.StartAddress)?, 293 | control_byte: sm 294 | .ControlByte 295 | .as_deref() 296 | .map(u8_from_hex_dec_value) 297 | .transpose()?, 298 | default_size: if let Some(x) = sm.DefaultSize { 299 | let n = u32_from_hex_dec_value(&x)?; 300 | Some(n as usize) 301 | } else { 302 | None 303 | }, 304 | enable: sm.Enable == Some(1), 305 | r#virtual: sm.Virtual.as_deref().map(bool_from_str).transpose()? == Some(true), 306 | }) 307 | } 308 | } 309 | 310 | impl TryFrom for S::Pdo { 311 | type Error = Error; 312 | fn try_from(pdo: Pdo) -> Result { 313 | Ok(S::Pdo { 314 | fixed: if let Some(s) = &pdo.Fixed { 315 | bool_from_str(s)? 316 | } else { 317 | false 318 | }, 319 | mandatory: if let Some(s) = &pdo.Mandatory { 320 | bool_from_str(s)? 321 | } else { 322 | false 323 | }, 324 | name: names_from(pdo.Name)?, 325 | sm: pdo.Sm.map(ec::SmIdx::from), 326 | idx: ec::PdoIdx::from(u16_from_hex_dec_value(&pdo.Index.value)?), 327 | entries: pdo 328 | .Entry 329 | .unwrap_or_default() 330 | .into_iter() 331 | .map(S::PdoEntry::try_from) 332 | .collect::>()?, 333 | }) 334 | } 335 | } 336 | 337 | impl TryFrom for S::PdoEntry { 338 | type Error = Error; 339 | fn try_from(e: Entry) -> Result { 340 | Ok(S::PdoEntry { 341 | entry_idx: S::PdoEntryIdx { 342 | idx: ec::Idx::from(u16_from_hex_dec_value(&e.Index.value)?), 343 | sub_idx: match e.SubIndex { 344 | Some(idx_string) => ec::SubIdx::from(u8_from_hex_dec_value(&idx_string)?), 345 | None => ec::SubIdx::from(0), 346 | }, 347 | }, 348 | bit_len: e.BitLen, 349 | name: names_from(e.Name.unwrap_or_default())?, 350 | data_type: e.DataType, 351 | }) 352 | } 353 | } 354 | 355 | impl TryFrom for S::Module { 356 | type Error = Error; 357 | fn try_from(m: Module) -> Result { 358 | let rx_pdo = m 359 | .RxPdo 360 | .unwrap_or_default() 361 | .into_iter() 362 | .map(S::Pdo::try_from) 363 | .collect::>()?; 364 | 365 | let tx_pdo = m 366 | .TxPdo 367 | .unwrap_or_default() 368 | .into_iter() 369 | .map(S::Pdo::try_from) 370 | .collect::>()?; 371 | 372 | Ok(S::Module { 373 | name: names_from(m.Name)?, 374 | r#type: m.Type, 375 | rx_pdo, 376 | tx_pdo, 377 | mailbox: None, 378 | profile: None, 379 | }) 380 | } 381 | } 382 | 383 | fn names_from(names: Vec) -> Result { 384 | names 385 | .into_iter() 386 | .filter_map(|n| { 387 | let lc_id = if let Some(val) = n.LcId { 388 | match u16_from_hex_dec_value(&val) { 389 | Err(e) => return Some(Err(e)), 390 | Ok(val) => Some(val), 391 | } 392 | } else { 393 | None 394 | }; 395 | n.value.map(|name| Ok((name, lc_id))) 396 | }) 397 | .collect() 398 | } 399 | 400 | fn bool_from_str(v: &str) -> Result { 401 | match &*v.to_lowercase() { 402 | "1" | "true" => Ok(true), 403 | "0" | "false" => Ok(false), 404 | _ => Err(Error::new( 405 | ErrorKind::Other, 406 | "unknown boolean value representation", 407 | )), 408 | } 409 | } 410 | 411 | fn u32_from_hex_dec_value(v: &str) -> Result { 412 | from_hex_dec_value(v, |x| u32::from_str_radix(x, 16)) 413 | } 414 | 415 | fn u16_from_hex_dec_value(v: &str) -> Result { 416 | from_hex_dec_value(v, |x| u16::from_str_radix(x, 16)) 417 | } 418 | 419 | fn u8_from_hex_dec_value(v: &str) -> Result { 420 | from_hex_dec_value(v, |x| u8::from_str_radix(x, 16)) 421 | } 422 | 423 | fn from_hex_dec_value(v: &str, parse_hex: F) -> Result 424 | where 425 | T: FromStr, 426 | F: Fn(&str) -> std::result::Result, 427 | { 428 | let mut chars = v.chars(); 429 | match (chars.next(), chars.next(), chars.next()) { 430 | (Some('x'), _, _) | (Some('X'), _, _) => parse_hex(&v[1..]), 431 | (Some('#'), Some('x'), _) 432 | | (Some('#'), Some('X'), _) 433 | | (Some('0'), Some('x'), _) 434 | | (Some('0'), Some('X'), _) => parse_hex(&v[2..]), 435 | _ => FromStr::from_str(v), 436 | } 437 | .map_err(|e| Error::new(ErrorKind::Other, e)) 438 | } 439 | 440 | #[cfg(test)] 441 | mod tests { 442 | use super::*; 443 | 444 | #[test] 445 | fn parse_u32_from_hex_dec_values() { 446 | assert_eq!(u32_from_hex_dec_value("0").unwrap(), 0); 447 | assert_eq!(u32_from_hex_dec_value("1").unwrap(), 1); 448 | assert_eq!(u32_from_hex_dec_value("0x1").unwrap(), 0x1); 449 | assert_eq!(u32_from_hex_dec_value("0X1").unwrap(), 0x1); 450 | assert_eq!(u32_from_hex_dec_value("#x1").unwrap(), 0x1); 451 | assert_eq!(u32_from_hex_dec_value("#X1").unwrap(), 0x1); 452 | assert_eq!(u32_from_hex_dec_value("#x005").unwrap(), 0x5); 453 | assert_eq!(u32_from_hex_dec_value("xF75").unwrap(), 0xf75); 454 | assert_eq!(u32_from_hex_dec_value("XF75").unwrap(), 0xf75); 455 | } 456 | 457 | #[test] 458 | fn parse_u16() { 459 | assert_eq!(u16_from_hex_dec_value("0").unwrap(), 0); 460 | assert_eq!(u16_from_hex_dec_value("1").unwrap(), 1); 461 | assert_eq!(u16_from_hex_dec_value("0x1").unwrap(), 0x1); 462 | assert_eq!(u16_from_hex_dec_value("0X1").unwrap(), 0x1); 463 | assert_eq!(u16_from_hex_dec_value("#x1").unwrap(), 0x1); 464 | assert_eq!(u16_from_hex_dec_value("#X1").unwrap(), 0x1); 465 | assert_eq!(u16_from_hex_dec_value("#x005").unwrap(), 0x5); 466 | assert_eq!(u16_from_hex_dec_value("xF75").unwrap(), 0xf75); 467 | assert_eq!(u16_from_hex_dec_value("XF75").unwrap(), 0xf75); 468 | } 469 | 470 | #[test] 471 | fn parse_u8() { 472 | assert_eq!(u8_from_hex_dec_value("0").unwrap(), 0); 473 | assert_eq!(u8_from_hex_dec_value("1").unwrap(), 1); 474 | assert_eq!(u8_from_hex_dec_value("0x1").unwrap(), 0x1); 475 | assert_eq!(u8_from_hex_dec_value("0X1").unwrap(), 0x1); 476 | assert_eq!(u8_from_hex_dec_value("#x1").unwrap(), 0x1); 477 | assert_eq!(u8_from_hex_dec_value("#X1").unwrap(), 0x1); 478 | assert_eq!(u8_from_hex_dec_value("#x005").unwrap(), 0x5); 479 | assert_eq!(u8_from_hex_dec_value("xF7").unwrap(), 0xf7); 480 | assert_eq!(u8_from_hex_dec_value("XF7").unwrap(), 0xf7); 481 | } 482 | 483 | #[test] 484 | fn parse_bool_from_str() { 485 | assert_eq!(bool_from_str("1").unwrap(), true); 486 | assert_eq!(bool_from_str("true").unwrap(), true); 487 | assert_eq!(bool_from_str("True").unwrap(), true); 488 | assert_eq!(bool_from_str("0").unwrap(), false); 489 | assert_eq!(bool_from_str("false").unwrap(), false); 490 | assert_eq!(bool_from_str("False").unwrap(), false); 491 | assert!(bool_from_str("foo").is_err()); 492 | } 493 | } 494 | -------------------------------------------------------------------------------- /src/parser/mod.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use std::{ 3 | convert::TryInto, 4 | io::{Error, ErrorKind, Result}, 5 | }; 6 | 7 | mod conversions; 8 | 9 | #[allow(non_snake_case)] 10 | #[derive(Debug, Deserialize, PartialEq)] 11 | pub struct EtherCATInfo { 12 | Version: Option, 13 | InfoReference: Option, 14 | Vendor: Vendor, 15 | Descriptions: Option, 16 | Modules: Option, 17 | } 18 | 19 | #[allow(non_snake_case)] 20 | #[derive(Debug, Deserialize, PartialEq)] 21 | struct Vendor { 22 | FileVersion: Option, 23 | Id: String, 24 | Name: Option>, 25 | Comment: Option, 26 | URL: Option, 27 | DescriptionURL: Option, 28 | Image16x14: Option, 29 | ImageFile16x14: Option, 30 | ImageData16x14: Option, 31 | } 32 | 33 | #[allow(non_snake_case)] 34 | #[derive(Debug, Deserialize, PartialEq)] 35 | pub struct Descriptions { 36 | Groups: Option, 37 | Devices: Devices, 38 | Modules: Option, 39 | } 40 | 41 | #[allow(non_snake_case)] 42 | #[derive(Debug, Deserialize, PartialEq)] 43 | pub struct Groups { 44 | #[serde(rename = "$value")] 45 | items: Option>, 46 | } 47 | 48 | #[allow(non_snake_case)] 49 | #[derive(Debug, Deserialize, PartialEq)] 50 | pub struct Devices { 51 | #[serde(rename = "$value")] 52 | items: Option>, 53 | } 54 | 55 | #[allow(non_snake_case)] 56 | #[derive(Debug, Deserialize, PartialEq)] 57 | pub struct Modules { 58 | #[serde(rename = "$value")] 59 | items: Option>, 60 | } 61 | 62 | #[allow(non_snake_case)] 63 | #[derive(Debug, Deserialize, PartialEq)] 64 | pub struct Group { 65 | SortOrder: Option, 66 | ParentGroup: Option, 67 | #[serde(rename = "$value")] 68 | items: Vec, 69 | } 70 | 71 | #[allow(non_snake_case)] 72 | #[derive(Debug, Deserialize, PartialEq)] 73 | pub enum GroupProperty { 74 | Type(String), 75 | Name(Vec), 76 | Comment(String), 77 | Image16x14(String), 78 | ImageFile16x14(String), 79 | ImageData16x14(String), 80 | } 81 | 82 | #[allow(non_snake_case)] 83 | #[derive(Debug, Deserialize, PartialEq)] 84 | pub struct Device { 85 | Physics: Option, 86 | #[serde(rename = "$value")] 87 | items: Vec, 88 | } 89 | 90 | #[allow(non_snake_case)] 91 | #[derive(Debug, Clone, Deserialize, PartialEq)] 92 | pub struct Name { 93 | LcId: Option, 94 | #[serde(rename = "$value")] 95 | value: Option, 96 | } 97 | 98 | #[allow(non_snake_case)] 99 | #[derive(Debug, Deserialize, PartialEq)] 100 | pub enum DeviceProperty { 101 | Type(DeviceType), 102 | Name(Vec), 103 | RxPdo(Vec), 104 | TxPdo(Vec), 105 | Sm(Vec), 106 | Info { 107 | // TODO 108 | }, 109 | HideType { 110 | // TODO 111 | }, 112 | GroupType { 113 | // TODO 114 | }, 115 | URL { 116 | // TODO 117 | }, 118 | Profile { 119 | // TODO 120 | }, 121 | Eeprom { 122 | // TODO 123 | }, 124 | Fmmu { 125 | // TODO 126 | }, 127 | Image16x14(String), 128 | ImageFile16x14(String), 129 | ImageData16x14(String), 130 | Mailbox { 131 | // TODO 132 | }, 133 | Dc { 134 | // TODO 135 | }, 136 | Slots { 137 | // TODO 138 | }, 139 | Su { 140 | // TODO 141 | }, 142 | AlternativeType { 143 | // TODO 144 | }, 145 | VendorSpecific { 146 | // TODO 147 | }, 148 | SubDevice { 149 | // TODO 150 | }, 151 | ESC { 152 | // TODO 153 | }, 154 | } 155 | 156 | #[allow(non_snake_case)] 157 | #[derive(Debug, Deserialize, PartialEq)] 158 | pub struct DeviceType { 159 | ModulePdoGroup: Option, 160 | ProductCode: Option, 161 | RevisionNo: Option, 162 | #[serde(rename = "$value")] 163 | Description: String, 164 | } 165 | 166 | #[allow(non_snake_case)] 167 | #[derive(Debug, Clone, Deserialize, PartialEq)] 168 | pub struct Sm { 169 | Enable: Option, 170 | StartAddress: String, 171 | ControlByte: Option, 172 | DefaultSize: Option, 173 | Virtual: Option, 174 | } 175 | 176 | #[allow(non_snake_case)] 177 | #[derive(Debug, Clone, Deserialize, PartialEq)] 178 | pub struct Entry { 179 | Index: Index, 180 | SubIndex: Option, 181 | BitLen: usize, 182 | Name: Option>, 183 | DataType: Option, 184 | } 185 | 186 | pub type RxPdo = Pdo; 187 | pub type TxPdo = Pdo; 188 | 189 | #[allow(non_snake_case)] 190 | #[derive(Debug, Clone, Deserialize, PartialEq)] 191 | pub struct Pdo { 192 | Sm: Option, 193 | Fixed: Option, 194 | Mandatory: Option, 195 | Index: Index, 196 | Name: Vec, 197 | Entry: Option>, 198 | } 199 | 200 | #[allow(non_snake_case)] 201 | #[derive(Debug, Clone, Deserialize, PartialEq)] 202 | pub struct Index { 203 | DependOnSlot: Option, 204 | #[serde(rename = "$value")] 205 | value: String, 206 | } 207 | 208 | #[allow(non_snake_case)] 209 | #[derive(Debug, Deserialize, PartialEq)] 210 | pub struct Module { 211 | Type: String, 212 | Name: Vec, 213 | TxPdo: Option>, 214 | RxPdo: Option>, 215 | Mailbox: Option, 216 | Profile: Option, 217 | } 218 | 219 | #[allow(non_snake_case)] 220 | #[derive(Debug, Deserialize, PartialEq)] 221 | pub struct Profile { 222 | // TODO 223 | } 224 | 225 | #[allow(non_snake_case)] 226 | #[derive(Debug, Deserialize, PartialEq)] 227 | pub struct Mailbox { 228 | // TODO 229 | } 230 | 231 | #[cfg(test)] 232 | mod tests { 233 | use super::*; 234 | use serde_xml_rs::from_str; 235 | use std::{fs::File, io::prelude::*}; 236 | 237 | #[test] 238 | fn ethercat_info() { 239 | let s = r##" 240 | 241 | FooBar.xml 242 | 243 | #x00000000 244 | Vendor Foo 245 | 7D 246 | 247 | 248 | 249 | 250 | 251 | 252 | "##; 253 | let info: EtherCATInfo = from_str(s).unwrap(); 254 | 255 | assert_eq!( 256 | info, 257 | EtherCATInfo { 258 | Version: Some("1.11".to_string()), 259 | InfoReference: Some("FooBar.xml".to_string()), 260 | Vendor: Vendor { 261 | FileVersion: Some(99), 262 | Id: "#x00000000".to_string(), 263 | Name: Some(vec![Name { 264 | LcId: None, 265 | value: Some("Vendor Foo".to_string()), 266 | }]), 267 | Comment: None, 268 | URL: None, 269 | DescriptionURL: None, 270 | Image16x14: None, 271 | ImageFile16x14: None, 272 | ImageData16x14: Some("7D".to_string()), 273 | }, 274 | Descriptions: Some(Descriptions { 275 | Groups: Some(Groups { items: None }), 276 | Devices: Devices { items: None }, 277 | Modules: None, 278 | }), 279 | Modules: None, 280 | } 281 | ); 282 | } 283 | 284 | #[test] 285 | fn ethercat_info_crated_by_beckhoff() { 286 | let mut file = File::open("tests/fixtures/Beckhoff_EK11xx.xml").unwrap(); 287 | let mut xml_string = String::new(); 288 | file.read_to_string(&mut xml_string).unwrap(); 289 | let _: EtherCATInfo = from_str(&xml_string).unwrap(); 290 | } 291 | 292 | #[test] 293 | fn ethercat_info_crated_by_weidmueller() { 294 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_FBC.xml").unwrap(); 295 | let mut xml_string = String::new(); 296 | file.read_to_string(&mut xml_string).unwrap(); 297 | let _: EtherCATInfo = from_str(&xml_string).unwrap(); 298 | } 299 | 300 | #[test] 301 | fn ethercat_info_crated_by_weidmueller_module_information() { 302 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_IO.xml").unwrap(); 303 | let mut xml_string = String::new(); 304 | file.read_to_string(&mut xml_string).unwrap(); 305 | let _: EtherCATInfo = from_str(&xml_string).unwrap(); 306 | } 307 | 308 | #[test] 309 | fn ethercat_info_crated_by_igh() { 310 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_FBC_from_IgH.xml").unwrap(); 311 | let mut xml_string = String::new(); 312 | file.read_to_string(&mut xml_string).unwrap(); 313 | let _: EtherCATInfo = from_str(&xml_string).unwrap(); 314 | } 315 | 316 | #[test] 317 | fn vendor() { 318 | let s = r##" 319 | 320 | #x00000999 321 | Vendor Name 322 | Vendör Näme 323 | 7D7D7D7 324 | "##; 325 | let vendor: Vendor = from_str(s).unwrap(); 326 | 327 | assert_eq!( 328 | vendor, 329 | Vendor { 330 | FileVersion: Some(45), 331 | Id: "#x00000999".to_string(), 332 | Name: Some(vec![ 333 | Name { 334 | LcId: Some("1033".to_string()), 335 | value: Some("Vendor Name".to_string()), 336 | }, 337 | Name { 338 | LcId: Some("1049".to_string()), 339 | value: Some("Vendör Näme".to_string()), 340 | } 341 | ]), 342 | Comment: None, 343 | URL: None, 344 | DescriptionURL: None, 345 | Image16x14: None, 346 | ImageFile16x14: None, 347 | ImageData16x14: Some("7D7D7D7".to_string()), 348 | } 349 | ) 350 | } 351 | 352 | #[test] 353 | fn descriptions() { 354 | let s = r##" 355 | 356 | 357 | 358 | Coupler 359 | Coupler 360 | 44 361 | 362 | 363 | 364 | "##; 365 | let descriptions: Descriptions = from_str(s).unwrap(); 366 | assert_eq!( 367 | descriptions, 368 | Descriptions { 369 | Groups: Some(Groups { 370 | items: Some(vec![Group { 371 | SortOrder: Some(0), 372 | ParentGroup: None, 373 | items: vec![ 374 | GroupProperty::Type("Coupler".to_string()), 375 | GroupProperty::Name(vec![Name { 376 | LcId: None, 377 | value: Some("Coupler".to_string()), 378 | }]), 379 | GroupProperty::ImageData16x14("44".to_string()), 380 | ] 381 | }]), 382 | }), 383 | Devices: Devices { items: None }, 384 | Modules: None, 385 | } 386 | ); 387 | } 388 | 389 | #[test] 390 | fn entry() { 391 | let s = r##" 392 | 393 | #xf200 394 | 2 395 | 1 396 | 397 | BOOL 398 | "##; 399 | let entry: Entry = from_str(s).unwrap(); 400 | assert_eq!( 401 | entry, 402 | Entry { 403 | Index: Index { 404 | DependOnSlot: None, 405 | value: "#xf200".to_string(), 406 | }, 407 | SubIndex: Some("2".into()), 408 | BitLen: 1, 409 | Name: Some(vec![Name { 410 | LcId: None, 411 | value: None 412 | }]), 413 | DataType: Some("BOOL".to_string()), 414 | } 415 | ); 416 | } 417 | 418 | #[test] 419 | fn rx_pdo() { 420 | let s = r##" 421 | 422 | #x16ff 423 | 424 | 425 | #xf200 426 | 3 427 | 1 428 | 429 | BOOL 430 | 431 | "##; 432 | let pdo: RxPdo = from_str(s).unwrap(); 433 | assert_eq!( 434 | pdo, 435 | RxPdo { 436 | Sm: Some(2), 437 | Fixed: Some("1".to_string()), 438 | Mandatory: Some("true".to_string()), 439 | Index: Index { 440 | DependOnSlot: None, 441 | value: "#x16ff".to_string(), 442 | }, 443 | Name: vec![Name { 444 | LcId: None, 445 | value: None 446 | }], 447 | Entry: Some(vec![Entry { 448 | Index: Index { 449 | DependOnSlot: None, 450 | value: "#xf200".to_string(), 451 | }, 452 | SubIndex: Some("3".into()), 453 | BitLen: 1, 454 | Name: Some(vec![Name { 455 | LcId: None, 456 | value: None 457 | }]), 458 | DataType: Some("BOOL".to_string()), 459 | }]) 460 | } 461 | ); 462 | } 463 | 464 | #[test] 465 | fn device() { 466 | let s = r##" 467 | 468 | Foo 469 | Bar 470 | 471 | 472 | 473 | 474 | "##; 475 | let device: Device = from_str(s).unwrap(); 476 | assert_eq!( 477 | device, 478 | Device { 479 | Physics: None, 480 | items: vec![ 481 | DeviceProperty::Type(DeviceType { 482 | Description: "Foo".to_string(), 483 | ModulePdoGroup: None, 484 | ProductCode: Some("#x45".to_string()), 485 | RevisionNo: Some("#x001".to_string()), 486 | }), 487 | DeviceProperty::Name(vec![Name { 488 | LcId: None, 489 | value: Some("Bar".to_string()), 490 | }]), 491 | DeviceProperty::Sm(vec![ 492 | Sm { 493 | Enable: Some(1), 494 | StartAddress: "#x1000".to_string(), 495 | ControlByte: Some("#x26".to_string()), 496 | DefaultSize: Some("512".to_string()), 497 | Virtual: Some("1".to_string()), 498 | }, 499 | Sm { 500 | Enable: Some(1), 501 | StartAddress: "#x1400".to_string(), 502 | ControlByte: Some("#x22".to_string()), 503 | DefaultSize: Some("#x200".to_string()), 504 | Virtual: Some("0".to_string()), 505 | }, 506 | Sm { 507 | Enable: None, 508 | StartAddress: "#x1800".to_string(), 509 | ControlByte: Some("#x64".to_string()), 510 | DefaultSize: None, 511 | Virtual: Some("true".to_string()), 512 | }, 513 | Sm { 514 | Enable: Some(0), 515 | StartAddress: "#x2400".to_string(), 516 | ControlByte: None, 517 | DefaultSize: Some("0".to_string()), 518 | Virtual: None, 519 | } 520 | ]), 521 | ] 522 | } 523 | ); 524 | } 525 | } 526 | -------------------------------------------------------------------------------- /src/structs.rs: -------------------------------------------------------------------------------- 1 | pub use ethercat_types::{PdoEntryIdx, PdoIdx, SmIdx, SubIdx}; 2 | 3 | /// EtherCAT Slave Information (ESI). 4 | #[derive(Debug, Clone)] 5 | pub struct EtherCatInfo { 6 | pub version: Option, 7 | pub info_reference: Option, 8 | pub vendor: Vendor, 9 | pub description: Description, 10 | } 11 | 12 | /// Vendor information. 13 | #[derive(Debug, Clone)] 14 | pub struct Vendor { 15 | pub file_version: Option, 16 | pub id: u32, 17 | pub name: Names, 18 | pub comment: Option, 19 | pub url: Option, 20 | pub desc_url: Option, 21 | pub image: Option, 22 | } 23 | 24 | /// A collection of human readable names, with attached language IDs. 25 | pub type Names = Vec<(String, Option)>; 26 | 27 | /// Further slave descriptions. 28 | #[derive(Debug, Clone, Default)] 29 | pub struct Description { 30 | pub groups: Vec, 31 | pub devices: Vec, 32 | pub modules: Vec, 33 | } 34 | 35 | /// Image data (BMP file format). 36 | #[derive(Debug, Clone)] 37 | pub enum Image { 38 | /// Obsolete 39 | Image16x14(String), 40 | ImageFile16x14(String), 41 | ImageData16x14(HexBinary), 42 | } 43 | 44 | #[derive(Debug, Clone)] 45 | pub struct Group { 46 | pub sort_order: Option, 47 | pub parent_group: Option, 48 | pub r#type: String, 49 | pub name: Names, 50 | pub comment: Option, 51 | pub image: Option, 52 | // TODO: Optional 'VendorSpecific' 53 | } 54 | 55 | #[derive(Debug, Clone)] 56 | pub struct Device { 57 | pub physics: Option, 58 | pub name: Names, 59 | pub desc: String, 60 | pub product_code: Option, 61 | pub revision_no: Option, 62 | pub sm: Vec, 63 | pub rx_pdo: Vec, 64 | pub tx_pdo: Vec, 65 | } 66 | 67 | /// Sync Manager (SM). 68 | #[derive(Debug, Clone)] 69 | pub struct Sm { 70 | pub enable: bool, 71 | pub start_address: u16, 72 | pub control_byte: Option, 73 | pub default_size: Option, 74 | pub r#virtual: bool, 75 | } 76 | 77 | /// Process Data Object (PDO). 78 | #[derive(Debug, Clone)] 79 | pub struct Pdo { 80 | pub sm: Option, 81 | pub fixed: bool, 82 | pub mandatory: bool, 83 | pub idx: PdoIdx, 84 | pub name: Names, 85 | pub entries: Vec, 86 | } 87 | 88 | /// Service Data Object (SDO). 89 | #[derive(Debug, Clone)] 90 | pub struct Sdo { 91 | // TODO 92 | } 93 | 94 | /// PDO Entry. 95 | #[derive(Debug, Clone)] 96 | pub struct PdoEntry { 97 | pub entry_idx: PdoEntryIdx, 98 | pub bit_len: usize, 99 | pub name: Names, 100 | pub data_type: Option, 101 | } 102 | 103 | #[derive(Debug, Clone)] 104 | pub struct Module { 105 | pub r#type: String, 106 | pub name: Names, 107 | pub tx_pdo: Vec, 108 | pub rx_pdo: Vec, 109 | pub mailbox: Option, 110 | pub profile: Option, 111 | } 112 | 113 | #[derive(Debug, Clone)] 114 | pub struct Mailbox { 115 | // TODO 116 | } 117 | 118 | #[derive(Debug, Clone)] 119 | pub struct Profile { 120 | // TODO 121 | } 122 | 123 | /// HexBinary represents arbitrary hex-encoded binary data. 124 | /// 125 | /// More info: https://www.w3.org/TR/xmlschema-2/#hexBinary 126 | #[derive(Debug, Clone, PartialEq)] 127 | pub struct HexBinary(pub String); 128 | -------------------------------------------------------------------------------- /tests/fixtures/Beckhoff_EK11xx.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2 5 | Beckhoff Automation GmbH & Co. KG 6 | 424DE6000000000000007600000028000000100000000E000000010004000000000070000000120B0000120B0000100000001000000000000000000080000080000000808000800000008000800080800000C0C0C000808080000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF009D9DD99DD9DDD9DD9D9D9DD9D9DDD9DD999D9DD9D999D9999D9D9DD9D9DDD9DD9D9DD99DD999D999DDDDDDDDDDDDDDDD88888888888888888888888888888888DDDDDDDDDDDDDDDD999D999DD99DD9D99D9D9DDD9DD9D9D999DD999D9DDDD99D9D9D9DDD9DD9D99D999D999DD99DD9D9 7 | 8 | 9 | 10 | 11 | System 12 | System Terminals 13 | System Klemmen 14 | TERM_SYS 15 | 16 | 17 | SystemBk 18 | System Couplers 19 | System Koppler 20 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 21 | 22 | 23 | Customer 24 | Customer specific Terminals 25 | Kundenspezifische Klemmen 26 | TERM_CUST 27 | 28 | 29 | 30 | 31 | EK1100 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -500 43 | 44 | 45 | MII 46 | 47 | 48 | 49 | EBUS 50 | 51 | 52 | MII 53 | 54 | 55 | 56 | SystemBk 57 | 58 | 2048 59 | 0001 60 | 61 | 62 | 63 | EK1100 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -2000 72 | 73 | 74 | MII 75 | 76 | 77 | 78 | EBUS 79 | 80 | 81 | MII 82 | 83 | 84 | 85 | SystemBk 86 | 87 | 2048 88 | 0001 89 | 90 | 91 | 92 | EK1100 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -2000 101 | 102 | 103 | MII 104 | 105 | 106 | 107 | EBUS 108 | 109 | 110 | MII 111 | 112 | 113 | 114 | SystemBk 115 | 116 | 2048 117 | 0001 118 | 119 | 120 | 121 | EK1100 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -2000 130 | 131 | 132 | MII 133 | 134 | 135 | 136 | EBUS 137 | 138 | 139 | MII 140 | 141 | 142 | 143 | SystemBk 144 | 145 | 2048 146 | 000D 147 | 148 | 149 | 150 | EK1100 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -2000 160 | 161 | 162 | MII 163 | 164 | 165 | 166 | EBUS 167 | 168 | 169 | MII 170 | 171 | 172 | 173 | SystemBk 174 | 175 | 2048 176 | 000D 177 | 178 | 179 | 180 | EK1100-0008 181 | 182 | 183 | 184 | 185 | 186 | 187 | -2000 188 | 189 | 190 | MII 191 | 192 | 193 | 194 | EBUS 195 | 196 | 197 | MII 198 | 199 | 200 | 201 | SystemBk 202 | 203 | 2048 204 | 000D 205 | 206 | 207 | 208 | EK1100-0030 209 | 210 | 211 | 212 | 213 | 214 | 215 | -2000 216 | 217 | 218 | MII 219 | 220 | 221 | 222 | EBUS 223 | 224 | 225 | Customer 226 | 227 | 2048 228 | 000D 229 | 230 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 231 | 232 | 233 | EK1100-0030 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -2000 242 | 243 | 244 | MII 245 | 246 | 247 | 248 | EBUS 249 | 250 | 251 | Customer 252 | 253 | 2048 254 | 000D 255 | 256 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 257 | 258 | 259 | EK1101 260 | 261 | 262 | 263 | 264 | 265 | 266 | -2000 267 | 268 | #x1000 269 | 270 | SystemBk 271 | Inputs 272 | Inputs 273 | 274 | #x1a00 275 | ID 276 | 277 | #x6000 278 | 1 279 | 16 280 | ID 281 | UINT 282 | 283 | 284 | 285 | 2048 286 | 040100000000c000 287 | 288 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF000000C0C0C0C0C0C0000000808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 289 | 290 | 291 | EK1101 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | -2000 300 | 301 | 302 | MII 303 | 304 | 305 | 306 | EBUS 307 | 308 | 309 | MII 310 | 311 | 312 | #x1000 313 | 314 | SystemBk 315 | Inputs 316 | Inputs 317 | 318 | #x1a00 319 | ID 320 | 321 | #x6000 322 | 1 323 | 16 324 | ID 325 | UINT 326 | 327 | 328 | 329 | 2048 330 | 040D00000000c000 331 | 332 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF000000C0C0C0C0C0C0000000808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 333 | 334 | 335 | EK1101 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | -2000 345 | 346 | 347 | MII 348 | 349 | 350 | 351 | EBUS 352 | 353 | 354 | MII 355 | 356 | 357 | #x1000 358 | 359 | SystemBk 360 | Inputs 361 | Inputs 362 | 363 | #x1a00 364 | ID 365 | 366 | #x6000 367 | 1 368 | 16 369 | ID 370 | UINT 371 | 372 | 373 | 374 | 2048 375 | 040D00000000c000 376 | 377 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF000000C0C0C0C0C0C0000000808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 378 | 379 | 380 | EK1101-0008 381 | 382 | 383 | 384 | 385 | 386 | 387 | -2000 388 | 389 | 390 | MII 391 | 392 | 393 | 394 | EBUS 395 | 396 | 397 | MII 398 | 399 | 400 | #x1000 401 | 402 | SystemBk 403 | Inputs 404 | Inputs 405 | 406 | #x1a00 407 | ID 408 | 409 | #x6000 410 | 1 411 | 16 412 | ID 413 | UINT 414 | 415 | 416 | 417 | 2048 418 | 040D00000000c000 419 | 420 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF000000C0C0C0C0C0C0000000808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 421 | 422 | 423 | EK1101-0010 424 | 425 | 426 | 427 | 428 | 429 | 430 | -2000 431 | 432 | 433 | MII 434 | 435 | 436 | 437 | EBUS 438 | 439 | 440 | MII 441 | 442 | 443 | #x1000 444 | 445 | SystemBk 446 | Inputs 447 | Inputs 448 | 449 | #x1a00 450 | ID 451 | 452 | #x6000 453 | 1 454 | 16 455 | ID 456 | UINT 457 | 458 | 459 | 460 | 2048 461 | 040D00000000c000 462 | 463 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C000FFFFC0C0C000FFFF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0FF0000C0C0C0FF0000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C00000FFC0C0C00000FF808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C000BFFF00BFFFC0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0000000C0C0C0000000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF000000C0C0C0C0C0C0000000808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0000000000000C0C0C0808080C0C0C0008000C0C0C0008000808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 464 | 465 | 466 | EK1110 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 140 476 | 477 | 478 | EBUS 479 | 480 | 481 | MII 482 | 483 | 484 | 485 | System 486 | 487 | 256 488 | 0001 489 | 490 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 491 | 492 | 493 | EK1110 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 130 502 | 503 | 504 | EBUS 505 | 506 | 507 | MII 508 | 509 | 510 | 511 | System 512 | 513 | 2048 514 | 0001 515 | 516 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 517 | 518 | 519 | EK1110 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 130 529 | 530 | 531 | EBUS 532 | 533 | 534 | MII 535 | 536 | 537 | 538 | System 539 | 540 | 2048 541 | 0001 542 | 543 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 544 | 545 | 546 | EK1110-0008 547 | 548 | 549 | 550 | 551 | 552 | 553 | 130 554 | 555 | 556 | EBUS 557 | 558 | 559 | MII 560 | 561 | 562 | 563 | System 564 | 565 | 2048 566 | 0001 567 | 568 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 569 | 570 | 571 | EK1110-0043 572 | 573 | 574 | 575 | 576 | 577 | 578 | 50 579 | 580 | 581 | EBUS 582 | 583 | 584 | EBUS 585 | 586 | 587 | 588 | System 589 | 590 | 2048 591 | 0001004401 592 | 593 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 594 | 595 | 596 | EK1110-0044 597 | 598 | 599 | 600 | 601 | 602 | 603 | 140 604 | 605 | 606 | EBUS 607 | 608 | 609 | EBUS 610 | 611 | 612 | 613 | NONE 614 | 615 | 616 | MII 617 | 618 | 619 | 620 | System 621 | 622 | 2048 623 | 0781014401 624 | 625 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000C40E0000C40E00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FF 626 | 627 | 628 | EK1121-0010 629 | 630 | 631 | 632 | 633 | 634 | 635 | 170 636 | 637 | 638 | EBUS 639 | 641 | 642 | NONE 643 | 644 | 645 | EBUS 646 | 647 | 648 | MII 649 | 650 | 651 | 652 | System 653 | 654 | 2048 655 | 000D 656 | 657 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0BBC2BBC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0BAC2BA0BFC0BC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF 658 | 659 | 660 | EK1122 661 | 662 | 663 | 664 | 665 | 666 | 667 | 220 668 | 669 | 670 | EBUS 671 | 672 | 673 | MII 674 | 675 | 676 | 677 | EBUS 678 | 679 | 680 | MII 681 | 682 | 683 | 684 | System 685 | 686 | 2048 687 | 0001 688 | 689 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0BBC2BBC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0BAC2BA0BFC0BC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF 690 | 691 | 692 | EK1122 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 220 701 | 702 | 703 | EBUS 704 | 705 | 706 | MII 707 | 708 | 709 | 710 | EBUS 711 | 712 | 713 | MII 714 | 715 | 716 | 717 | System 718 | 719 | 2048 720 | 000D 721 | 722 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0BBC2BBC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0BAC2BA0BFC0BC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF 723 | 724 | 725 | EK1122 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 220 735 | 736 | 737 | EBUS 738 | 739 | 740 | MII 741 | 742 | 743 | 744 | EBUS 745 | 746 | 747 | MII 748 | 749 | 750 | 751 | System 752 | 753 | 2048 754 | 000D 755 | 756 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0BBC2BBC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0BAC2BA0BFC0BC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF 757 | 758 | 759 | EK1122-0008 760 | 761 | 762 | 763 | 764 | 765 | 766 | 220 767 | 768 | 769 | EBUS 770 | 771 | 772 | MII 773 | 774 | 775 | 776 | EBUS 777 | 778 | 779 | MII 780 | 781 | 782 | 783 | System 784 | 785 | 2048 786 | 000D 787 | 788 | 424DD6020000000000003600000028000000100000000E0000000100180000000000A0020000120B0000120B00000000000000000000FF00FFFF00FFFF00FFFF00FFFF00FFFF00FF808080808080808080808080808080808080808080808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C080808080808080808000BFFF00BFFF00BFFF00BFFF00BFFF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0808080808080808080C0C0C0C0C0C080808000BFFFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0BBC2BBC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0BAC2BA0BFC0BC0C0C0C0C0C0C0C0C0808080FF00FFFF00FF007FFF007FFF007FFF007FFF007FFF007FFFC0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0808080FF00FFFF00FF 789 | 790 | 791 | 792 | 793 | -------------------------------------------------------------------------------- /tests/fixtures/Weidmueller_UR20_FBC_from_IgH.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 560 6 | 7 | 8 | 9 | 10 | UR20-FBC-EC 11 | 12 | 13 | 14 | 15 | 16 | 17 | #x16ff 18 | 19 | 20 | #xf200 21 | 1 22 | 1 23 | 24 | BOOL 25 | 26 | 27 | #xf200 28 | 2 29 | 1 30 | 31 | BOOL 32 | 33 | 34 | #xf200 35 | 3 36 | 1 37 | 38 | BOOL 39 | 40 | 41 | #xf200 42 | 4 43 | 1 44 | 45 | BOOL 46 | 47 | 48 | #xf200 49 | 5 50 | 1 51 | 52 | BOOL 53 | 54 | 55 | #xf200 56 | 6 57 | 1 58 | 59 | BOOL 60 | 61 | 62 | #xf200 63 | 7 64 | 1 65 | 66 | BOOL 67 | 68 | 69 | #xf200 70 | 8 71 | 1 72 | 73 | BOOL 74 | 75 | 76 | #xf200 77 | 9 78 | 1 79 | 80 | BOOL 81 | 82 | 83 | #xf200 84 | 10 85 | 1 86 | 87 | BOOL 88 | 89 | 90 | #xf200 91 | 11 92 | 1 93 | 94 | BOOL 95 | 96 | 97 | #xf200 98 | 12 99 | 1 100 | 101 | BOOL 102 | 103 | 104 | #xf200 105 | 13 106 | 1 107 | 108 | BOOL 109 | 110 | 111 | #xf200 112 | 14 113 | 1 114 | 115 | BOOL 116 | 117 | 118 | #xf200 119 | 15 120 | 1 121 | 122 | BOOL 123 | 124 | 125 | #xf200 126 | 16 127 | 1 128 | 129 | BOOL 130 | 131 | 132 | 133 | #x1600 134 | 135 | 136 | #x7000 137 | 1 138 | 32 139 | 140 | UINT32 141 | 142 | 143 | #x7000 144 | 2 145 | 32 146 | 147 | UINT32 148 | 149 | 150 | #x7000 151 | 3 152 | 16 153 | 154 | UINT16 155 | 156 | 157 | #x7000 158 | 4 159 | 16 160 | 161 | UINT16 162 | 163 | 164 | 165 | #x1601 166 | 167 | 168 | #x7010 169 | 1 170 | 32 171 | 172 | UINT32 173 | 174 | 175 | #x7010 176 | 2 177 | 32 178 | 179 | UINT32 180 | 181 | 182 | #x7010 183 | 3 184 | 16 185 | 186 | UINT16 187 | 188 | 189 | #x7010 190 | 4 191 | 16 192 | 193 | UINT16 194 | 195 | 196 | 197 | #x1602 198 | 199 | 200 | #x7020 201 | 1 202 | 1 203 | 204 | BOOL 205 | 206 | 207 | #x7020 208 | 2 209 | 1 210 | 211 | BOOL 212 | 213 | 214 | #x7020 215 | 3 216 | 1 217 | 218 | BOOL 219 | 220 | 221 | #x7020 222 | 4 223 | 1 224 | 225 | BOOL 226 | 227 | 228 | #x0000 229 | 4 230 | 231 | 232 | 233 | #x1603 234 | 235 | 236 | #x7030 237 | 1 238 | 1 239 | 240 | BOOL 241 | 242 | 243 | #x7030 244 | 2 245 | 1 246 | 247 | BOOL 248 | 249 | 250 | #x7030 251 | 3 252 | 1 253 | 254 | BOOL 255 | 256 | 257 | #x7030 258 | 4 259 | 1 260 | 261 | BOOL 262 | 263 | 264 | #x7030 265 | 5 266 | 1 267 | 268 | BOOL 269 | 270 | 271 | #x7030 272 | 6 273 | 1 274 | 275 | BOOL 276 | 277 | 278 | #x7030 279 | 7 280 | 1 281 | 282 | BOOL 283 | 284 | 285 | #x7030 286 | 8 287 | 1 288 | 289 | BOOL 290 | 291 | 292 | #x7030 293 | 9 294 | 1 295 | 296 | BOOL 297 | 298 | 299 | #x7030 300 | 10 301 | 1 302 | 303 | BOOL 304 | 305 | 306 | #x7030 307 | 11 308 | 1 309 | 310 | BOOL 311 | 312 | 313 | #x7030 314 | 12 315 | 1 316 | 317 | BOOL 318 | 319 | 320 | #x7030 321 | 13 322 | 1 323 | 324 | BOOL 325 | 326 | 327 | #x7030 328 | 14 329 | 1 330 | 331 | BOOL 332 | 333 | 334 | #x7030 335 | 15 336 | 1 337 | 338 | BOOL 339 | 340 | 341 | #x7030 342 | 16 343 | 1 344 | 345 | BOOL 346 | 347 | 348 | 349 | #x1aff 350 | 351 | 352 | #xf100 353 | 1 354 | 1 355 | 356 | BOOL 357 | 358 | 359 | #xf100 360 | 2 361 | 1 362 | 363 | BOOL 364 | 365 | 366 | #xf100 367 | 3 368 | 1 369 | 370 | BOOL 371 | 372 | 373 | #xf100 374 | 4 375 | 1 376 | 377 | BOOL 378 | 379 | 380 | #xf100 381 | 5 382 | 1 383 | 384 | BOOL 385 | 386 | 387 | #xf100 388 | 6 389 | 1 390 | 391 | BOOL 392 | 393 | 394 | #xf100 395 | 7 396 | 1 397 | 398 | BOOL 399 | 400 | 401 | #xf100 402 | 8 403 | 1 404 | 405 | BOOL 406 | 407 | 408 | #xf100 409 | 9 410 | 1 411 | 412 | BOOL 413 | 414 | 415 | #xf100 416 | 10 417 | 1 418 | 419 | BOOL 420 | 421 | 422 | #xf100 423 | 11 424 | 1 425 | 426 | BOOL 427 | 428 | 429 | #xf100 430 | 12 431 | 1 432 | 433 | BOOL 434 | 435 | 436 | #xf100 437 | 13 438 | 1 439 | 440 | BOOL 441 | 442 | 443 | #xf100 444 | 14 445 | 1 446 | 447 | BOOL 448 | 449 | 450 | #xf100 451 | 15 452 | 1 453 | 454 | BOOL 455 | 456 | 457 | #xf100 458 | 16 459 | 1 460 | 461 | BOOL 462 | 463 | 464 | 465 | #x1a00 466 | 467 | 468 | #x6000 469 | 1 470 | 32 471 | 472 | UINT32 473 | 474 | 475 | #x6000 476 | 2 477 | 32 478 | 479 | UINT32 480 | 481 | 482 | #x6000 483 | 3 484 | 32 485 | 486 | UINT32 487 | 488 | 489 | #x6000 490 | 4 491 | 32 492 | 493 | UINT32 494 | 495 | 496 | #x6000 497 | 5 498 | 16 499 | 500 | UINT16 501 | 502 | 503 | #x6000 504 | 6 505 | 16 506 | 507 | UINT16 508 | 509 | 510 | #x6000 511 | 7 512 | 8 513 | 514 | UINT8 515 | 516 | 517 | 518 | #x1a01 519 | 520 | 521 | #x6010 522 | 1 523 | 32 524 | 525 | UINT32 526 | 527 | 528 | #x6010 529 | 2 530 | 32 531 | 532 | UINT32 533 | 534 | 535 | #x6010 536 | 3 537 | 32 538 | 539 | UINT32 540 | 541 | 542 | #x6010 543 | 4 544 | 32 545 | 546 | UINT32 547 | 548 | 549 | #x6010 550 | 5 551 | 16 552 | 553 | UINT16 554 | 555 | 556 | #x6010 557 | 6 558 | 16 559 | 560 | UINT16 561 | 562 | 563 | #x6010 564 | 7 565 | 8 566 | 567 | UINT8 568 | 569 | 570 | 571 | #x1a02 572 | 573 | 574 | #x6020 575 | 1 576 | 8 577 | 578 | UINT8 579 | 580 | 581 | 582 | #x1a03 583 | 584 | 585 | #x6030 586 | 1 587 | 8 588 | 589 | UINT8 590 | 591 | 592 | 593 | 594 | 595 | 596 | -------------------------------------------------------------------------------- /tests/parse-xml.rs: -------------------------------------------------------------------------------- 1 | use ethercat_esi::EtherCatInfo; 2 | use ethercat_types as ec; 3 | use std::{fs::File, io::prelude::*}; 4 | 5 | #[test] 6 | fn parse_xml_crated_by_weidmueller() { 7 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_FBC.xml").unwrap(); 8 | let mut xml_string = String::new(); 9 | file.read_to_string(&mut xml_string).unwrap(); 10 | let esi = EtherCatInfo::from_xml_str(&xml_string).unwrap(); 11 | assert_eq!(esi.vendor.id, 0x0000_0230); 12 | assert_eq!(esi.description.devices.len(), 2); 13 | let dev_0 = &esi.description.devices[0]; 14 | let dev_1 = &esi.description.devices[1]; 15 | assert_eq!(dev_0.product_code, Some(0x4F911C30)); 16 | assert_eq!(dev_1.product_code, Some(0x4F911C30)); 17 | assert_eq!(dev_0.revision_no, Some(0x1)); 18 | assert_eq!(dev_1.revision_no, Some(0x00011100)); 19 | assert_eq!(dev_0.sm[0].start_address, 0x1000); 20 | assert_eq!(dev_0.sm[0].control_byte, Some(0x26)); 21 | assert_eq!(dev_0.rx_pdo[0].idx, ec::PdoIdx::from(0x16FF)); 22 | assert_eq!( 23 | dev_0.rx_pdo[0].entries[0].entry_idx.idx, 24 | ec::Idx::from(0xF200) 25 | ); 26 | assert_eq!( 27 | dev_0.rx_pdo[0].entries[0].entry_idx.sub_idx, 28 | ec::SubIdx::from(1) 29 | ); 30 | } 31 | 32 | #[test] 33 | fn parse_xml_crated_by_weidmueller_module_information() { 34 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_IO.xml").unwrap(); 35 | let mut xml_string = String::new(); 36 | file.read_to_string(&mut xml_string).unwrap(); 37 | let esi = EtherCatInfo::from_xml_str(&xml_string).unwrap(); 38 | assert_eq!(esi.vendor.id, 0x0000_0230); 39 | assert_eq!(esi.description.modules.len(), 82); 40 | let m = &esi.description.modules[0]; 41 | assert_eq!(m.tx_pdo[0].entries.len(), 6); 42 | } 43 | 44 | #[test] 45 | fn parse_xml_crated_by_beckhoff() { 46 | let mut file = File::open("tests/fixtures/Beckhoff_EK11xx.xml").unwrap(); 47 | let mut xml_string = String::new(); 48 | file.read_to_string(&mut xml_string).unwrap(); 49 | let esi = EtherCatInfo::from_xml_str(&xml_string).unwrap(); 50 | assert_eq!(esi.vendor.id, 2); 51 | assert_eq!(esi.description.devices.len(), 24); 52 | } 53 | 54 | #[test] 55 | fn parse_xml_crated_by_igh() { 56 | // Parse file that was crated by `/opt/etherlab/bin/ethercat xml` 57 | let mut file = File::open("tests/fixtures/Weidmueller_UR20_FBC_from_IgH.xml").unwrap(); 58 | let mut xml_string = String::new(); 59 | file.read_to_string(&mut xml_string).unwrap(); 60 | let esi = EtherCatInfo::from_xml_str(&xml_string).unwrap(); 61 | assert_eq!(esi.vendor.id, 0x230); 62 | } 63 | --------------------------------------------------------------------------------